From 16c7b3a39018ab41ddd979bf7c6104c244345faf Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 25 Sep 2019 16:20:42 +0100 Subject: [PATCH 001/344] Added Registry TTL to memory registry. Tracking node lifetimes. --- registry/handler/handler.go | 10 +++- registry/memory/memory.go | 114 +++++++++++++++++++++++++++++++----- registry/service/service.go | 7 ++- 3 files changed, 114 insertions(+), 17 deletions(-) diff --git a/registry/handler/handler.go b/registry/handler/handler.go index f86148cd..5c7fd5c9 100644 --- a/registry/handler/handler.go +++ b/registry/handler/handler.go @@ -2,6 +2,7 @@ package handler import ( "context" + "time" "github.com/micro/go-micro/errors" "github.com/micro/go-micro/registry" @@ -26,10 +27,17 @@ func (r *Registry) GetService(ctx context.Context, req *pb.GetRequest, rsp *pb.G } func (r *Registry) Register(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error { - err := r.Registry.Register(service.ToService(req)) + var regOpts []registry.RegisterOption + regTTL, ok := ctx.Value("register_ttl").(time.Duration) + if ok { + regOpts = append(regOpts, registry.RegisterTTL(regTTL)) + } + + err := r.Registry.Register(service.ToService(req), regOpts...) if err != nil { return errors.InternalServerError("go.micro.registry", err.Error()) } + return nil } diff --git a/registry/memory/memory.go b/registry/memory/memory.go index 446aa0f0..c9e8b353 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -8,17 +8,25 @@ import ( "github.com/google/uuid" "github.com/micro/go-micro/registry" + "github.com/micro/go-micro/util/log" ) var ( timeout = time.Millisecond * 10 ) +// node tracks node registration timestamp and TTL +type node struct { + ts time.Time + ttl time.Duration +} + type Registry struct { options registry.Options sync.RWMutex Services map[string][]*registry.Service + nodes map[string]*node Watchers map[string]*Watcher } @@ -39,6 +47,7 @@ func NewRegistry(opts ...registry.Option) registry.Registry { return &Registry{ options: options, Services: services, + nodes: make(map[string]*node), Watchers: make(map[string]*Watcher), } } @@ -111,30 +120,73 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption m.Lock() defer m.Unlock() + var options registry.RegisterOptions + for _, o := range opts { + o(&options) + } + if service, ok := m.Services[s.Name]; !ok { m.Services[s.Name] = []*registry.Service{s} - go m.sendEvent(®istry.Result{Action: "update", Service: s}) - } else { - svcCount := len(service) - svcNodeCounts := make(map[string]map[string]int) - for _, s := range service { - if _, ok := svcNodeCounts[s.Name]; !ok { - svcNodeCounts[s.Name] = make(map[string]int) - } - if _, ok := svcNodeCounts[s.Name][s.Version]; !ok { - svcNodeCounts[s.Name][s.Version] = len(s.Nodes) + // add all nodes into nodes map to track their TTL + for _, n := range s.Nodes { + log.Logf("Tracking node %s for service %s", n.Id, s.Name) + m.nodes[s.Name+n.Id] = &node{ + ts: time.Now(), + ttl: options.TTL, } } - // if merged count and original service counts changed we added new version of the service + go m.sendEvent(®istry.Result{Action: "update", Service: s}) + } else { + // svcCount essentially keep the count of all service vesions + svcCount := len(service) + // svcNodes maintains a list of node Ids per particular service version + svcNodes := make(map[string]map[string][]string) + // collect all service ids for all service versions + for _, s := range service { + if _, ok := svcNodes[s.Name]; !ok { + svcNodes[s.Name] = make(map[string][]string) + } + if _, ok := svcNodes[s.Name][s.Version]; !ok { + for _, n := range s.Nodes { + svcNodes[s.Name][s.Version] = append(svcNodes[s.Name][s.Version], n.Id) + } + } + } + // if merged count and original service counts changed we know we are adding a new version of the service merged := registry.Merge(service, []*registry.Service{s}) if len(merged) != svcCount { m.Services[s.Name] = merged + // we know s is the new [version of] service; we need to strart tracking its nodes + for _, n := range s.Nodes { + log.Logf("Tracking node %s for service %s", n.Id, s.Name) + m.nodes[s.Name+n.Id] = &node{ + ts: time.Now(), + ttl: options.TTL, + } + } go m.sendEvent(®istry.Result{Action: "update", Service: s}) return nil } - // if the node count for a particular service has changed we added a new node to the service + // if the node count of any particular service [version] changed we know we are adding a new node to the service for _, s := range merged { - if len(s.Nodes) != svcNodeCounts[s.Name][s.Version] { + // we know that if the node counts have changed we need to track new nodes + if len(s.Nodes) != len(svcNodes[s.Name][s.Version]) { + for _, n := range s.Nodes { + var found bool + for _, id := range svcNodes[s.Name][s.Version] { + if n.Id == id { + found = true + break + } + } + if !found { + log.Logf("Tracking node %s for service %s", n.Id, s.Name) + m.nodes[s.Name+n.Id] = &node{ + ts: time.Now(), + ttl: options.TTL, + } + } + } m.Services[s.Name] = merged go m.sendEvent(®istry.Result{Action: "update", Service: s}) return nil @@ -150,12 +202,44 @@ func (m *Registry) Deregister(s *registry.Service) error { defer m.Unlock() if service, ok := m.Services[s.Name]; ok { - go m.sendEvent(®istry.Result{Action: "delete", Service: s}) + // svcNodes maintains a list of node Ids per particular service version + svcNodes := make(map[string]map[string][]string) + // collect all service ids for all service versions + for _, s := range service { + if _, ok := svcNodes[s.Name]; !ok { + svcNodes[s.Name] = make(map[string][]string) + } + if _, ok := svcNodes[s.Name][s.Version]; !ok { + for _, n := range s.Nodes { + svcNodes[s.Name][s.Version] = append(svcNodes[s.Name][s.Version], n.Id) + } + } + } if service := registry.Remove(service, []*registry.Service{s}); len(service) == 0 { + id := svcNodes[s.Name][s.Version][0] + log.Logf("Stopped tracking node %s for service %s", id, s.Name) + delete(m.nodes, s.Name+id) delete(m.Services, s.Name) } else { - m.Services[s.Name] = service + // find out which nodes have been removed + for _, id := range svcNodes[s.Name][s.Version] { + for _, s := range service { + var found bool + for _, n := range s.Nodes { + if id == n.Id { + found = true + break + } + } + if !found { + log.Logf("Stopped tracking node %s for service %s", id, s.Name) + delete(m.nodes, s.Name+id) + } + } + m.Services[s.Name] = service + } } + go m.sendEvent(®istry.Result{Action: "delete", Service: s}) } return nil diff --git a/registry/service/service.go b/registry/service/service.go index 4af5ab40..9585c242 100644 --- a/registry/service/service.go +++ b/registry/service/service.go @@ -58,8 +58,13 @@ func (s *serviceRegistry) Register(srv *registry.Service, opts ...registry.Regis o(&options) } + ctx := context.Background() + if options.TTL.Nanoseconds() != 0.0 { + ctx = context.WithValue(ctx, "register_ttl", options.TTL) + } + // register the service - _, err := s.client.Register(context.TODO(), ToProto(srv), s.callOpts()...) + _, err := s.client.Register(ctx, ToProto(srv), s.callOpts()...) if err != nil { return err } From 27bd9581bfc4809784dabe401369a73f85c17be8 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 25 Sep 2019 18:19:18 +0100 Subject: [PATCH 002/344] Refresh TTL; prune expired nodes. --- registry/memory/memory.go | 104 ++++++++++++++++++++++++++++++++------ 1 file changed, 88 insertions(+), 16 deletions(-) diff --git a/registry/memory/memory.go b/registry/memory/memory.go index c9e8b353..f7134bf2 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -3,6 +3,7 @@ package memory import ( "context" + "strings" "sync" "time" @@ -12,13 +13,15 @@ import ( ) var ( - timeout = time.Millisecond * 10 + sendEventTime = 10 * time.Millisecond + ttlPruneTime = 1 * time.Minute + DefaultTTL = 1 * time.Minute ) // node tracks node registration timestamp and TTL type node struct { - ts time.Time - ttl time.Duration + lastSeen time.Time + ttl time.Duration } type Registry struct { @@ -44,12 +47,67 @@ func NewRegistry(opts ...registry.Option) registry.Registry { services = make(map[string][]*registry.Service) } - return &Registry{ + reg := &Registry{ options: options, Services: services, nodes: make(map[string]*node), Watchers: make(map[string]*Watcher), } + + go reg.ttlPrune() + + return reg +} + +// nodeTrackId returns a string we use to track a node of a given service +func nodeTrackId(svcName, svcVersion, nodeId string) string { + return svcName + "+" + svcVersion + "+" + nodeId +} + +func (m *Registry) ttlPrune() { + prune := time.NewTicker(ttlPruneTime) + defer prune.Stop() + + for { + select { + case <-prune.C: + m.Lock() + for nodeTrackId, node := range m.nodes { + // if we exceed the TTL threshold we need to stop tracking the node + if time.Since(node.lastSeen) > node.ttl { + // split nodeTrackID into service Name, Version and Node Id + trackIdSplit := strings.Split(nodeTrackId, "+") + svcName, svcVersion, nodeId := trackIdSplit[0], trackIdSplit[1], trackIdSplit[2] + log.Logf("TTL threshold reached for node %s for service %s", nodeId, svcName) + // we need to find a node that expired and delete it from service nodes + if _, ok := m.Services[svcName]; ok { + for _, service := range m.Services[svcName] { + if service.Version != svcVersion { + continue + } + // find expired service node and delete it + var nodes []*registry.Node + for _, n := range service.Nodes { + var del bool + if n.Id == nodeId { + del = true + } + if !del { + nodes = append(nodes, n) + } + } + service.Nodes = nodes + } + } + // stop tracking the node + delete(m.nodes, nodeTrackId) + } + } + m.Unlock() + } + } + + return } func (m *Registry) sendEvent(r *registry.Result) { @@ -70,7 +128,7 @@ func (m *Registry) sendEvent(r *registry.Result) { default: select { case w.res <- r: - case <-time.After(timeout): + case <-time.After(sendEventTime): } } } @@ -125,14 +183,19 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption o(&options) } + // if no TTL has been set, set it to DefaultTTL + if options.TTL.Seconds() == 0.0 { + options.TTL = DefaultTTL + } + if service, ok := m.Services[s.Name]; !ok { m.Services[s.Name] = []*registry.Service{s} // add all nodes into nodes map to track their TTL for _, n := range s.Nodes { log.Logf("Tracking node %s for service %s", n.Id, s.Name) - m.nodes[s.Name+n.Id] = &node{ - ts: time.Now(), - ttl: options.TTL, + m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ + lastSeen: time.Now(), + ttl: options.TTL, } } go m.sendEvent(®istry.Result{Action: "update", Service: s}) @@ -159,9 +222,9 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption // we know s is the new [version of] service; we need to strart tracking its nodes for _, n := range s.Nodes { log.Logf("Tracking node %s for service %s", n.Id, s.Name) - m.nodes[s.Name+n.Id] = &node{ - ts: time.Now(), - ttl: options.TTL, + m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ + lastSeen: time.Now(), + ttl: options.TTL, } } go m.sendEvent(®istry.Result{Action: "update", Service: s}) @@ -181,9 +244,9 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption } if !found { log.Logf("Tracking node %s for service %s", n.Id, s.Name) - m.nodes[s.Name+n.Id] = &node{ - ts: time.Now(), - ttl: options.TTL, + m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ + lastSeen: time.Now(), + ttl: options.TTL, } } } @@ -191,6 +254,15 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption go m.sendEvent(®istry.Result{Action: "update", Service: s}) return nil } + // refresh the timestamp and TTL of the service node + for _, n := range s.Nodes { + trackId := nodeTrackId(s.Name, s.Version, n.Id) + log.Logf("Refreshing TTL for node %s for service %s", n.Id, s.Name) + if trackedNode, ok := m.nodes[trackId]; ok { + trackedNode.lastSeen = time.Now() + trackedNode.ttl = options.TTL + } + } } } @@ -218,7 +290,7 @@ func (m *Registry) Deregister(s *registry.Service) error { if service := registry.Remove(service, []*registry.Service{s}); len(service) == 0 { id := svcNodes[s.Name][s.Version][0] log.Logf("Stopped tracking node %s for service %s", id, s.Name) - delete(m.nodes, s.Name+id) + delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) delete(m.Services, s.Name) } else { // find out which nodes have been removed @@ -233,7 +305,7 @@ func (m *Registry) Deregister(s *registry.Service) error { } if !found { log.Logf("Stopped tracking node %s for service %s", id, s.Name) - delete(m.nodes, s.Name+id) + delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) } } m.Services[s.Name] = service From e973bfaa2571f3d1487f82586301203bf4e655fa Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 27 Sep 2019 11:25:06 +0100 Subject: [PATCH 003/344] Add TTL options to memory registry. --- registry/handler/handler.go | 6 +- registry/proto/registry.pb.go | 149 +++++++++++++++++++++++----------- registry/proto/registry.proto | 6 ++ 3 files changed, 108 insertions(+), 53 deletions(-) diff --git a/registry/handler/handler.go b/registry/handler/handler.go index 5c7fd5c9..e828ecdb 100644 --- a/registry/handler/handler.go +++ b/registry/handler/handler.go @@ -28,10 +28,8 @@ func (r *Registry) GetService(ctx context.Context, req *pb.GetRequest, rsp *pb.G func (r *Registry) Register(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error { var regOpts []registry.RegisterOption - regTTL, ok := ctx.Value("register_ttl").(time.Duration) - if ok { - regOpts = append(regOpts, registry.RegisterTTL(regTTL)) - } + ttl := time.Duration(req.Options.Ttl) + regOpts = append(regOpts, registry.RegisterTTL(ttl)) err := r.Registry.Register(service.ToService(req), regOpts...) if err != nil { diff --git a/registry/proto/registry.pb.go b/registry/proto/registry.pb.go index 9c62a1fb..c6862d59 100644 --- a/registry/proto/registry.pb.go +++ b/registry/proto/registry.pb.go @@ -56,6 +56,7 @@ type Service struct { Metadata map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Endpoints []*Endpoint `protobuf:"bytes,4,rep,name=endpoints,proto3" json:"endpoints,omitempty"` Nodes []*Node `protobuf:"bytes,5,rep,name=nodes,proto3" json:"nodes,omitempty"` + Options *Options `protobuf:"bytes,6,opt,name=options,proto3" json:"options,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -121,6 +122,13 @@ func (m *Service) GetNodes() []*Node { return nil } +func (m *Service) GetOptions() *Options { + if m != nil { + return m.Options + } + return nil +} + // Node represents the node the service is on type Node struct { Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` @@ -305,6 +313,46 @@ func (m *Value) GetValues() []*Value { return nil } +// Options are registry options +type Options struct { + Ttl int64 `protobuf:"varint,1,opt,name=ttl,proto3" json:"ttl,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Options) Reset() { *m = Options{} } +func (m *Options) String() string { return proto.CompactTextString(m) } +func (*Options) ProtoMessage() {} +func (*Options) Descriptor() ([]byte, []int) { + return fileDescriptor_41af05d40a615591, []int{4} +} + +func (m *Options) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Options.Unmarshal(m, b) +} +func (m *Options) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Options.Marshal(b, m, deterministic) +} +func (m *Options) XXX_Merge(src proto.Message) { + xxx_messageInfo_Options.Merge(m, src) +} +func (m *Options) XXX_Size() int { + return xxx_messageInfo_Options.Size(m) +} +func (m *Options) XXX_DiscardUnknown() { + xxx_messageInfo_Options.DiscardUnknown(m) +} + +var xxx_messageInfo_Options proto.InternalMessageInfo + +func (m *Options) GetTtl() int64 { + if m != nil { + return m.Ttl + } + return 0 +} + // Result is returns by the watcher type Result struct { Action string `protobuf:"bytes,1,opt,name=action,proto3" json:"action,omitempty"` @@ -319,7 +367,7 @@ func (m *Result) Reset() { *m = Result{} } func (m *Result) String() string { return proto.CompactTextString(m) } func (*Result) ProtoMessage() {} func (*Result) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{4} + return fileDescriptor_41af05d40a615591, []int{5} } func (m *Result) XXX_Unmarshal(b []byte) error { @@ -371,7 +419,7 @@ func (m *EmptyResponse) Reset() { *m = EmptyResponse{} } func (m *EmptyResponse) String() string { return proto.CompactTextString(m) } func (*EmptyResponse) ProtoMessage() {} func (*EmptyResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{5} + return fileDescriptor_41af05d40a615591, []int{6} } func (m *EmptyResponse) XXX_Unmarshal(b []byte) error { @@ -403,7 +451,7 @@ func (m *GetRequest) Reset() { *m = GetRequest{} } func (m *GetRequest) String() string { return proto.CompactTextString(m) } func (*GetRequest) ProtoMessage() {} func (*GetRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{6} + return fileDescriptor_41af05d40a615591, []int{7} } func (m *GetRequest) XXX_Unmarshal(b []byte) error { @@ -442,7 +490,7 @@ func (m *GetResponse) Reset() { *m = GetResponse{} } func (m *GetResponse) String() string { return proto.CompactTextString(m) } func (*GetResponse) ProtoMessage() {} func (*GetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{7} + return fileDescriptor_41af05d40a615591, []int{8} } func (m *GetResponse) XXX_Unmarshal(b []byte) error { @@ -480,7 +528,7 @@ func (m *ListRequest) Reset() { *m = ListRequest{} } func (m *ListRequest) String() string { return proto.CompactTextString(m) } func (*ListRequest) ProtoMessage() {} func (*ListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{8} + return fileDescriptor_41af05d40a615591, []int{9} } func (m *ListRequest) XXX_Unmarshal(b []byte) error { @@ -512,7 +560,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} } func (m *ListResponse) String() string { return proto.CompactTextString(m) } func (*ListResponse) ProtoMessage() {} func (*ListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{9} + return fileDescriptor_41af05d40a615591, []int{10} } func (m *ListResponse) XXX_Unmarshal(b []byte) error { @@ -552,7 +600,7 @@ func (m *WatchRequest) Reset() { *m = WatchRequest{} } func (m *WatchRequest) String() string { return proto.CompactTextString(m) } func (*WatchRequest) ProtoMessage() {} func (*WatchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{10} + return fileDescriptor_41af05d40a615591, []int{11} } func (m *WatchRequest) XXX_Unmarshal(b []byte) error { @@ -599,7 +647,7 @@ func (m *Event) Reset() { *m = Event{} } func (m *Event) String() string { return proto.CompactTextString(m) } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{11} + return fileDescriptor_41af05d40a615591, []int{12} } func (m *Event) XXX_Unmarshal(b []byte) error { @@ -657,6 +705,7 @@ func init() { proto.RegisterType((*Endpoint)(nil), "go.micro.registry.Endpoint") proto.RegisterMapType((map[string]string)(nil), "go.micro.registry.Endpoint.MetadataEntry") proto.RegisterType((*Value)(nil), "go.micro.registry.Value") + proto.RegisterType((*Options)(nil), "go.micro.registry.Options") proto.RegisterType((*Result)(nil), "go.micro.registry.Result") proto.RegisterType((*EmptyResponse)(nil), "go.micro.registry.EmptyResponse") proto.RegisterType((*GetRequest)(nil), "go.micro.registry.GetRequest") @@ -670,45 +719,47 @@ func init() { func init() { proto.RegisterFile("registry.proto", fileDescriptor_41af05d40a615591) } var fileDescriptor_41af05d40a615591 = []byte{ - // 632 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xdb, 0x6e, 0xd3, 0x4c, - 0x10, 0x8e, 0xed, 0x38, 0x87, 0x49, 0xdb, 0xbf, 0xff, 0x08, 0x81, 0x31, 0x05, 0x22, 0x4b, 0xa0, - 0x80, 0x84, 0xa9, 0x42, 0x85, 0x38, 0x5c, 0x21, 0x62, 0x2a, 0xa1, 0x16, 0x09, 0x73, 0xba, 0x36, - 0xf1, 0xa8, 0x58, 0xc4, 0x07, 0x76, 0x37, 0x91, 0xfc, 0x0e, 0x48, 0x3c, 0x01, 0x77, 0x3c, 0x0a, - 0x0f, 0x86, 0xbc, 0x5e, 0x27, 0xa9, 0x62, 0x07, 0xa4, 0xc2, 0xdd, 0x8c, 0xf7, 0x9b, 0x6f, 0x67, - 0xbe, 0x6f, 0x36, 0x81, 0x3d, 0x46, 0x67, 0x11, 0x17, 0x2c, 0x77, 0x33, 0x96, 0x8a, 0x14, 0xff, - 0x3f, 0x4b, 0xdd, 0x38, 0x9a, 0xb2, 0xd4, 0xad, 0x0e, 0x9c, 0x1f, 0x3a, 0x74, 0xdf, 0x10, 0x5b, - 0x44, 0x53, 0x42, 0x84, 0x76, 0x12, 0xc4, 0x64, 0x69, 0x43, 0x6d, 0xd4, 0xf7, 0x65, 0x8c, 0x16, - 0x74, 0x17, 0xc4, 0x78, 0x94, 0x26, 0x96, 0x2e, 0x3f, 0x57, 0x29, 0x4e, 0xa0, 0x17, 0x93, 0x08, - 0xc2, 0x40, 0x04, 0x96, 0x31, 0x34, 0x46, 0x83, 0xf1, 0xc8, 0xdd, 0xe0, 0x77, 0x15, 0xb7, 0x7b, - 0xaa, 0xa0, 0x5e, 0x22, 0x58, 0xee, 0x2f, 0x2b, 0xf1, 0x31, 0xf4, 0x29, 0x09, 0xb3, 0x34, 0x4a, - 0x04, 0xb7, 0xda, 0x92, 0xe6, 0x5a, 0x0d, 0x8d, 0xa7, 0x30, 0xfe, 0x0a, 0x8d, 0xf7, 0xc0, 0x4c, - 0xd2, 0x90, 0xb8, 0x65, 0xca, 0xb2, 0x2b, 0x35, 0x65, 0xaf, 0xd2, 0x90, 0xfc, 0x12, 0x65, 0x3f, - 0x85, 0xdd, 0x73, 0x4d, 0xe0, 0x3e, 0x18, 0x9f, 0x29, 0x57, 0xd3, 0x16, 0x21, 0x5e, 0x02, 0x73, - 0x11, 0xcc, 0xe6, 0xa4, 0x46, 0x2d, 0x93, 0x27, 0xfa, 0x23, 0xcd, 0xf9, 0xa9, 0x41, 0xbb, 0x20, - 0xc3, 0x3d, 0xd0, 0xa3, 0x50, 0xd5, 0xe8, 0x51, 0x58, 0xe8, 0x13, 0x84, 0x21, 0x23, 0xce, 0x2b, - 0x7d, 0x54, 0x5a, 0xa8, 0x99, 0xa5, 0x4c, 0x58, 0xc6, 0x50, 0x1b, 0x19, 0xbe, 0x8c, 0xf1, 0xd9, - 0x9a, 0x66, 0xe5, 0xb0, 0xb7, 0x1a, 0xba, 0x6e, 0x12, 0xec, 0x62, 0x63, 0x7c, 0xd5, 0xa1, 0x57, - 0x49, 0x59, 0x6b, 0xf7, 0x18, 0xba, 0x8c, 0xbe, 0xcc, 0x89, 0x0b, 0x59, 0x3c, 0x18, 0x5b, 0x35, - 0xfd, 0xbd, 0x2f, 0xf8, 0xfc, 0x0a, 0x88, 0x47, 0xd0, 0x63, 0xc4, 0xb3, 0x34, 0xe1, 0x24, 0x87, - 0xdd, 0x56, 0xb4, 0x44, 0xa2, 0xb7, 0x21, 0xc5, 0x9d, 0x2d, 0xbe, 0xff, 0x1b, 0x39, 0x02, 0x30, - 0x65, 0x5b, 0xb5, 0x52, 0x20, 0xb4, 0x45, 0x9e, 0x55, 0x55, 0x32, 0xc6, 0x43, 0xe8, 0xc8, 0x6a, - 0xae, 0x36, 0xbe, 0x79, 0x50, 0x85, 0x73, 0x04, 0x74, 0x7c, 0xe2, 0xf3, 0x99, 0xc0, 0xcb, 0xd0, - 0x09, 0xa6, 0xa2, 0x78, 0x48, 0xe5, 0x2d, 0x2a, 0xc3, 0x23, 0xe8, 0xf2, 0xf2, 0x91, 0x28, 0xc9, - 0xed, 0xe6, 0x67, 0xe4, 0x57, 0x50, 0x3c, 0x80, 0xbe, 0x88, 0x62, 0xe2, 0x22, 0x88, 0x33, 0xb5, - 0x62, 0xab, 0x0f, 0xce, 0x7f, 0xb0, 0xeb, 0xc5, 0x99, 0xc8, 0x7d, 0xa5, 0xb6, 0x73, 0x1b, 0xe0, - 0x98, 0x84, 0xaf, 0x1c, 0xb3, 0x56, 0x57, 0x96, 0xbd, 0x54, 0xa9, 0xe3, 0xc1, 0x40, 0xe2, 0x94, - 0x49, 0x0f, 0xa1, 0xa7, 0x4e, 0xb8, 0xa5, 0xc9, 0x89, 0xb7, 0x35, 0xb7, 0xc4, 0x3a, 0xbb, 0x30, - 0x38, 0x89, 0x78, 0x75, 0x9f, 0xf3, 0x02, 0x76, 0xca, 0xf4, 0x82, 0xb4, 0x23, 0xd8, 0xf9, 0x10, - 0x88, 0xe9, 0xa7, 0xdf, 0xcf, 0xf1, 0x5d, 0x03, 0xd3, 0x5b, 0x50, 0x22, 0x36, 0x1e, 0xec, 0xe1, - 0x9a, 0xad, 0x7b, 0xe3, 0x83, 0xba, 0x9d, 0x2b, 0xea, 0xde, 0xe6, 0x19, 0x29, 0xd3, 0xb7, 0x4a, - 0xbd, 0x6e, 0x5f, 0xfb, 0x8f, 0xed, 0xbb, 0x7b, 0x1f, 0xfa, 0xcb, 0x6b, 0x10, 0xa0, 0xf3, 0x9c, - 0x51, 0x20, 0x68, 0xbf, 0x55, 0xc4, 0x13, 0x9a, 0x91, 0xa0, 0x7d, 0xad, 0x88, 0xdf, 0x65, 0x61, - 0xf1, 0x5d, 0x1f, 0x7f, 0x33, 0xa0, 0xe7, 0x2b, 0x3a, 0x3c, 0x95, 0x6e, 0x56, 0x3f, 0xdb, 0xd7, - 0x6b, 0x2e, 0x5c, 0x99, 0x6d, 0xdf, 0x68, 0x3a, 0x56, 0xab, 0xd1, 0xc2, 0x97, 0x15, 0x35, 0x31, - 0xdc, 0xd2, 0xbd, 0x3d, 0xac, 0x13, 0xeb, 0xdc, 0x9a, 0xb5, 0xf0, 0x04, 0x60, 0x42, 0xec, 0x6f, - 0xb1, 0xbd, 0x2e, 0x17, 0x47, 0x95, 0x70, 0xac, 0x9b, 0x65, 0x6d, 0xd1, 0xec, 0x9b, 0x8d, 0xe7, - 0x4b, 0xca, 0x63, 0x30, 0xe5, 0x0e, 0x61, 0x1d, 0x76, 0x7d, 0xbb, 0xec, 0xab, 0x35, 0x80, 0xf2, - 0x2d, 0x3b, 0xad, 0x43, 0xed, 0x63, 0x47, 0xfe, 0xa7, 0x3e, 0xf8, 0x15, 0x00, 0x00, 0xff, 0xff, - 0x08, 0x0e, 0xe4, 0xae, 0x65, 0x07, 0x00, 0x00, + // 667 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xdd, 0x6e, 0xd3, 0x4c, + 0x10, 0x8d, 0xed, 0xfc, 0x4e, 0xda, 0x7e, 0xfd, 0x46, 0x08, 0x8c, 0x5b, 0x20, 0xb2, 0x04, 0x0a, + 0x48, 0x84, 0x2a, 0x54, 0x88, 0x9f, 0x2b, 0x44, 0x43, 0x25, 0xd4, 0x82, 0x58, 0xfe, 0xae, 0x4d, + 0x3c, 0x2a, 0x16, 0x89, 0x6d, 0x76, 0xb7, 0x91, 0xf2, 0x0e, 0x48, 0x3c, 0x01, 0x6f, 0xc3, 0x53, + 0xf0, 0x34, 0x68, 0xd7, 0xeb, 0x24, 0x55, 0xd7, 0x01, 0xa9, 0x70, 0x37, 0xe3, 0x3d, 0x33, 0x3b, + 0x73, 0xce, 0x59, 0x19, 0xb6, 0x38, 0x9d, 0x24, 0x42, 0xf2, 0xf9, 0x20, 0xe7, 0x99, 0xcc, 0xf0, + 0xff, 0x93, 0x6c, 0x30, 0x4d, 0xc6, 0x3c, 0x1b, 0x94, 0x07, 0xe1, 0x4f, 0x17, 0x5a, 0x6f, 0x88, + 0xcf, 0x92, 0x31, 0x21, 0x42, 0x3d, 0x8d, 0xa6, 0xe4, 0x3b, 0x3d, 0xa7, 0xdf, 0x61, 0x3a, 0x46, + 0x1f, 0x5a, 0x33, 0xe2, 0x22, 0xc9, 0x52, 0xdf, 0xd5, 0x9f, 0xcb, 0x14, 0x0f, 0xa0, 0x3d, 0x25, + 0x19, 0xc5, 0x91, 0x8c, 0x7c, 0xaf, 0xe7, 0xf5, 0xbb, 0xc3, 0xfe, 0xe0, 0x5c, 0xff, 0x81, 0xe9, + 0x3d, 0x38, 0x36, 0xd0, 0x51, 0x2a, 0xf9, 0x9c, 0x2d, 0x2a, 0xf1, 0x11, 0x74, 0x28, 0x8d, 0xf3, + 0x2c, 0x49, 0xa5, 0xf0, 0xeb, 0xba, 0xcd, 0x8e, 0xa5, 0xcd, 0xc8, 0x60, 0xd8, 0x12, 0x8d, 0x77, + 0xa1, 0x91, 0x66, 0x31, 0x09, 0xbf, 0xa1, 0xcb, 0xae, 0x58, 0xca, 0x5e, 0x66, 0x31, 0xb1, 0x02, + 0x85, 0xfb, 0xd0, 0xca, 0x72, 0x99, 0x64, 0xa9, 0xf0, 0x9b, 0x3d, 0xa7, 0xdf, 0x1d, 0x06, 0x96, + 0x82, 0x57, 0x05, 0x82, 0x95, 0xd0, 0xe0, 0x09, 0x6c, 0x9e, 0x19, 0x1d, 0xb7, 0xc1, 0xfb, 0x4c, + 0x73, 0xc3, 0x91, 0x0a, 0xf1, 0x12, 0x34, 0x66, 0xd1, 0xe4, 0x94, 0x0c, 0x41, 0x45, 0xf2, 0xd8, + 0x7d, 0xe8, 0x84, 0x3f, 0x1c, 0xa8, 0xab, 0x11, 0x70, 0x0b, 0xdc, 0x24, 0x36, 0x35, 0x6e, 0x12, + 0x2b, 0x56, 0xa3, 0x38, 0xe6, 0x24, 0x44, 0xc9, 0xaa, 0x49, 0x95, 0x06, 0x79, 0xc6, 0xa5, 0xef, + 0xf5, 0x9c, 0xbe, 0xc7, 0x74, 0x8c, 0x4f, 0x57, 0x98, 0x2e, 0x28, 0xba, 0x59, 0xb1, 0x6b, 0x15, + 0xcd, 0x17, 0x5b, 0xe3, 0xab, 0x0b, 0xed, 0x52, 0x00, 0xab, 0x49, 0x86, 0xd0, 0xe2, 0xf4, 0xe5, + 0x94, 0x84, 0xd4, 0xc5, 0xdd, 0xa1, 0x6f, 0x99, 0xef, 0xbd, 0xea, 0xc7, 0x4a, 0x20, 0xee, 0x43, + 0x9b, 0x93, 0xc8, 0xb3, 0x54, 0x90, 0x5e, 0x76, 0x5d, 0xd1, 0x02, 0x89, 0xa3, 0x73, 0x54, 0xdc, + 0x5e, 0xe3, 0x96, 0x7f, 0x43, 0x47, 0x04, 0x0d, 0x3d, 0x96, 0x95, 0x0a, 0x84, 0xba, 0x9c, 0xe7, + 0x65, 0x95, 0x8e, 0x71, 0x0f, 0x9a, 0xba, 0x5a, 0x98, 0x77, 0x52, 0xbd, 0xa8, 0xc1, 0x85, 0x3b, + 0xd0, 0x32, 0x4e, 0x54, 0x93, 0x49, 0x39, 0xd1, 0x77, 0x78, 0x4c, 0x85, 0xa1, 0x84, 0x26, 0x23, + 0x71, 0x3a, 0x91, 0x78, 0x19, 0x9a, 0xd1, 0x58, 0xc1, 0xcc, 0x08, 0x26, 0x53, 0x56, 0x17, 0xc5, + 0xbb, 0x33, 0x7a, 0x04, 0xd5, 0x2f, 0x93, 0x95, 0x50, 0xdc, 0x85, 0x8e, 0x4c, 0xa6, 0x24, 0x64, + 0x34, 0xcd, 0x8d, 0xff, 0x96, 0x1f, 0xc2, 0xff, 0x60, 0x73, 0x34, 0xcd, 0xe5, 0x9c, 0x19, 0x29, + 0xc2, 0x5b, 0x00, 0x87, 0x24, 0x99, 0x91, 0xd3, 0x5f, 0x5e, 0x59, 0xcc, 0x52, 0xa6, 0xe1, 0x08, + 0xba, 0x1a, 0x67, 0x14, 0x7c, 0x00, 0x6d, 0x73, 0x22, 0x7c, 0x47, 0xd3, 0xb1, 0x6e, 0xb8, 0x05, + 0x36, 0xdc, 0x84, 0xee, 0x51, 0x22, 0xca, 0xfb, 0xc2, 0xe7, 0xb0, 0x51, 0xa4, 0x17, 0x6c, 0xdb, + 0x87, 0x8d, 0x0f, 0x91, 0x1c, 0x7f, 0xfa, 0xfd, 0x1e, 0xdf, 0x1d, 0x68, 0x8c, 0x66, 0x94, 0xca, + 0x73, 0xaf, 0x79, 0x6f, 0x45, 0xf3, 0xad, 0xe1, 0xae, 0xcd, 0x90, 0xaa, 0xee, 0xed, 0x3c, 0x27, + 0xe3, 0x88, 0xb5, 0x54, 0xaf, 0xca, 0x57, 0xff, 0x63, 0xf9, 0xee, 0xdc, 0x83, 0xce, 0xe2, 0x1a, + 0x04, 0x68, 0x3e, 0xe3, 0x14, 0x49, 0xda, 0xae, 0xa9, 0xf8, 0x80, 0x26, 0x24, 0x69, 0xdb, 0x51, + 0xf1, 0xbb, 0x3c, 0x56, 0xdf, 0xdd, 0xe1, 0x37, 0x0f, 0xda, 0xcc, 0xb4, 0xc3, 0x63, 0xad, 0x66, + 0xf9, 0x27, 0xb8, 0x66, 0xb9, 0x70, 0x29, 0x76, 0x70, 0xbd, 0xea, 0xd8, 0x58, 0xa3, 0x86, 0x2f, + 0xca, 0xd6, 0xc4, 0x71, 0xcd, 0xf4, 0x41, 0xcf, 0x46, 0xd6, 0x19, 0x9b, 0xd5, 0xf0, 0x08, 0xe0, + 0x80, 0xf8, 0xdf, 0xea, 0xf6, 0xba, 0x30, 0x8e, 0x29, 0x11, 0x68, 0xdb, 0x65, 0xc5, 0x68, 0xc1, + 0x8d, 0xca, 0xf3, 0x45, 0xcb, 0x43, 0x68, 0x68, 0x0f, 0xa1, 0x0d, 0xbb, 0xea, 0xae, 0xe0, 0xaa, + 0x05, 0x50, 0xbc, 0xe5, 0xb0, 0xb6, 0xe7, 0x7c, 0x6c, 0xea, 0xdf, 0xf4, 0xfd, 0x5f, 0x01, 0x00, + 0x00, 0xff, 0xff, 0xfb, 0x3e, 0x7d, 0xa4, 0xb8, 0x07, 0x00, 0x00, } diff --git a/registry/proto/registry.proto b/registry/proto/registry.proto index 6883102a..c161828b 100644 --- a/registry/proto/registry.proto +++ b/registry/proto/registry.proto @@ -17,6 +17,7 @@ message Service { map metadata = 3; repeated Endpoint endpoints = 4; repeated Node nodes = 5; + Options options = 6; } // Node represents the node the service is on @@ -42,6 +43,11 @@ message Value { repeated Value values = 3; } +// Options are registry options +message Options { + int64 ttl = 1; +} + // Result is returns by the watcher message Result { string action = 1; // create, update, delete From d85ca7abd23d9d22cbd14b35ce4affd25db47286 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 27 Sep 2019 14:29:00 +0100 Subject: [PATCH 004/344] Set registry TTL properly via protobuf Options --- registry/service/service.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/registry/service/service.go b/registry/service/service.go index 9585c242..5bc3cffb 100644 --- a/registry/service/service.go +++ b/registry/service/service.go @@ -58,13 +58,12 @@ func (s *serviceRegistry) Register(srv *registry.Service, opts ...registry.Regis o(&options) } - ctx := context.Background() - if options.TTL.Nanoseconds() != 0.0 { - ctx = context.WithValue(ctx, "register_ttl", options.TTL) - } + // encode srv into protobuf and pack Register TTL into it + pbSrv := ToProto(srv) + pbSrv.Options.Ttl = int64(options.TTL.Seconds()) // register the service - _, err := s.client.Register(ctx, ToProto(srv), s.callOpts()...) + _, err := s.client.Register(context.TODO(), pbSrv, s.callOpts()...) if err != nil { return err } From 8417361bceb8810cd400263d1758bc47d56d414f Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 27 Sep 2019 15:00:25 +0100 Subject: [PATCH 005/344] Set registry TTL to seconds, not the nanoseconds --- registry/handler/handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/handler/handler.go b/registry/handler/handler.go index e828ecdb..68d4523b 100644 --- a/registry/handler/handler.go +++ b/registry/handler/handler.go @@ -28,7 +28,7 @@ func (r *Registry) GetService(ctx context.Context, req *pb.GetRequest, rsp *pb.G func (r *Registry) Register(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error { var regOpts []registry.RegisterOption - ttl := time.Duration(req.Options.Ttl) + ttl := time.Duration(req.Options.Ttl) * time.Second regOpts = append(regOpts, registry.RegisterTTL(ttl)) err := r.Registry.Register(service.ToService(req), regOpts...) From 204c7d1fcfc64ec1b56b76d1c7fca427e8d9ca71 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Sun, 29 Sep 2019 15:03:21 +0100 Subject: [PATCH 006/344] Fixed options bug and proto indenting --- registry/handler/handler.go | 6 ++++-- registry/proto/registry.proto | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/registry/handler/handler.go b/registry/handler/handler.go index 68d4523b..a592dffa 100644 --- a/registry/handler/handler.go +++ b/registry/handler/handler.go @@ -28,8 +28,10 @@ func (r *Registry) GetService(ctx context.Context, req *pb.GetRequest, rsp *pb.G func (r *Registry) Register(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error { var regOpts []registry.RegisterOption - ttl := time.Duration(req.Options.Ttl) * time.Second - regOpts = append(regOpts, registry.RegisterTTL(ttl)) + if req.Options != nil { + ttl := time.Duration(req.Options.Ttl) * time.Second + regOpts = append(regOpts, registry.RegisterTTL(ttl)) + } err := r.Registry.Register(service.ToService(req), regOpts...) if err != nil { diff --git a/registry/proto/registry.proto b/registry/proto/registry.proto index c161828b..ddc09669 100644 --- a/registry/proto/registry.proto +++ b/registry/proto/registry.proto @@ -12,11 +12,11 @@ service Registry { // Service represents a go-micro service message Service { - string name = 1; - string version = 2; - map metadata = 3; - repeated Endpoint endpoints = 4; - repeated Node nodes = 5; + string name = 1; + string version = 2; + map metadata = 3; + repeated Endpoint endpoints = 4; + repeated Node nodes = 5; Options options = 6; } From 859ecb18725b3f3955d9d98ba4a89edce3d5b157 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Sun, 29 Sep 2019 21:42:30 +0100 Subject: [PATCH 007/344] Dont set default TTL. Stop tracking nodes with no TTL --- registry/memory/memory.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/registry/memory/memory.go b/registry/memory/memory.go index f7134bf2..72d62298 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -73,8 +73,8 @@ func (m *Registry) ttlPrune() { case <-prune.C: m.Lock() for nodeTrackId, node := range m.nodes { - // if we exceed the TTL threshold we need to stop tracking the node - if time.Since(node.lastSeen) > node.ttl { + // if the TTL has been set and we exceed the hresholdset by it we stop tracking the node + if node.ttl.Seconds() != 0.0 && time.Since(node.lastSeen) > node.ttl { // split nodeTrackID into service Name, Version and Node Id trackIdSplit := strings.Split(nodeTrackId, "+") svcName, svcVersion, nodeId := trackIdSplit[0], trackIdSplit[1], trackIdSplit[2] @@ -183,11 +183,6 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption o(&options) } - // if no TTL has been set, set it to DefaultTTL - if options.TTL.Seconds() == 0.0 { - options.TTL = DefaultTTL - } - if service, ok := m.Services[s.Name]; !ok { m.Services[s.Name] = []*registry.Service{s} // add all nodes into nodes map to track their TTL From 3f3f1272b358b1369147f227a55a6d4181eae13b Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Mon, 30 Sep 2019 11:11:32 +0100 Subject: [PATCH 008/344] Turn regular logs to Debug logs; annotate with Registry "tag" --- registry/memory/memory.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/registry/memory/memory.go b/registry/memory/memory.go index 72d62298..1cad2274 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -78,7 +78,7 @@ func (m *Registry) ttlPrune() { // split nodeTrackID into service Name, Version and Node Id trackIdSplit := strings.Split(nodeTrackId, "+") svcName, svcVersion, nodeId := trackIdSplit[0], trackIdSplit[1], trackIdSplit[2] - log.Logf("TTL threshold reached for node %s for service %s", nodeId, svcName) + log.Debugf("Registry TTL expired for service %s, node %s", svcName, nodeId) // we need to find a node that expired and delete it from service nodes if _, ok := m.Services[svcName]; ok { for _, service := range m.Services[svcName] { @@ -187,7 +187,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption m.Services[s.Name] = []*registry.Service{s} // add all nodes into nodes map to track their TTL for _, n := range s.Nodes { - log.Logf("Tracking node %s for service %s", n.Id, s.Name) + log.Debugf("Registry tracking node %s for service %s", n.Id, s.Name) m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ lastSeen: time.Now(), ttl: options.TTL, @@ -216,7 +216,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption m.Services[s.Name] = merged // we know s is the new [version of] service; we need to strart tracking its nodes for _, n := range s.Nodes { - log.Logf("Tracking node %s for service %s", n.Id, s.Name) + log.Debugf("Registry tracking node %s for service %s", n.Id, s.Name) m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ lastSeen: time.Now(), ttl: options.TTL, @@ -238,7 +238,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption } } if !found { - log.Logf("Tracking node %s for service %s", n.Id, s.Name) + log.Debugf("Registry tracking node %s for service %s", n.Id, s.Name) m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ lastSeen: time.Now(), ttl: options.TTL, @@ -252,7 +252,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption // refresh the timestamp and TTL of the service node for _, n := range s.Nodes { trackId := nodeTrackId(s.Name, s.Version, n.Id) - log.Logf("Refreshing TTL for node %s for service %s", n.Id, s.Name) + log.Debugf("Registry refreshing TTL for node %s for service %s", n.Id, s.Name) if trackedNode, ok := m.nodes[trackId]; ok { trackedNode.lastSeen = time.Now() trackedNode.ttl = options.TTL @@ -284,7 +284,7 @@ func (m *Registry) Deregister(s *registry.Service) error { } if service := registry.Remove(service, []*registry.Service{s}); len(service) == 0 { id := svcNodes[s.Name][s.Version][0] - log.Logf("Stopped tracking node %s for service %s", id, s.Name) + log.Debugf("Registry stopped tracking node %s for service %s", id, s.Name) delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) delete(m.Services, s.Name) } else { @@ -299,7 +299,7 @@ func (m *Registry) Deregister(s *registry.Service) error { } } if !found { - log.Logf("Stopped tracking node %s for service %s", id, s.Name) + log.Debugf("Registry stopped tracking node %s for service %s", id, s.Name) delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) } } From 4b73ac9dc5b6b6c418159e528ae77171f5b59892 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Mon, 30 Sep 2019 12:48:06 +0100 Subject: [PATCH 009/344] Simplified code. Small bug fix the used to lead to multi-registry loop. --- registry/memory/memory.go | 65 +++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/registry/memory/memory.go b/registry/memory/memory.go index 1cad2274..810d8d4c 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -178,6 +178,8 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption m.Lock() defer m.Unlock() + log.Debugf("Registry deregistering service: %s", s.Name) + var options registry.RegisterOptions for _, o := range opts { o(&options) @@ -187,16 +189,17 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption m.Services[s.Name] = []*registry.Service{s} // add all nodes into nodes map to track their TTL for _, n := range s.Nodes { - log.Debugf("Registry tracking node %s for service %s", n.Id, s.Name) + log.Debugf("Registry tracking new service: %s, node %s", s.Name, n.Id) m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ lastSeen: time.Now(), ttl: options.TTL, } } go m.sendEvent(®istry.Result{Action: "update", Service: s}) + return nil } else { - // svcCount essentially keep the count of all service vesions - svcCount := len(service) + // svcCount keeps the count of all versions of particular service + //svcCount := len(service) // svcNodes maintains a list of node Ids per particular service version svcNodes := make(map[string]map[string][]string) // collect all service ids for all service versions @@ -212,20 +215,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption } // if merged count and original service counts changed we know we are adding a new version of the service merged := registry.Merge(service, []*registry.Service{s}) - if len(merged) != svcCount { - m.Services[s.Name] = merged - // we know s is the new [version of] service; we need to strart tracking its nodes - for _, n := range s.Nodes { - log.Debugf("Registry tracking node %s for service %s", n.Id, s.Name) - m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ - lastSeen: time.Now(), - ttl: options.TTL, - } - } - go m.sendEvent(®istry.Result{Action: "update", Service: s}) - return nil - } - // if the node count of any particular service [version] changed we know we are adding a new node to the service + // if the node count of any service [version] changed we know we are adding a new node to the service for _, s := range merged { // we know that if the node counts have changed we need to track new nodes if len(s.Nodes) != len(svcNodes[s.Name][s.Version]) { @@ -238,7 +228,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption } } if !found { - log.Debugf("Registry tracking node %s for service %s", n.Id, s.Name) + log.Debugf("Registry tracking new node: %s for service %s", n.Id, s.Name) m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ lastSeen: time.Now(), ttl: options.TTL, @@ -268,31 +258,38 @@ func (m *Registry) Deregister(s *registry.Service) error { m.Lock() defer m.Unlock() + log.Debugf("Registry deregistering service: %s", s.Name) + if service, ok := m.Services[s.Name]; ok { - // svcNodes maintains a list of node Ids per particular service version + // svcNodes collects the list of all node Ids for each service version svcNodes := make(map[string]map[string][]string) - // collect all service ids for all service versions - for _, s := range service { - if _, ok := svcNodes[s.Name]; !ok { - svcNodes[s.Name] = make(map[string][]string) + // collect all service node ids for all service versions + for _, svc := range service { + if _, ok := svcNodes[svc.Name]; !ok { + svcNodes[svc.Name] = make(map[string][]string) } - if _, ok := svcNodes[s.Name][s.Version]; !ok { - for _, n := range s.Nodes { - svcNodes[s.Name][s.Version] = append(svcNodes[s.Name][s.Version], n.Id) + if _, ok := svcNodes[svc.Name][svc.Version]; !ok { + for _, n := range svc.Nodes { + svcNodes[svc.Name][svc.Version] = append(svcNodes[svc.Name][svc.Version], n.Id) } } } - if service := registry.Remove(service, []*registry.Service{s}); len(service) == 0 { - id := svcNodes[s.Name][s.Version][0] - log.Debugf("Registry stopped tracking node %s for service %s", id, s.Name) - delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) + // if there are no more services we know we have either removed all nodes or there were no nodes + if updatedService := registry.Remove(service, []*registry.Service{s}); len(updatedService) == 0 { + for _, id := range svcNodes[s.Name][s.Version] { + log.Debugf("Registry stopped tracking node %s for service %s", id, s.Name) + delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) + go m.sendEvent(®istry.Result{Action: "delete", Service: s}) + } + log.Debugf("Registry deleting service %s: no service nodes", s.Name) delete(m.Services, s.Name) + return nil } else { // find out which nodes have been removed for _, id := range svcNodes[s.Name][s.Version] { - for _, s := range service { + for _, svc := range updatedService { var found bool - for _, n := range s.Nodes { + for _, n := range svc.Nodes { if id == n.Id { found = true break @@ -301,12 +298,12 @@ func (m *Registry) Deregister(s *registry.Service) error { if !found { log.Debugf("Registry stopped tracking node %s for service %s", id, s.Name) delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) + go m.sendEvent(®istry.Result{Action: "delete", Service: s}) } } - m.Services[s.Name] = service + m.Services[s.Name] = updatedService } } - go m.sendEvent(®istry.Result{Action: "delete", Service: s}) } return nil From 6477c3afffca0e3e60b0205325ea5617aee03a94 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 1 Oct 2019 18:33:26 +0100 Subject: [PATCH 010/344] Bump travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 211cb587..cb760ae9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: go go: -- 1.12.x +- 1.13.x env: - GO111MODULE=on notifications: From e48155118f6d8ab035cb95dc27a3d61c5ae8e91f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 1 Oct 2019 18:55:03 +0100 Subject: [PATCH 011/344] Update go mod --- go.sum | 123 +-------------------------------------------------------- 1 file changed, 1 insertion(+), 122 deletions(-) diff --git a/go.sum b/go.sum index c01a6c5e..b330bc19 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,21 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.40.0/go.mod h1:Tk58MuI9rbLMKlAjeO/bDnteAx7tX2gJIXw4T5Jwlro= -cloud.google.com/go v0.41.0/go.mod h1:OauMR7DV8fzvZIl2qg6rkaIhD/vmgk4iwEw/h6ercmg= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.0/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.13/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 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-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= @@ -44,7 +37,6 @@ github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wX github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= 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 h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -53,16 +45,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v0.7.3-0.20190309235953-33c3200e0d16 h1:dmUn0SuGx7unKFwxyeQ/oLUHhEfZosEDrpmYM+6MTuc= -github.com/docker/docker v0.7.3-0.20190309235953-33c3200e0d16/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b h1:+Ga+YpCDpcY1fln6GI0fiiirpqHGcob5/Vk3oKNuGdU= github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b/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.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/emirpasic/gods v1.9.0 h1:rUF4PuzEjMChMiNsVjdI+SyLu7rEqpQ5reNFnhC7oFo= -github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -71,14 +59,10 @@ github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c h1:pBgVXWDXj github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY= 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/fsouza/go-dockerclient v1.4.1 h1:W7wuJ3IB48WYZv/UBk9dCTIb9oX805+L9KIm65HcUYs= -github.com/fsouza/go-dockerclient v1.4.1/go.mod h1:PUNHxbowDqRXfRgZqMz1OeGtbWC6VKyZvJ99hDjB0qs= github.com/fsouza/go-dockerclient v1.4.2 h1:dl6GfIWS5Qn4C6OfSnnoe6YuOV8lvKAE8W/YD1Q7udo= github.com/fsouza/go-dockerclient v1.4.2/go.mod h1:COunfLZrsdwX/j3YVDAG8gIw3KutrI0x1+vGEJ5zxdI= 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/gliderlabs/ssh v0.1.3/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -100,11 +84,9 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= -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/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/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/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -121,13 +103,8 @@ 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/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/handlers v1.4.0 h1:XulKRWSQK5uChr4pEgSE4Tc/OcmnU9GJuSwdog/tZsA= -github.com/gorilla/handlers v1.4.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/handlers v1.4.1 h1:BHvcRGJe/TrL+OqFxoKQGddTgeibiOjaBssV5a/N9sw= -github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/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= @@ -139,11 +116,9 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv 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-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-immutable-radix v1.1.0 h1:vN9wG1D6KG6YHRTWr8512cxGOVgTMEfgEdSj/hr8MPc= github.com/hashicorp/go-immutable-radix v1.1.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-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= @@ -151,11 +126,9 @@ github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uP github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -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-rootcerts v1.0.1 h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+09R3cEP8= github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -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.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= @@ -165,9 +138,7 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -179,7 +150,6 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg 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/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= @@ -193,16 +163,11 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= -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/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e h1:RgQk53JHp/Cjunrr1WlsXSZpqXn+uREuHvUVcK82CV8= -github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kevinburke/ssh_config v0.0.0-20190630040420-2e50c441276c h1:VAx3LRNjVNvjtgO7KFRuT/3aye/0zJvwn01rHSfoolo= -github.com/kevinburke/ssh_config v0.0.0-20190630040420-2e50c441276c/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -213,52 +178,30 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= -github.com/lucas-clemente/quic-go v0.7.1-0.20190710050138-1441923ab031 h1:wjcGvgllMOQw8wNYFH6acq/KlTAdjKMSo1EUYybHXto= -github.com/lucas-clemente/quic-go v0.7.1-0.20190710050138-1441923ab031/go.mod h1:lb5aAxL68VvhZ00e7yYuQVK/9FLggtYy4qo7oI5qzqA= -github.com/lucas-clemente/quic-go v0.11.2 h1:Mop0ac3zALaBR3wGs6j8OYe/tcFvFsxTUFMkE/7yUOI= -github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= -github.com/lucas-clemente/quic-go v0.12.0 h1:dYHUyB50gEQlK3KqytmNySzuyzAcaQ3iuI2ZReAfVrE= +github.com/lucas-clemente/quic-go v0.12.0 h1:TRbvZ6F++sofeGbh+Z2IIyIOhl8KyGnYuA06g2yrHdI= github.com/lucas-clemente/quic-go v0.12.0/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= -github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA= -github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= -github.com/marten-seemann/qtls v0.2.4 h1:mCJ6i1jAqcsm9XODrSGvXECodoAb1STta+TkxJCwCnE= -github.com/marten-seemann/qtls v0.2.4/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= -github.com/marten-seemann/qtls v0.3.1 h1:ySYIvhFjFY2JsNHY6VACvomMEDy3EvdPA6yciUFAiHw= -github.com/marten-seemann/qtls v0.3.1/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI= github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/micro/cli v0.2.0 h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA= github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= -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/mdns v0.1.1-0.20190729112526-ef68c9635478 h1:L6jnZZ763dMLlvst8P0dWHa1WbUu7ppUY1q3AY2hhIU= -github.com/micro/mdns v0.1.1-0.20190729112526-ef68c9635478/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= -github.com/micro/mdns v0.2.0 h1:/+/n2PSiJURrXsBIGtfCz0hex/XYKqVsn51GAGdFrOE= -github.com/micro/mdns v0.2.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= 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.14 h1:wkQWn9wIp4mZbwW8XV6Km6owkvRPbOiV004ZM2CkGvA= -github.com/miekg/dns v1.1.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= github.com/miekg/dns v1.1.15/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 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -282,7 +225,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= -github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -290,7 +232,6 @@ github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nlopes/slack v0.5.0 h1:NbIae8Kd0NpqaEI3iUrsuS0KbcEDhzhc939jLW5fNm0= github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM= -github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -305,7 +246,6 @@ github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJ github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -334,8 +274,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME= -github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -349,8 +287,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/xanzy/ssh-agent v0.2.0 h1:Adglfbi5p9Z0BmK2oKU9nTG+zKfniSfnaMYB+ULd+Ro= -github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -363,22 +299,14 @@ golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= -golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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/exp v0.0.0-20190627132806-fd42eb6b336f/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190618124811-92942e4437e2/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -386,8 +314,6 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk 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-20190607214518-6fa95d984e88/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mobile v0.0.0-20190711165009-e47acb2ca7f9/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190806162312-597adff16ade/go.mod h1:AlhUtkH4DA4asiFC5RgK7ZKmauvtkAVcy9L0epCzlWo= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= @@ -404,16 +330,10 @@ golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190502183928-7f726cade0ab/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190607181551-461777fb6f67 h1:rJJxsykSlULwd2P2+pg/rtnwN2FrWp4IuCxOSyS0V00= -golang.org/x/net v0.0.0-20190607181551-461777fb6f67/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -426,7 +346,6 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ 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-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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -436,26 +355,18 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/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-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190310054646-10058d7d4faa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190621062556-bf70e4678053 h1:T0MJjz97TtCXa3ZNW2Oenb3KQWB91K965zMEbIJ4ThA= -golang.org/x/sys v0.0.0-20190621062556-bf70e4678053/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 h1:6ZQFf1D2YYDDI7eSwW8adlkkavTB9sw5I24FVtEvNUQ= golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa h1:KIDDMLT1O0Nr7TSxp8xM5tJcdn8tgyAONntO829og1M= -golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e h1:TsjK5I7fXk8f2FQrgu6NS7i5Qih3knl2FL1htyguLRE= golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/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/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -473,47 +384,29 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190530171427-2b03ca6e44eb/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190620191750-1fa568393b23/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190710184609-286818132824/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190711191110-9a621aea19f8/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190807201305-8be58fba6352/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190809145639-6d4652c779c4/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601 h1:9VBRTdmgQxbs6HE0sUnMrSWNePppAJU07NYvX5dIB04= -google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190626174449-989357319d63/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190708153700-3bdd9d9f5532 h1:5pOB7se0B2+IssELuQUs6uoBgYJenkU2AQlvopc2sRw= -google.golang.org/genproto v0.0.0-20190708153700-3bdd9d9f5532/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64 h1:iKtrH9Y8mcbADOP0YFaEMth7OfuHY9xHOwNj4znpM1A= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.0 h1:J0UbZOIrCAl+fpTOf8YLs4dJo8L/owV4LYVtAXQoPkw= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= @@ -522,24 +415,11 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/validator.v9 v9.29.0 h1:5ofssLNYgAA/inWn6rTZ4juWpRJUwEnXc1LG2IeXwgQ= -gopkg.in/go-playground/validator.v9 v9.29.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc= gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= -gopkg.in/src-d/go-billy.v4 v4.2.1 h1:omN5CrMrMcQ+4I8bJ0wEhOBPanIRWzFC953IiXKdYzo= -gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= -gopkg.in/src-d/go-billy.v4 v4.3.0 h1:KtlZ4c1OWbIs4jCv5ZXrTqG8EQocr0g/d4DjNg70aek= -gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= -gopkg.in/src-d/go-billy.v4 v4.3.1 h1:OkK1DmefDy1Z6Veu82wdNj/cLpYORhdX4qdaYCPwc7s= -gopkg.in/src-d/go-billy.v4 v4.3.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= -gopkg.in/src-d/go-git.v4 v4.11.0 h1:cJwWgJ0DXifrNrXM6RGN1Y2yR60Rr1zQ9Q5DX5S9qgU= -gopkg.in/src-d/go-git.v4 v4.11.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk= -gopkg.in/src-d/go-git.v4 v4.12.0 h1:CKgvBCJCcdfNnyXPYI4Cp8PaDDAmAPEN0CtfEdEAbd8= -gopkg.in/src-d/go-git.v4 v4.12.0/go.mod h1:zjlNnzc1Wjn43v3Mtii7RVxiReNP0fIu9npcXKzuNp4= gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/telegram-bot-api.v4 v4.6.4 h1:hpHWhzn4jTCsAJZZ2loNKfy2QWyPDRJVl3aTFXeMW8g= @@ -555,6 +435,5 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190614002413-cb51c254f01b/go.mod h1:JlmFZigtG9vBVR3QGIQ9g/Usz4BzH+Xm6Z8iHQWRYUw= honnef.co/go/tools v0.0.1-2019.2.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= From e8a53610f17bfb70a3b9e1b50c6252ba7111e13b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 1 Oct 2019 19:09:29 +0100 Subject: [PATCH 012/344] Update go mod to use 1.13 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index b0f037a3..f0519d50 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/micro/go-micro -go 1.12 +go 1.13 require ( cloud.google.com/go v0.44.0 // indirect From 03b8ceab5c0c54e9e49bbd6168d874ab0e06a690 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 1 Oct 2019 19:33:23 +0100 Subject: [PATCH 013/344] Update go.mod --- go.mod | 54 +++---------- go.sum | 236 ++++++++++----------------------------------------------- 2 files changed, 50 insertions(+), 240 deletions(-) diff --git a/go.mod b/go.mod index f0519d50..0dfd6091 100644 --- a/go.mod +++ b/go.mod @@ -3,76 +3,40 @@ module github.com/micro/go-micro go 1.13 require ( - cloud.google.com/go v0.44.0 // indirect github.com/BurntSushi/toml v0.3.1 - github.com/Microsoft/go-winio v0.4.14 // indirect - github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 // indirect - github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 // indirect - github.com/armon/go-radix v1.0.0 // indirect github.com/beevik/ntp v0.2.0 github.com/bitly/go-simplejson v0.5.0 github.com/bwmarrin/discordgo v0.19.0 - github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc // indirect github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c github.com/fsnotify/fsnotify v1.4.7 - github.com/fsouza/go-dockerclient v1.4.2 + github.com/fsouza/go-dockerclient v1.4.4 github.com/ghodss/yaml v1.0.0 - github.com/go-kit/kit v0.9.0 // indirect github.com/go-log/log v0.1.0 github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect github.com/golang/protobuf v1.3.2 - github.com/google/go-cmp v0.3.1 // indirect - github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70 // indirect github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 - github.com/gorilla/websocket v1.4.0 - github.com/hashicorp/consul/api v1.1.0 - github.com/hashicorp/go-immutable-radix v1.1.0 // indirect - github.com/hashicorp/go-msgpack v0.5.5 // indirect - github.com/hashicorp/go-retryablehttp v0.5.4 // indirect - github.com/hashicorp/go-rootcerts v1.0.1 // indirect - github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-version v1.2.0 // indirect - github.com/hashicorp/golang-lru v0.5.3 // indirect + github.com/gorilla/websocket v1.4.1 + github.com/hashicorp/consul/api v1.2.0 github.com/hashicorp/hcl v1.0.0 - github.com/hashicorp/mdns v1.0.1 // indirect - github.com/hashicorp/memberlist v0.1.4 - github.com/hashicorp/serf v0.8.3 // indirect + github.com/hashicorp/memberlist v0.1.5 github.com/imdario/mergo v0.3.7 github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 - github.com/kisielk/errcheck v1.2.0 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/leodido/go-urn v1.1.0 // indirect github.com/lucas-clemente/quic-go v0.12.0 - github.com/mattn/go-colorable v0.1.2 // indirect - github.com/mattn/go-runewidth v0.0.4 // indirect github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 - github.com/miekg/dns v1.1.15 // indirect - github.com/mitchellh/gox v1.0.1 // indirect github.com/mitchellh/hashstructure v1.0.0 - github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/nats-io/nats.go v1.8.1 - github.com/nats-io/nkeys v0.1.0 // indirect - github.com/nlopes/slack v0.5.0 - github.com/olekukonko/tablewriter v0.0.1 - github.com/onsi/ginkgo v1.8.0 // indirect - github.com/onsi/gomega v1.5.0 // indirect + github.com/nlopes/slack v0.6.0 github.com/pkg/errors v0.8.1 - github.com/posener/complete v1.2.1 // indirect - github.com/prometheus/client_golang v1.1.0 // indirect - github.com/sirupsen/logrus v1.4.2 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect - golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 - golang.org/x/mobile v0.0.0-20190806162312-597adff16ade // indirect - golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 - golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e // indirect - golang.org/x/tools v0.0.0-20190809145639-6d4652c779c4 // indirect - google.golang.org/grpc v1.22.1 - gopkg.in/go-playground/validator.v9 v9.29.1 + golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc + golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 + google.golang.org/grpc v1.24.0 + gopkg.in/go-playground/validator.v9 v9.30.0 gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/telegram-bot-api.v4 v4.6.4 - honnef.co/go/tools v0.0.1-2019.2.2 // indirect ) diff --git a/go.sum b/go.sum index b330bc19..ae387d3e 100644 --- a/go.sum +++ b/go.sum @@ -1,32 +1,21 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.0/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +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/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Microsoft/go-winio v0.4.13/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -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/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 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-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/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= @@ -34,12 +23,9 @@ github.com/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5a github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -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 h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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= @@ -59,100 +45,74 @@ github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c h1:pBgVXWDXj github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY= 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/fsouza/go-dockerclient v1.4.2 h1:dl6GfIWS5Qn4C6OfSnnoe6YuOV8lvKAE8W/YD1Q7udo= -github.com/fsouza/go-dockerclient v1.4.2/go.mod h1:COunfLZrsdwX/j3YVDAG8gIw3KutrI0x1+vGEJ5zxdI= +github.com/fsouza/go-dockerclient v1.4.4 h1:Sd5nD4wdAgiPxvrbYUzT2ZZNmPk3z+GGnZ+frvw8z04= +github.com/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA= 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.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-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-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/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/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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 v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/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/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/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/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/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 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/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -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/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/consul v1.6.1 h1:ISPgwOO8/vPYrCXQNyx63eJAYjPGRnmFsXK7aj2XICs= +github.com/hashicorp/consul/api v1.2.0 h1:oPsuzLp2uk7I7rojPKuncWbZ+m5TMoD4Ivs+2Rkeh4Y= +github.com/hashicorp/consul/api v1.2.0/go.mod h1:1SIkFYi2ZTXUE5Kgt179+4hH33djo11+0Eo2XgTAtkw= +github.com/hashicorp/consul/sdk v0.2.0/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-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-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-immutable-radix v1.1.0 h1:vN9wG1D6KG6YHRTWr8512cxGOVgTMEfgEdSj/hr8MPc= -github.com/hashicorp/go-immutable-radix v1.1.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-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-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +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-rootcerts v1.0.1 h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+09R3cEP8= -github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +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.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/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-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 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/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/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= 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/memberlist v0.1.5 h1:AYBsgJOW9gab/toO5tEB8lWetVgDKZycqkebJ8xxpqM= +github.com/hashicorp/memberlist v0.1.5/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/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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= @@ -163,19 +123,14 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 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/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/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/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= @@ -188,56 +143,41 @@ github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGD github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI= github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/micro/cli v0.2.0 h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA= github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= 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.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= -github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/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 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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= +github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= -github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nlopes/slack v0.5.0 h1:NbIae8Kd0NpqaEI3iUrsuS0KbcEDhzhc939jLW5fNm0= -github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA= +github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -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= @@ -245,38 +185,19 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= 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/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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 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/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -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 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -286,12 +207,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -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= @@ -299,124 +216,58 @@ golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc h1:KyTYo8xkh/2WdbFLUyQwBS0Jfn3qfZ9QmuPbok2oENE= +golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-20190806162312-597adff16ade/go.mod h1:AlhUtkH4DA4asiFC5RgK7ZKmauvtkAVcy9L0epCzlWo= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA= +golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-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-20181116152217-5ac8a444bdc5/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/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-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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e h1:TsjK5I7fXk8f2FQrgu6NS7i5Qih3knl2FL1htyguLRE= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190809145639-6d4652c779c4/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64 h1:iKtrH9Y8mcbADOP0YFaEMth7OfuHY9xHOwNj4znpM1A= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= 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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc= -gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss= +gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= @@ -431,9 +282,4 @@ 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/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= From b722798caafa7468ac55d919d0801a6195835d6f Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Wed, 2 Oct 2019 03:48:51 +0300 Subject: [PATCH 014/344] some spelling fixes in memory and gossip registry Signed-off-by: Vasiliy Tolstov --- registry/gossip/gossip.go | 17 +++++++++++------ registry/memory/memory.go | 18 +++++++++--------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 24006438..416422f1 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -292,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] Registry broadcast message size %d bigger then MaxPacketSize %d", l, MaxPacketSize) } return up } @@ -427,14 +427,14 @@ func (g *gossipRegistry) connect(addrs []string) error { return nil // in case of timeout fail with a timeout error case <-timeout: - return fmt.Errorf("[gossip] connect timeout %v", g.addrs) + return fmt.Errorf("[gossip] Registry 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) + log.Debugf("[gossip] Registry connect success for %v", g.addrs) return nil } else { - log.Logf("[gossip] connect failed for %v", g.addrs) + log.Debugf("[gossip] Registry connect failed for %v", g.addrs) } } } @@ -697,6 +697,8 @@ func (g *gossipRegistry) Options() registry.Options { } func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { + log.Debugf("[gossip] Registry registering service: %s", s.Name) + b, err := json.Marshal(s) if err != nil { return err @@ -716,7 +718,7 @@ func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.Register } if options.TTL == 0 && g.tcpInterval == 0 { - return fmt.Errorf("Require register TTL or interval for memberlist.Config") + return fmt.Errorf("[gossip] Require register TTL or interval for memberlist.Config") } up := &pb.Update{ @@ -747,6 +749,9 @@ func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.Register } func (g *gossipRegistry) Deregister(s *registry.Service) error { + + log.Debugf("[gossip] Registry deregistering service: %s", s.Name) + b, err := json.Marshal(s) if err != nil { return err @@ -834,7 +839,7 @@ func NewRegistry(opts ...registry.Option) registry.Registry { // configure the gossiper if err := configure(g, opts...); err != nil { - log.Fatalf("[gossip] Error configuring registry: %v", err) + log.Fatalf("[gossip] Registry configuring error: %v", err) } // wait for setup <-time.After(g.interval * 2) diff --git a/registry/memory/memory.go b/registry/memory/memory.go index 810d8d4c..eecb1284 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -78,7 +78,7 @@ func (m *Registry) ttlPrune() { // split nodeTrackID into service Name, Version and Node Id trackIdSplit := strings.Split(nodeTrackId, "+") svcName, svcVersion, nodeId := trackIdSplit[0], trackIdSplit[1], trackIdSplit[2] - log.Debugf("Registry TTL expired for service %s, node %s", svcName, nodeId) + log.Debugf("[memory] Registry TTL expired for service %s, node %s", svcName, nodeId) // we need to find a node that expired and delete it from service nodes if _, ok := m.Services[svcName]; ok { for _, service := range m.Services[svcName] { @@ -178,7 +178,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption m.Lock() defer m.Unlock() - log.Debugf("Registry deregistering service: %s", s.Name) + log.Debugf("[memory] Registry registering service: %s", s.Name) var options registry.RegisterOptions for _, o := range opts { @@ -189,7 +189,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption m.Services[s.Name] = []*registry.Service{s} // add all nodes into nodes map to track their TTL for _, n := range s.Nodes { - log.Debugf("Registry tracking new service: %s, node %s", s.Name, n.Id) + log.Debugf("[memory] Registry tracking new service: %s, node %s", s.Name, n.Id) m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ lastSeen: time.Now(), ttl: options.TTL, @@ -228,7 +228,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption } } if !found { - log.Debugf("Registry tracking new node: %s for service %s", n.Id, s.Name) + log.Debugf("[memory] Registry tracking new node: %s for service %s", n.Id, s.Name) m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ lastSeen: time.Now(), ttl: options.TTL, @@ -242,7 +242,7 @@ func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption // refresh the timestamp and TTL of the service node for _, n := range s.Nodes { trackId := nodeTrackId(s.Name, s.Version, n.Id) - log.Debugf("Registry refreshing TTL for node %s for service %s", n.Id, s.Name) + log.Debugf("[memory] Registry refreshing TTL for node %s for service %s", n.Id, s.Name) if trackedNode, ok := m.nodes[trackId]; ok { trackedNode.lastSeen = time.Now() trackedNode.ttl = options.TTL @@ -258,7 +258,7 @@ func (m *Registry) Deregister(s *registry.Service) error { m.Lock() defer m.Unlock() - log.Debugf("Registry deregistering service: %s", s.Name) + log.Debugf("[memory] Registry deregistering service: %s", s.Name) if service, ok := m.Services[s.Name]; ok { // svcNodes collects the list of all node Ids for each service version @@ -277,11 +277,11 @@ func (m *Registry) Deregister(s *registry.Service) error { // if there are no more services we know we have either removed all nodes or there were no nodes if updatedService := registry.Remove(service, []*registry.Service{s}); len(updatedService) == 0 { for _, id := range svcNodes[s.Name][s.Version] { - log.Debugf("Registry stopped tracking node %s for service %s", id, s.Name) + log.Debugf("[memory] Registry stopped tracking node %s for service %s", id, s.Name) delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) go m.sendEvent(®istry.Result{Action: "delete", Service: s}) } - log.Debugf("Registry deleting service %s: no service nodes", s.Name) + log.Debugf("[memory] Registry deleting service %s: no service nodes", s.Name) delete(m.Services, s.Name) return nil } else { @@ -296,7 +296,7 @@ func (m *Registry) Deregister(s *registry.Service) error { } } if !found { - log.Debugf("Registry stopped tracking node %s for service %s", id, s.Name) + log.Debugf("[memory] Registry stopped tracking node %s for service %s", id, s.Name) delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) go m.sendEvent(®istry.Result{Action: "delete", Service: s}) } From 5d77ce9e9bb13aca61f44100e2932c2821bf2ae7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 2 Oct 2019 12:35:20 +0100 Subject: [PATCH 015/344] Rename rcache file to cache --- registry/cache/{rcache.go => cache.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename registry/cache/{rcache.go => cache.go} (100%) diff --git a/registry/cache/rcache.go b/registry/cache/cache.go similarity index 100% rename from registry/cache/rcache.go rename to registry/cache/cache.go From 308424488b447204b3ef833f05add36c45dc80f5 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 2 Oct 2019 15:22:44 +0100 Subject: [PATCH 016/344] Hash the network address --- network/default.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/network/default.go b/network/default.go index 770f7f0f..e18ce772 100644 --- a/network/default.go +++ b/network/default.go @@ -86,17 +86,25 @@ func newNetwork(opts ...Option) Network { tun.WithTunnel(options.Tunnel), ) + // set the address to a hashed address + hasher := fnv.New64() + hasher.Write([]byte(options.Address + options.Id)) + address := fmt.Sprintf("%d", hasher.Sum64()) + // set the address to advertise - address := options.Address + var advertise string + if len(options.Advertise) > 0 { - address = options.Advertise + advertise = options.Advertise + } else { + advertise = options.Address } // server is network server server := server.NewServer( server.Id(options.Id), - server.Address(options.Id), - server.Advertise(address), + server.Address(address), + server.Advertise(advertise), server.Name(options.Name), server.Transport(tunTransport), ) @@ -728,7 +736,6 @@ func (n *network) Connect() error { // set our internal node address // if advertise address is not set if len(n.options.Advertise) == 0 { - n.node.address = n.tunnel.Address() n.server.Init(server.Advertise(n.tunnel.Address())) } From 2370fb12097bdc71e4de93c34647ce2badf5e6bb Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 2 Oct 2019 15:52:31 +0100 Subject: [PATCH 017/344] Set gateway to node address rather than id --- network/default.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index e18ce772..8d482b24 100644 --- a/network/default.go +++ b/network/default.go @@ -683,7 +683,7 @@ func (n *network) advertise(client transport.Client, advertChan <-chan *router.A route := &pbRtr.Route{ Service: event.Route.Service, Address: address, - Gateway: n.node.id, + Gateway: n.node.Address(), Network: event.Route.Network, Router: event.Route.Router, Link: DefaultLink, From b6db0d2663e74f91858a74ddb9f8def9a40e491d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 2 Oct 2019 17:42:34 +0100 Subject: [PATCH 018/344] Add ability to set log prefix --- util/log/log.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/util/log/log.go b/util/log/log.go index c8ae4acc..32992545 100644 --- a/util/log/log.go +++ b/util/log/log.go @@ -2,6 +2,7 @@ package log import ( + "fmt" "os" "github.com/go-log/log" @@ -25,6 +26,9 @@ var ( // default log level is info level = LevelInfo + + // prefix for all messages + prefix string ) func init() { @@ -44,11 +48,18 @@ func init() { // Log makes use of github.com/go-log/log.Log func Log(v ...interface{}) { + if len(prefix) > 0 { + logger.Log(append([]interface{}{prefix, " "}, v...)...) + return + } logger.Log(v...) } // Logf makes use of github.com/go-log/log.Logf func Logf(format string, v ...interface{}) { + if len(prefix) > 0 { + format = prefix + " " + format + } logger.Logf(format, v...) } @@ -139,3 +150,13 @@ func SetLevel(l Level) { func GetLevel() Level { return level } + +// Set a prefix for the logger +func SetPrefix(p string) { + prefix = p +} + +// Set service name +func Name(name string) { + prefix = fmt.Sprintf("[%s]", name) +} From 25148af44cb6e666bc9723fe0331566e10a163fc Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 2 Oct 2019 18:56:53 +0100 Subject: [PATCH 019/344] First commit to add etcd registry support --- config/cmd/cmd.go | 4 +- go.mod | 6 + go.sum | 12 ++ registry/etcd/etcd.go | 309 +++++++++++++++++++++++++++++++++++++++ registry/etcd/options.go | 24 +++ registry/etcd/watcher.go | 88 +++++++++++ 6 files changed, 442 insertions(+), 1 deletion(-) create mode 100644 registry/etcd/etcd.go create mode 100644 registry/etcd/options.go create mode 100644 registry/etcd/watcher.go diff --git a/config/cmd/cmd.go b/config/cmd/cmd.go index d6ee3eb2..82d4714c 100644 --- a/config/cmd/cmd.go +++ b/config/cmd/cmd.go @@ -27,6 +27,7 @@ import ( // registries "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/consul" + "github.com/micro/go-micro/registry/etcd" "github.com/micro/go-micro/registry/gossip" "github.com/micro/go-micro/registry/mdns" rmem "github.com/micro/go-micro/registry/memory" @@ -154,7 +155,7 @@ var ( cli.StringFlag{ Name: "registry", EnvVar: "MICRO_REGISTRY", - Usage: "Registry for discovery. consul, mdns", + Usage: "Registry for discovery. consul, etcd, mdns", }, cli.StringFlag{ Name: "registry_address", @@ -194,6 +195,7 @@ var ( "go.micro.registry": regSrv.NewRegistry, "service": regSrv.NewRegistry, "consul": consul.NewRegistry, + "etcd": etcd.NewRegistry, "gossip": gossip.NewRegistry, "mdns": mdns.NewRegistry, "memory": rmem.NewRegistry, diff --git a/go.mod b/go.mod index 0dfd6091..f5889f4e 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,9 @@ require ( github.com/beevik/ntp v0.2.0 github.com/bitly/go-simplejson v0.5.0 github.com/bwmarrin/discordgo v0.19.0 + github.com/coreos/etcd v3.3.15+incompatible + github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect + github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c github.com/fsnotify/fsnotify v1.4.7 github.com/fsouza/go-dockerclient v1.4.4 @@ -33,6 +36,9 @@ require ( github.com/nlopes/slack v0.6.0 github.com/pkg/errors v0.8.1 github.com/technoweenie/multipartstreamer v1.0.1 // indirect + go.uber.org/atomic v1.4.0 // indirect + go.uber.org/multierr v1.2.0 // indirect + go.uber.org/zap v1.10.0 // indirect golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 google.golang.org/grpc v1.24.0 diff --git a/go.sum b/go.sum index ae387d3e..648484b8 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,12 @@ github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wX 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/coreos/etcd v3.3.15+incompatible h1:+9RjdC18gMxNQVvSiXvObLu29mOFmkgdsB4cRTlV+EE= +github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/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/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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= @@ -209,6 +215,12 @@ github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQ github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4= +go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 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= diff --git a/registry/etcd/etcd.go b/registry/etcd/etcd.go new file mode 100644 index 00000000..495eed91 --- /dev/null +++ b/registry/etcd/etcd.go @@ -0,0 +1,309 @@ +// Package etcd provides an etcd service registry +package etcd + +import ( + "context" + "crypto/tls" + "encoding/json" + "errors" + "path" + "strings" + "sync" + "time" + + "github.com/coreos/etcd/clientv3" + "github.com/micro/go-micro/registry" + + "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" + hash "github.com/mitchellh/hashstructure" +) + +var ( + prefix = "/micro-registry" +) + +type etcdRegistry struct { + client *clientv3.Client + options registry.Options + sync.Mutex + register map[string]uint64 + leases map[string]clientv3.LeaseID +} + +func NewRegistry(opts ...registry.Option) registry.Registry { + e := &etcdRegistry{ + options: registry.Options{}, + register: make(map[string]uint64), + leases: make(map[string]clientv3.LeaseID), + } + configure(e, opts...) + return e +} + +func configure(e *etcdRegistry, opts ...registry.Option) error { + config := clientv3.Config{ + Endpoints: []string{"127.0.0.1:2379"}, + } + + for _, o := range opts { + o(&e.options) + } + + if e.options.Timeout == 0 { + e.options.Timeout = 5 * time.Second + } + + if e.options.Secure || e.options.TLSConfig != nil { + tlsConfig := e.options.TLSConfig + if tlsConfig == nil { + tlsConfig = &tls.Config{ + InsecureSkipVerify: true, + } + } + + config.TLS = tlsConfig + } + + if e.options.Context != nil { + u, ok := e.options.Context.Value(authKey{}).(*authCreds) + if ok { + config.Username = u.Username + config.Password = u.Password + } + } + + var cAddrs []string + + for _, addr := range e.options.Addrs { + if len(addr) == 0 { + continue + } + cAddrs = append(cAddrs, addr) + } + + // if we got addrs then we'll update + if len(cAddrs) > 0 { + config.Endpoints = cAddrs + } + + cli, err := clientv3.New(config) + if err != nil { + return err + } + e.client = cli + return nil +} + +func encode(s *registry.Service) string { + b, _ := json.Marshal(s) + return string(b) +} + +func decode(ds []byte) *registry.Service { + var s *registry.Service + json.Unmarshal(ds, &s) + return s +} + +func nodePath(s, id string) string { + service := strings.Replace(s, "/", "-", -1) + node := strings.Replace(id, "/", "-", -1) + return path.Join(prefix, service, node) +} + +func servicePath(s string) string { + return path.Join(prefix, strings.Replace(s, "/", "-", -1)) +} + +func (e *etcdRegistry) Init(opts ...registry.Option) error { + return configure(e, opts...) +} + +func (e *etcdRegistry) Options() registry.Options { + return e.options +} + +func (e *etcdRegistry) Deregister(s *registry.Service) error { + if len(s.Nodes) == 0 { + return errors.New("Require at least one node") + } + + e.Lock() + // delete our hash of the service + delete(e.register, s.Name) + // delete our lease of the service + delete(e.leases, s.Name) + e.Unlock() + + ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) + defer cancel() + + for _, node := range s.Nodes { + _, err := e.client.Delete(ctx, nodePath(s.Name, node.Id)) + if err != nil { + return err + } + } + return nil +} + +func (e *etcdRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { + if len(s.Nodes) == 0 { + return errors.New("Require at least one node") + } + + var leaseNotFound bool + //refreshing lease if existing + leaseID, ok := e.leases[s.Name] + if ok { + if _, err := e.client.KeepAliveOnce(context.TODO(), leaseID); err != nil { + if err != rpctypes.ErrLeaseNotFound { + return err + } + + // lease not found do register + leaseNotFound = true + } + } + + // create hash of service; uint64 + h, err := hash.Hash(s, nil) + if err != nil { + return err + } + + // get existing hash + e.Lock() + v, ok := e.register[s.Name] + e.Unlock() + + // the service is unchanged, skip registering + if ok && v == h && !leaseNotFound { + return nil + } + + service := ®istry.Service{ + Name: s.Name, + Version: s.Version, + Metadata: s.Metadata, + Endpoints: s.Endpoints, + } + + var options registry.RegisterOptions + for _, o := range opts { + o(&options) + } + + ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) + defer cancel() + + var lgr *clientv3.LeaseGrantResponse + if options.TTL.Seconds() > 0 { + lgr, err = e.client.Grant(ctx, int64(options.TTL.Seconds())) + if err != nil { + return err + } + } + + for _, node := range s.Nodes { + service.Nodes = []*registry.Node{node} + if lgr != nil { + _, err = e.client.Put(ctx, nodePath(service.Name, node.Id), encode(service), clientv3.WithLease(lgr.ID)) + } else { + _, err = e.client.Put(ctx, nodePath(service.Name, node.Id), encode(service)) + } + if err != nil { + return err + } + } + + e.Lock() + // save our hash of the service + e.register[s.Name] = h + // save our leaseID of the service + if lgr != nil { + e.leases[s.Name] = lgr.ID + } + e.Unlock() + + return nil +} + +func (e *etcdRegistry) GetService(name string) ([]*registry.Service, error) { + ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) + defer cancel() + + rsp, err := e.client.Get(ctx, servicePath(name)+"/", clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortDescend)) + if err != nil { + return nil, err + } + + if len(rsp.Kvs) == 0 { + return nil, registry.ErrNotFound + } + + serviceMap := map[string]*registry.Service{} + + for _, n := range rsp.Kvs { + if sn := decode(n.Value); sn != nil { + s, ok := serviceMap[sn.Version] + if !ok { + s = ®istry.Service{ + Name: sn.Name, + Version: sn.Version, + Metadata: sn.Metadata, + Endpoints: sn.Endpoints, + } + serviceMap[s.Version] = s + } + + for _, node := range sn.Nodes { + s.Nodes = append(s.Nodes, node) + } + } + } + + var services []*registry.Service + for _, service := range serviceMap { + services = append(services, service) + } + return services, nil +} + +func (e *etcdRegistry) ListServices() ([]*registry.Service, error) { + var services []*registry.Service + nameSet := make(map[string]struct{}) + + ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) + defer cancel() + + rsp, err := e.client.Get(ctx, prefix, clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortDescend)) + if err != nil { + return nil, err + } + + if len(rsp.Kvs) == 0 { + return []*registry.Service{}, nil + } + + for _, n := range rsp.Kvs { + if sn := decode(n.Value); sn != nil { + nameSet[sn.Name] = struct{}{} + } + } + for k := range nameSet { + service := ®istry.Service{} + service.Name = k + services = append(services, service) + } + + return services, nil +} + +func (e *etcdRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { + return newEtcdWatcher(e, e.options.Timeout, opts...) +} + +func (e *etcdRegistry) String() string { + return "etcd" +} diff --git a/registry/etcd/options.go b/registry/etcd/options.go new file mode 100644 index 00000000..46bacc09 --- /dev/null +++ b/registry/etcd/options.go @@ -0,0 +1,24 @@ +package etcd + +import ( + "context" + + "github.com/micro/go-micro/registry" +) + +type authKey struct{} + +type authCreds struct { + Username string + Password string +} + +// Auth allows you to specify username/password +func Auth(username, password string) registry.Option { + return func(o *registry.Options) { + if o.Context == nil { + o.Context = context.Background() + } + o.Context = context.WithValue(o.Context, authKey{}, &authCreds{Username: username, Password: password}) + } +} diff --git a/registry/etcd/watcher.go b/registry/etcd/watcher.go new file mode 100644 index 00000000..4eef76ba --- /dev/null +++ b/registry/etcd/watcher.go @@ -0,0 +1,88 @@ +package etcd + +import ( + "context" + "errors" + "time" + + "github.com/coreos/etcd/clientv3" + "github.com/micro/go-micro/registry" +) + +type etcdWatcher struct { + stop chan bool + w clientv3.WatchChan + client *clientv3.Client + timeout time.Duration +} + +func newEtcdWatcher(r *etcdRegistry, timeout time.Duration, opts ...registry.WatchOption) (registry.Watcher, error) { + var wo registry.WatchOptions + for _, o := range opts { + o(&wo) + } + + ctx, cancel := context.WithCancel(context.Background()) + stop := make(chan bool, 1) + + go func() { + <-stop + cancel() + }() + + watchPath := prefix + if len(wo.Service) > 0 { + watchPath = servicePath(wo.Service) + "/" + } + + return &etcdWatcher{ + stop: stop, + w: r.client.Watch(ctx, watchPath, clientv3.WithPrefix(), clientv3.WithPrevKV()), + client: r.client, + timeout: timeout, + }, nil +} + +func (ew *etcdWatcher) Next() (*registry.Result, error) { + for wresp := range ew.w { + if wresp.Err() != nil { + return nil, wresp.Err() + } + for _, ev := range wresp.Events { + service := decode(ev.Kv.Value) + var action string + + switch ev.Type { + case clientv3.EventTypePut: + if ev.IsCreate() { + action = "create" + } else if ev.IsModify() { + action = "update" + } + case clientv3.EventTypeDelete: + action = "delete" + + // get service from prevKv + service = decode(ev.PrevKv.Value) + } + + if service == nil { + continue + } + return ®istry.Result{ + Action: action, + Service: service, + }, nil + } + } + return nil, errors.New("could not get next") +} + +func (ew *etcdWatcher) Stop() { + select { + case <-ew.stop: + return + default: + close(ew.stop) + } +} From 31026da2a1f2898f8673aac0bb9e2144637b3cfd Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 2 Oct 2019 20:33:59 +0100 Subject: [PATCH 020/344] Update etcd.go Use /micro/registry as the etcd key prefix --- registry/etcd/etcd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/etcd/etcd.go b/registry/etcd/etcd.go index 495eed91..c4419487 100644 --- a/registry/etcd/etcd.go +++ b/registry/etcd/etcd.go @@ -19,7 +19,7 @@ import ( ) var ( - prefix = "/micro-registry" + prefix = "/micro/registry" ) type etcdRegistry struct { From 8d2b12258f4b891fb5637ff44b9402a5b5ad4c61 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 09:29:48 +0100 Subject: [PATCH 021/344] Remove gossip registry --- config/cmd/cmd.go | 2 - registry/gossip/README.md | 24 - registry/gossip/gossip.go | 848 -------------------------- registry/gossip/gossip_test.go | 214 ------- registry/gossip/options.go | 58 -- registry/gossip/proto/gossip.micro.go | 28 - registry/gossip/proto/gossip.pb.go | 127 ---- registry/gossip/proto/gossip.proto | 17 - registry/gossip/watcher.go | 53 -- 9 files changed, 1371 deletions(-) delete mode 100644 registry/gossip/README.md delete mode 100644 registry/gossip/gossip.go delete mode 100644 registry/gossip/gossip_test.go delete mode 100644 registry/gossip/options.go delete mode 100644 registry/gossip/proto/gossip.micro.go delete mode 100644 registry/gossip/proto/gossip.pb.go delete mode 100644 registry/gossip/proto/gossip.proto delete mode 100644 registry/gossip/watcher.go diff --git a/config/cmd/cmd.go b/config/cmd/cmd.go index 82d4714c..cfb8b313 100644 --- a/config/cmd/cmd.go +++ b/config/cmd/cmd.go @@ -28,7 +28,6 @@ import ( "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/consul" "github.com/micro/go-micro/registry/etcd" - "github.com/micro/go-micro/registry/gossip" "github.com/micro/go-micro/registry/mdns" rmem "github.com/micro/go-micro/registry/memory" regSrv "github.com/micro/go-micro/registry/service" @@ -196,7 +195,6 @@ var ( "service": regSrv.NewRegistry, "consul": consul.NewRegistry, "etcd": etcd.NewRegistry, - "gossip": gossip.NewRegistry, "mdns": mdns.NewRegistry, "memory": rmem.NewRegistry, } diff --git a/registry/gossip/README.md b/registry/gossip/README.md deleted file mode 100644 index bfeca969..00000000 --- a/registry/gossip/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Gossip Registry - -Gossip is a zero dependency registry which uses github.com/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 -``` diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go deleted file mode 100644 index 416422f1..00000000 --- a/registry/gossip/gossip.go +++ /dev/null @@ -1,848 +0,0 @@ -// Package gossip provides a gossip registry based on hashicorp/memberlist -package gossip - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "net" - "os" - "strconv" - "strings" - "sync" - "time" - - "github.com/golang/protobuf/proto" - "github.com/google/uuid" - "github.com/hashicorp/memberlist" - "github.com/micro/go-micro/registry" - pb "github.com/micro/go-micro/registry/gossip/proto" - log "github.com/micro/go-micro/util/log" - "github.com/mitchellh/hashstructure" -) - -// use registry.Result int32 values after it switches from string to int32 types -// type actionType int32 -// type updateType int32 - -const ( - actionTypeInvalid int32 = iota - actionTypeCreate - actionTypeDelete - actionTypeUpdate - actionTypeSync -) - -const ( - nodeActionUnknown int32 = iota - nodeActionJoin - nodeActionLeave - nodeActionUpdate -) - -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 { - update *pb.Update - notify chan<- struct{} -} - -type delegate struct { - queue *memberlist.TransmitLimitedQueue - updates chan *update -} - -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 - - watchers map[string]chan *registry.Result - - mtu int - addrs []string - members map[string]int32 - done chan bool -} - -type update struct { - Update *pb.Update - Service *registry.Service - 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 - ExpiryTick = time.Second * 1 // needs to be smaller than registry.RegisterTTL - MaxPacketSize = 512 -) - -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 - g.Stop() - - // lock internals - g.Lock() - - // new done chan - g.done = make(chan bool) - - // replace addresses - curAddrs = newAddrs - - // create a new default config - c := memberlist.DefaultLocalConfig() - - // 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 - - // set config from options - if config, ok := g.options.Context.Value(configKey{}).(*memberlist.Config); ok && config != nil { - c = config - } - - // set address - if address, ok := g.options.Context.Value(addressKey{}).(string); ok { - host, port, err := net.SplitHostPort(address) - if err == nil { - p, err := strconv.Atoi(port) - if err == nil { - c.BindPort = p - } - c.BindAddr = host - } - } else { - // set bind to random port - c.BindPort = 0 - } - - // set the advertise address - if advertise, ok := g.options.Context.Value(advertiseKey{}).(string); ok { - host, port, err := net.SplitHostPort(advertise) - if err == nil { - p, err := strconv.Atoi(port) - if err == nil { - c.AdvertisePort = p - } - c.AdvertiseAddr = host - } - } - - // machine hostname - hostname, _ := os.Hostname() - - // set the name - c.Name = strings.Join([]string{"micro", hostname, uuid.New().String()}, "-") - - // set a secret key if secure - if g.options.Secure { - k, ok := g.options.Context.Value(secretKey{}).([]byte) - if !ok { - // use the default secret - k = DefaultSecret - } - c.SecretKey = k - } - - // set connect retry - if v, ok := g.options.Context.Value(connectRetryKey{}).(bool); ok && v { - g.connectRetry = true - } - - // set connect timeout - if td, ok := g.options.Context.Value(connectTimeoutKey{}).(time.Duration); ok { - g.connectTimeout = td - } - - // 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, - } - - if g.connectRetry { - c.Events = &eventDelegate{ - events: g.events, - } - } - // create the memberlist - m, err := memberlist.Create(c) - if err != nil { - return err - } - - 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()) - - // try connect - return g.connect(curAddrs) -} - -func (*broadcast) UniqueBroadcast() {} - -func (b *broadcast) Invalidates(other memberlist.Broadcast) bool { - return false -} - -func (b *broadcast) Message() []byte { - up, err := proto.Marshal(b.update) - if err != nil { - return nil - } - if l := len(up); l > MaxPacketSize { - log.Logf("[gossip] Registry broadcast message size %d bigger then MaxPacketSize %d", l, MaxPacketSize) - } - 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 - } - - go func() { - up := new(pb.Update) - if err := proto.Unmarshal(b, up); err != nil { - return - } - - // only process service action - if up.Type != updateTypeService { - 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 - } - - // send update - d.updates <- &update{ - Update: up, - Service: service, - } - }() -} - -func (d *delegate) GetBroadcasts(overhead, limit int) [][]byte { - return d.queue.GetBroadcasts(overhead, limit) -} - -func (d *delegate) LocalState(join bool) []byte { - if !join { - return []byte{} - } - - syncCh := make(chan *registry.Service, 1) - services := map[string][]*registry.Service{} - - d.updates <- &update{ - Update: &pb.Update{ - Action: actionTypeSync, - }, - sync: syncCh, - } - - for srv := range syncCh { - services[srv.Name] = append(services[srv.Name], srv) - } - - b, _ := json.Marshal(services) - 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 - } - for _, service := range services { - for _, srv := range service { - d.updates <- &update{ - Update: &pb.Update{Action: actionTypeCreate}, - Service: srv, - sync: nil, - } - } - } -} - -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] Registry connect timeout %v", g.addrs) - // got a tick, try to connect - case <-ticker.C: - if _, err := fn(); err == nil { - log.Debugf("[gossip] Registry connect success for %v", g.addrs) - return nil - } else { - log.Debugf("[gossip] Registry connect failed for %v", g.addrs) - } - } - } - - return nil -} - -func (g *gossipRegistry) publish(action string, services []*registry.Service) { - g.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.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.Lock() - g.watchers[id] = next - g.Unlock() - - go func() { - <-exit - g.Lock() - delete(g.watchers, id) - close(next) - g.Unlock() - }() - - return next, exit -} - -func (g *gossipRegistry) Stop() error { - select { - case <-g.done: - return nil - default: - close(g.done) - g.Lock() - 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() - - g.RLock() - done := g.done - g.RUnlock() - - for { - select { - case <-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() { - g.RLock() - done := g.done - g.RUnlock() - for { - select { - // return when done - case <-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() { - updates := &updates{ - services: make(map[uint64]*update), - } - - // expiry loop - go g.expiryLoop(updates) - - // 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 { - switch u.Update.Action { - case actionTypeCreate: - 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] = registry.Merge(service, []*registry.Service{u.Service}) - } - g.Unlock() - - // publish update to watchers - 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 { - // create a hash of this service - if hash, err := hashstructure.Hash(u.Service, nil); err == nil { - updates.Lock() - updates.services[hash] = u - updates.Unlock() - } - } - case actionTypeDelete: - g.Lock() - if service, ok := g.services[u.Service.Name]; ok { - if services := registry.Remove(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(actionTypeString(actionTypeDelete), []*registry.Service{u.Service}) - - // delete from expiry checks - if hash, err := hashstructure.Hash(u.Service, nil); err == nil { - updates.Lock() - delete(updates.services, hash) - updates.Unlock() - } - case actionTypeSync: - // 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(actionTypeString(actionTypeCreate), service) - } - - g.RUnlock() - - // close the sync chan - close(u.sync) - } - } -} - -func (g *gossipRegistry) Init(opts ...registry.Option) error { - return configure(g, opts...) -} - -func (g *gossipRegistry) Options() registry.Options { - return g.options -} - -func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { - log.Debugf("[gossip] Registry registering service: %s", s.Name) - - b, err := json.Marshal(s) - if err != nil { - return err - } - - g.Lock() - if service, ok := g.services[s.Name]; !ok { - g.services[s.Name] = []*registry.Service{s} - } else { - g.services[s.Name] = registry.Merge(service, []*registry.Service{s}) - } - g.Unlock() - - var options registry.RegisterOptions - for _, o := range opts { - o(&options) - } - - if options.TTL == 0 && g.tcpInterval == 0 { - return fmt.Errorf("[gossip] Require register TTL or interval for memberlist.Config") - } - - up := &pb.Update{ - Expires: uint64(time.Now().Add(options.TTL).UnixNano()), - Action: actionTypeCreate, - Type: updateTypeService, - Metadata: map[string]string{ - "Content-Type": "application/json", - }, - Data: b, - } - - g.queue.QueueBroadcast(&broadcast{ - update: up, - notify: nil, - }) - - // send update to local watchers - g.updates <- &update{ - Update: up, - Service: s, - } - - // wait - <-time.After(g.interval * 2) - - return nil -} - -func (g *gossipRegistry) Deregister(s *registry.Service) error { - - log.Debugf("[gossip] Registry deregistering service: %s", s.Name) - - b, err := json.Marshal(s) - if err != nil { - return err - } - - g.Lock() - if service, ok := g.services[s.Name]; ok { - if services := registry.Remove(service, []*registry.Service{s}); len(services) == 0 { - delete(g.services, s.Name) - } else { - g.services[s.Name] = services - } - } - g.Unlock() - - up := &pb.Update{ - Action: actionTypeDelete, - Type: updateTypeService, - Metadata: map[string]string{ - "Content-Type": "application/json", - }, - Data: b, - } - - g.queue.QueueBroadcast(&broadcast{ - update: up, - notify: nil, - }) - - // send update to local watchers - g.updates <- &update{ - Update: up, - Service: s, - } - - // wait - <-time.After(g.interval * 2) - - return nil -} - -func (g *gossipRegistry) GetService(name string) ([]*registry.Service, error) { - g.RLock() - service, ok := g.services[name] - g.RUnlock() - if !ok { - return nil, registry.ErrNotFound - } - return service, nil -} - -func (g *gossipRegistry) ListServices() ([]*registry.Service, error) { - var services []*registry.Service - g.RLock() - for _, service := range g.services { - services = append(services, service...) - } - g.RUnlock() - return services, nil -} - -func (g *gossipRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { - n, e := g.subscribe() - return newGossipWatcher(n, e, opts...) -} - -func (g *gossipRegistry) String() string { - return "gossip" -} - -func NewRegistry(opts ...registry.Option) registry.Registry { - g := &gossipRegistry{ - options: registry.Options{ - Context: context.Background(), - }, - 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), - members: make(map[string]int32), - } - // run the updater - go g.run() - - // configure the gossiper - if err := configure(g, opts...); err != nil { - log.Fatalf("[gossip] Registry configuring error: %v", err) - } - // wait for setup - <-time.After(g.interval * 2) - - return g -} diff --git a/registry/gossip/gossip_test.go b/registry/gossip/gossip_test.go deleted file mode 100644 index 9154d08d..00000000 --- a/registry/gossip/gossip_test.go +++ /dev/null @@ -1,214 +0,0 @@ -package gossip - -import ( - "os" - "sync" - "testing" - "time" - - "github.com/google/uuid" - "github.com/hashicorp/memberlist" - "github.com/micro/go-micro/registry" -) - -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 newRegistry(opts ...registry.Option) registry.Registry { - options := []registry.Option{ - ConnectRetry(true), - ConnectTimeout(60 * time.Second), - } - - options = append(options, opts...) - r := NewRegistry(options...) - return r -} - -func TestGossipRegistryBroadcast(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.1:54322"), registry.Addrs("127.0.0.1:54321")) - - defer r1.(*gossipRegistry).Stop() - defer r2.(*gossipRegistry).Stop() - - svc1 := ®istry.Service{Name: "service.1", Version: "0.0.0.1"} - svc2 := ®istry.Service{Name: "service.2", Version: "0.0.0.2"} - - if err := r1.Register(svc1, registry.RegisterTTL(10*time.Second)); err != nil { - t.Fatal(err) - } - if err := r2.Register(svc2, registry.RegisterTTL(10*time.Second)); 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 == "service.2" { - found = true - } - } - if !found { - t.Fatalf("[gossip registry] service.2 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 == "service.1" { - found = true - } - } - - if !found { - t.Fatalf("[gossip registry] broadcast failed: service.1 not found in r2") - } - - if err := r1.Deregister(svc1); err != nil { - t.Fatal(err) - } - if err := r2.Deregister(svc2); err != nil { - t.Fatal(err) - } - -} -func TestGossipRegistryRetry(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.1:54322"), registry.Addrs("127.0.0.1:54321")) - - defer r1.(*gossipRegistry).Stop() - defer r2.(*gossipRegistry).Stop() - - 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{}) - 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 == "service.1" { - found = true - } - } - - if !found { - t.Fatalf("[gossip registry] broadcast failed: service.1 not found in r2") - } - - if err = r1.(*gossipRegistry).Stop(); err != nil { - t.Fatalf("[gossip registry] failed to stop 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 == "service.1" { - found = true - } - } - - if found { - t.Fatalf("[gossip registry] service.1 found in r2") - } - - 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) - - found = false - svcs, err = r2.ListServices() - if err != nil { - t.Fatal(err) - } - - for _, svc := range svcs { - if svc.Name == "service.1" { - found = true - } - } - - if !found { - t.Fatalf("[gossip registry] connect retry failed: service.1 not found in r2") - } - - if err := r1.Deregister(svc1); err != nil { - t.Fatal(err) - } - if err := r2.Deregister(svc2); err != nil { - t.Fatal(err) - } - - r1.(*gossipRegistry).Stop() - r2.(*gossipRegistry).Stop() -} diff --git a/registry/gossip/options.go b/registry/gossip/options.go deleted file mode 100644 index cf9dc9dc..00000000 --- a/registry/gossip/options.go +++ /dev/null @@ -1,58 +0,0 @@ -package gossip - -import ( - "context" - "time" - - "github.com/hashicorp/memberlist" - "github.com/micro/go-micro/registry" -) - -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(secretKey{}, k) -} - -// Address to bind to - host:port -func Address(a string) registry.Option { - return setRegistryOption(addressKey{}, a) -} - -// Config sets *memberlist.Config for configuring gossip -func Config(c *memberlist.Config) registry.Option { - return setRegistryOption(configKey{}, c) -} - -// The address to advertise for other gossip members to connect to - host:port -func Advertise(a string) registry.Option { - return setRegistryOption(advertiseKey{}, a) -} - -// ConnectTimeout sets the registry connect timeout. Use -1 to specify infinite timeout -func ConnectTimeout(td time.Duration) registry.Option { - return setRegistryOption(connectTimeoutKey{}, td) -} - -// ConnectRetry enables reconnect to registry then connection closed, -// use with ConnectTimeout to specify how long retry -func ConnectRetry(v bool) registry.Option { - return setRegistryOption(connectRetryKey{}, v) -} diff --git a/registry/gossip/proto/gossip.micro.go b/registry/gossip/proto/gossip.micro.go deleted file mode 100644 index fe9796d9..00000000 --- a/registry/gossip/proto/gossip.micro.go +++ /dev/null @@ -1,28 +0,0 @@ -// 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 deleted file mode 100644 index e5d692fc..00000000 --- a/registry/gossip/proto/gossip.pb.go +++ /dev/null @@ -1,127 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/micro/go-micro/registry/gossip/proto/gossip.proto - -package gossip - -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 -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 { - // time to live for entry - 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; - 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 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) GetExpires() uint64 { - if m != nil { - return m.Expires - } - return 0 -} - -func (m *Update) GetType() int32 { - if m != nil { - return m.Type - } - return 0 -} - -func (m *Update) GetAction() int32 { - if m != nil { - return m.Action - } - return 0 -} - -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") - proto.RegisterMapType((map[string]string)(nil), "gossip.Update.MetadataEntry") -} - -func init() { - proto.RegisterFile("github.com/micro/go-micro/registry/gossip/proto/gossip.proto", fileDescriptor_18cba623e76e57f3) -} - -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 deleted file mode 100644 index 21acaaa5..00000000 --- a/registry/gossip/proto/gossip.proto +++ /dev/null @@ -1,17 +0,0 @@ -syntax = "proto3"; - -package gossip; - -// Update is the message broadcast -message Update { - // time to live for entry - 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; - bytes data = 7; -} diff --git a/registry/gossip/watcher.go b/registry/gossip/watcher.go deleted file mode 100644 index 57b35521..00000000 --- a/registry/gossip/watcher.go +++ /dev/null @@ -1,53 +0,0 @@ -package gossip - -import ( - "github.com/micro/go-micro/registry" -) - -type gossipWatcher struct { - wo registry.WatchOptions - next chan *registry.Result - stop chan bool -} - -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, ok := <-m.next: - if !ok { - return nil, registry.ErrWatcherStopped - } - // check watch options - if len(m.wo.Service) > 0 && r.Service.Name != m.wo.Service { - continue - } - nr := ®istry.Result{} - *nr = *r - return nr, nil - case <-m.stop: - return nil, registry.ErrWatcherStopped - } - } -} - -func (m *gossipWatcher) Stop() { - select { - case <-m.stop: - return - default: - close(m.stop) - } -} From b5ca40a91ad89baba40bc7870fae90900367a0a8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 09:46:20 +0100 Subject: [PATCH 022/344] Move out consul sync/lock and store. Move data/store to store --- data/data.go | 2 - data/store/consul/consul.go | 96 ---------------- store/etcd/etcd.go | 91 ++++++++++++++++ {data/store => store}/memory/memory.go | 2 +- {data/store => store}/memory/memory_test.go | 2 +- {data/store => store}/options.go | 0 {data/store => store}/store.go | 0 sync/lock/consul/consul.go | 104 ------------------ sync/lock/etcd/etcd.go | 115 ++++++++++++++++++++ sync/map.go | 6 +- sync/options.go | 2 +- sync/sync.go | 2 +- 12 files changed, 213 insertions(+), 209 deletions(-) delete mode 100644 data/data.go delete mode 100644 data/store/consul/consul.go create mode 100644 store/etcd/etcd.go rename {data/store => store}/memory/memory.go (97%) rename {data/store => store}/memory/memory_test.go (93%) rename {data/store => store}/options.go (100%) rename {data/store => store}/store.go (100%) delete mode 100644 sync/lock/consul/consul.go create mode 100644 sync/lock/etcd/etcd.go diff --git a/data/data.go b/data/data.go deleted file mode 100644 index eb6157d2..00000000 --- a/data/data.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package data is an interface for data access -package data diff --git a/data/store/consul/consul.go b/data/store/consul/consul.go deleted file mode 100644 index 174d043c..00000000 --- a/data/store/consul/consul.go +++ /dev/null @@ -1,96 +0,0 @@ -// Package consul is a consul implementation of kv -package consul - -import ( - "fmt" - "net" - - "github.com/hashicorp/consul/api" - "github.com/micro/go-micro/config/options" - "github.com/micro/go-micro/data/store" -) - -type ckv struct { - options.Options - client *api.Client -} - -func (c *ckv) Read(key string) (*store.Record, error) { - keyval, _, err := c.client.KV().Get(key, nil) - if err != nil { - return nil, err - } - - if keyval == nil { - return nil, store.ErrNotFound - } - - return &store.Record{ - Key: keyval.Key, - Value: keyval.Value, - }, nil -} - -func (c *ckv) Delete(key string) error { - _, err := c.client.KV().Delete(key, nil) - return err -} - -func (c *ckv) Write(record *store.Record) error { - _, err := c.client.KV().Put(&api.KVPair{ - Key: record.Key, - Value: record.Value, - }, nil) - return err -} - -func (c *ckv) Dump() ([]*store.Record, error) { - keyval, _, err := c.client.KV().List("/", nil) - if err != nil { - return nil, err - } - if keyval == nil { - return nil, store.ErrNotFound - } - var vals []*store.Record - for _, keyv := range keyval { - vals = append(vals, &store.Record{ - Key: keyv.Key, - Value: keyv.Value, - }) - } - return vals, nil -} - -func (c *ckv) String() string { - return "consul" -} - -func NewStore(opts ...options.Option) store.Store { - options := options.NewOptions(opts...) - config := api.DefaultConfig() - - var nodes []string - - if n, ok := options.Values().Get("store.nodes"); ok { - nodes = n.([]string) - } - - // set host - if len(nodes) > 0 { - addr, port, err := net.SplitHostPort(nodes[0]) - if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { - port = "8500" - config.Address = fmt.Sprintf("%s:%s", nodes[0], port) - } else if err == nil { - config.Address = fmt.Sprintf("%s:%s", addr, port) - } - } - - client, _ := api.NewClient(config) - - return &ckv{ - Options: options, - client: client, - } -} diff --git a/store/etcd/etcd.go b/store/etcd/etcd.go new file mode 100644 index 00000000..32994f26 --- /dev/null +++ b/store/etcd/etcd.go @@ -0,0 +1,91 @@ +// Package etcd is an etcd v3 implementation of kv +package etcd + +import ( + "context" + "log" + + client "github.com/coreos/etcd/clientv3" + "github.com/micro/go-micro/config/options" + "github.com/micro/go-micro/store" +) + +type ekv struct { + options.Options + kv client.KV +} + +func (e *ekv) Read(key string) (*store.Record, error) { + keyval, err := e.kv.Get(context.Background(), key) + if err != nil { + return nil, err + } + + if keyval == nil || len(keyval.Kvs) == 0 { + return nil, store.ErrNotFound + } + + return &store.Record{ + Key: string(keyval.Kvs[0].Key), + Value: keyval.Kvs[0].Value, + }, nil +} + +func (e *ekv) Delete(key string) error { + _, err := e.kv.Delete(context.Background(), key) + return err +} + +func (e *ekv) Write(record *store.Record) error { + _, err := e.kv.Put(context.Background(), record.Key, string(record.Value)) + return err +} + +func (e *ekv) Dump() ([]*store.Record, error) { + keyval, err := e.kv.Get(context.Background(), "/", client.WithPrefix()) + if err != nil { + return nil, err + } + var vals []*store.Record + if keyval == nil || len(keyval.Kvs) == 0 { + return vals, nil + } + for _, keyv := range keyval.Kvs { + vals = append(vals, &store.Record{ + Key: string(keyv.Key), + Value: keyv.Value, + }) + } + return vals, nil +} + +func (e *ekv) String() string { + return "etcd" +} + +func NewStore(opts ...options.Option) store.Store { + options := options.NewOptions(opts...) + + var endpoints []string + + if e, ok := options.Values().Get("store.nodes"); ok { + endpoints = e.([]string) + } + + if len(endpoints) == 0 { + endpoints = []string{"http://127.0.0.1:2379"} + } + + // TODO: parse addresses + c, err := client.New(client.Config{ + Endpoints: endpoints, + }) + if err != nil { + log.Fatal(err) + } + + return &ekv{ + Options: options, + kv: client.NewKV(c), + } +} diff --git a/data/store/memory/memory.go b/store/memory/memory.go similarity index 97% rename from data/store/memory/memory.go rename to store/memory/memory.go index bb7892e8..c8e7dd53 100644 --- a/data/store/memory/memory.go +++ b/store/memory/memory.go @@ -6,7 +6,7 @@ import ( "time" "github.com/micro/go-micro/config/options" - "github.com/micro/go-micro/data/store" + "github.com/micro/go-micro/store" ) type memoryStore struct { diff --git a/data/store/memory/memory_test.go b/store/memory/memory_test.go similarity index 93% rename from data/store/memory/memory_test.go rename to store/memory/memory_test.go index 44483869..639d18db 100644 --- a/data/store/memory/memory_test.go +++ b/store/memory/memory_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/micro/go-micro/data/store" + "github.com/micro/go-micro/store" ) func TestReadRecordExpire(t *testing.T) { diff --git a/data/store/options.go b/store/options.go similarity index 100% rename from data/store/options.go rename to store/options.go diff --git a/data/store/store.go b/store/store.go similarity index 100% rename from data/store/store.go rename to store/store.go diff --git a/sync/lock/consul/consul.go b/sync/lock/consul/consul.go deleted file mode 100644 index ef0f2dd4..00000000 --- a/sync/lock/consul/consul.go +++ /dev/null @@ -1,104 +0,0 @@ -// Package consul is a consul implemenation of lock -package consul - -import ( - "errors" - "fmt" - "net" - "sync" - "time" - - "github.com/hashicorp/consul/api" - lock "github.com/micro/go-micro/sync/lock" -) - -type consulLock struct { - sync.Mutex - - locks map[string]*api.Lock - opts lock.Options - c *api.Client -} - -func (c *consulLock) Acquire(id string, opts ...lock.AcquireOption) error { - var options lock.AcquireOptions - for _, o := range opts { - o(&options) - } - - if options.Wait <= time.Duration(0) { - options.Wait = api.DefaultLockWaitTime - } - - ttl := fmt.Sprintf("%v", options.TTL) - if options.TTL <= time.Duration(0) { - ttl = api.DefaultLockSessionTTL - } - - l, err := c.c.LockOpts(&api.LockOptions{ - Key: c.opts.Prefix + id, - LockWaitTime: options.Wait, - SessionTTL: ttl, - }) - - if err != nil { - return err - } - - _, err = l.Lock(nil) - if err != nil { - return err - } - - c.Lock() - c.locks[id] = l - c.Unlock() - - return nil -} - -func (c *consulLock) Release(id string) error { - c.Lock() - defer c.Unlock() - l, ok := c.locks[id] - if !ok { - return errors.New("lock not found") - } - err := l.Unlock() - delete(c.locks, id) - return err -} - -func (c *consulLock) String() string { - return "consul" -} - -func NewLock(opts ...lock.Option) lock.Lock { - var options lock.Options - for _, o := range opts { - o(&options) - } - - config := api.DefaultConfig() - - // set host - // config.Host something - // check if there are any addrs - if len(options.Nodes) > 0 { - addr, port, err := net.SplitHostPort(options.Nodes[0]) - if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { - port = "8500" - config.Address = fmt.Sprintf("%s:%s", options.Nodes[0], port) - } else if err == nil { - config.Address = fmt.Sprintf("%s:%s", addr, port) - } - } - - client, _ := api.NewClient(config) - - return &consulLock{ - locks: make(map[string]*api.Lock), - opts: options, - c: client, - } -} diff --git a/sync/lock/etcd/etcd.go b/sync/lock/etcd/etcd.go new file mode 100644 index 00000000..0b8ba823 --- /dev/null +++ b/sync/lock/etcd/etcd.go @@ -0,0 +1,115 @@ +// Package etcd is an etcd implementation of lock +package etcd + +import ( + "context" + "errors" + "log" + "path" + "strings" + "sync" + + client "github.com/coreos/etcd/clientv3" + cc "github.com/coreos/etcd/clientv3/concurrency" + "github.com/micro/go-micro/sync/lock" +) + +type etcdLock struct { + opts lock.Options + path string + client *client.Client + + sync.Mutex + locks map[string]*elock +} + +type elock struct { + s *cc.Session + m *cc.Mutex +} + +func (e *etcdLock) Acquire(id string, opts ...lock.AcquireOption) error { + var options lock.AcquireOptions + for _, o := range opts { + o(&options) + } + + // make path + path := path.Join(e.path, strings.Replace(e.opts.Prefix+id, "/", "-", -1)) + + var sopts []cc.SessionOption + if options.TTL > 0 { + sopts = append(sopts, cc.WithTTL(int(options.TTL.Seconds()))) + } + + s, err := cc.NewSession(e.client, sopts...) + if err != nil { + return err + } + + m := cc.NewMutex(s, path) + + ctx, _ := context.WithCancel(context.Background()) + + if err := m.Lock(ctx); err != nil { + return err + } + + e.Lock() + e.locks[id] = &elock{ + s: s, + m: m, + } + e.Unlock() + return nil +} + +func (e *etcdLock) Release(id string) error { + e.Lock() + defer e.Unlock() + v, ok := e.locks[id] + if !ok { + return errors.New("lock not found") + } + err := v.m.Unlock(context.Background()) + delete(e.locks, id) + return err +} + +func (e *etcdLock) String() string { + return "etcd" +} + +func NewLock(opts ...lock.Option) lock.Lock { + var options lock.Options + for _, o := range opts { + o(&options) + } + + var endpoints []string + + for _, addr := range options.Nodes { + if len(addr) > 0 { + endpoints = append(endpoints, addr) + } + } + + if len(endpoints) == 0 { + endpoints = []string{"http://127.0.0.1:2379"} + } + + // TODO: parse addresses + c, err := client.New(client.Config{ + Endpoints: endpoints, + }) + if err != nil { + log.Fatal(err) + } + + return &etcdLock{ + path: "/micro/lock", + client: c, + opts: options, + locks: make(map[string]*elock), + } +} diff --git a/sync/map.go b/sync/map.go index 5f7865e9..5913267b 100644 --- a/sync/map.go +++ b/sync/map.go @@ -6,9 +6,9 @@ import ( "encoding/json" "fmt" - "github.com/micro/go-micro/data/store" - ckv "github.com/micro/go-micro/data/store/consul" - lock "github.com/micro/go-micro/sync/lock/consul" + "github.com/micro/go-micro/store" + ckv "github.com/micro/go-micro/store/etcd" + lock "github.com/micro/go-micro/sync/lock/etcd" ) type syncMap struct { diff --git a/sync/options.go b/sync/options.go index 65f20e28..0e5cf3d0 100644 --- a/sync/options.go +++ b/sync/options.go @@ -1,7 +1,7 @@ package sync import ( - "github.com/micro/go-micro/data/store" + "github.com/micro/go-micro/store" "github.com/micro/go-micro/sync/leader" "github.com/micro/go-micro/sync/lock" "github.com/micro/go-micro/sync/time" diff --git a/sync/sync.go b/sync/sync.go index 27a6104a..7b080b1d 100644 --- a/sync/sync.go +++ b/sync/sync.go @@ -2,7 +2,7 @@ package sync import ( - "github.com/micro/go-micro/data/store" + "github.com/micro/go-micro/store" "github.com/micro/go-micro/sync/leader" "github.com/micro/go-micro/sync/lock" "github.com/micro/go-micro/sync/task" From b5f33b2aaa61e664213882b0f53197f1cc35749e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 09:56:25 +0100 Subject: [PATCH 023/344] Rename Dump to Sync --- store/etcd/etcd.go | 2 +- store/memory/memory.go | 2 +- store/store.go | 4 ++-- sync/map.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/store/etcd/etcd.go b/store/etcd/etcd.go index 32994f26..7d866d63 100644 --- a/store/etcd/etcd.go +++ b/store/etcd/etcd.go @@ -41,7 +41,7 @@ func (e *ekv) Write(record *store.Record) error { return err } -func (e *ekv) Dump() ([]*store.Record, error) { +func (e *ekv) Sync() ([]*store.Record, error) { keyval, err := e.kv.Get(context.Background(), "/", client.WithPrefix()) if err != nil { return nil, err diff --git a/store/memory/memory.go b/store/memory/memory.go index c8e7dd53..a7d5a83c 100644 --- a/store/memory/memory.go +++ b/store/memory/memory.go @@ -21,7 +21,7 @@ type memoryRecord struct { c time.Time } -func (m *memoryStore) Dump() ([]*store.Record, error) { +func (m *memoryStore) Sync() ([]*store.Record, error) { m.RLock() defer m.RUnlock() diff --git a/store/store.go b/store/store.go index e7241591..c6442947 100644 --- a/store/store.go +++ b/store/store.go @@ -16,8 +16,8 @@ var ( type Store interface { // embed options options.Options - // Dump the known records - Dump() ([]*Record, error) + // Sync all the known records + Sync() ([]*Record, error) // Read a record with key Read(key string) (*Record, error) // Write a record diff --git a/sync/map.go b/sync/map.go index 5913267b..a87bd988 100644 --- a/sync/map.go +++ b/sync/map.go @@ -85,7 +85,7 @@ func (m *syncMap) Delete(key interface{}) error { } func (m *syncMap) Iterate(fn func(key, val interface{}) error) error { - keyvals, err := m.opts.Store.Dump() + keyvals, err := m.opts.Store.Sync() if err != nil { return err } From af5d7a342091d56e7ebe71cac5992cc58e1b6014 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 11:22:35 +0100 Subject: [PATCH 024/344] Move the remaining consul cruft to go-plugins --- config/source/consul/README.md | 49 ------- config/source/consul/consul.go | 126 ----------------- config/source/consul/util.go | 89 ------------ config/source/consul/watcher.go | 95 ------------- config/source/etcd/README.md | 51 +++++++ config/source/etcd/etcd.go | 141 +++++++++++++++++++ config/source/{consul => etcd}/options.go | 39 +++--- config/source/etcd/util.go | 89 ++++++++++++ config/source/etcd/watcher.go | 113 ++++++++++++++++ sync/leader/consul/consul.go | 158 ---------------------- sync/leader/etcd/etcd.go | 145 ++++++++++++++++++++ 11 files changed, 556 insertions(+), 539 deletions(-) delete mode 100644 config/source/consul/README.md delete mode 100644 config/source/consul/consul.go delete mode 100644 config/source/consul/util.go delete mode 100644 config/source/consul/watcher.go create mode 100644 config/source/etcd/README.md create mode 100644 config/source/etcd/etcd.go rename config/source/{consul => etcd}/options.go (61%) create mode 100644 config/source/etcd/util.go create mode 100644 config/source/etcd/watcher.go delete mode 100644 sync/leader/consul/consul.go create mode 100644 sync/leader/etcd/etcd.go diff --git a/config/source/consul/README.md b/config/source/consul/README.md deleted file mode 100644 index 28006fc4..00000000 --- a/config/source/consul/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# Consul Source - -The consul source reads config from consul key/values - -## Consul Format - -The consul source expects keys under the default prefix `/micro/config` - -Values are expected to be json - -``` -// set database -consul kv put micro/config/database '{"address": "10.0.0.1", "port": 3306}' -// set cache -consul kv put micro/config/cache '{"address": "10.0.0.2", "port": 6379}' -``` - -Keys are split on `/` so access becomes - -``` -conf.Get("micro", "config", "database") -``` - -## New Source - -Specify source with data - -```go -consulSource := consul.NewSource( - // optionally specify consul address; default to localhost:8500 - consul.WithAddress("10.0.0.10:8500"), - // optionally specify prefix; defaults to /micro/config - consul.WithPrefix("/my/prefix"), - // optionally strip the provided prefix from the keys, defaults to false - consul.StripPrefix(true), -) -``` - -## Load Source - -Load the source into config - -```go -// Create new config -conf := config.NewConfig() - -// Load consul source -conf.Load(consulSource) -``` diff --git a/config/source/consul/consul.go b/config/source/consul/consul.go deleted file mode 100644 index f5c3c695..00000000 --- a/config/source/consul/consul.go +++ /dev/null @@ -1,126 +0,0 @@ -package consul - -import ( - "fmt" - "net" - "time" - - "github.com/hashicorp/consul/api" - "github.com/micro/go-micro/config/source" -) - -// Currently a single consul reader -type consul struct { - prefix string - stripPrefix string - addr string - opts source.Options - client *api.Client -} - -var ( - // DefaultPrefix is the prefix that consul keys will be assumed to have if you - // haven't specified one - DefaultPrefix = "/micro/config/" -) - -func (c *consul) Read() (*source.ChangeSet, error) { - kv, _, err := c.client.KV().List(c.prefix, nil) - if err != nil { - return nil, err - } - - if kv == nil || len(kv) == 0 { - return nil, fmt.Errorf("source not found: %s", c.prefix) - } - - data, err := makeMap(c.opts.Encoder, kv, c.stripPrefix) - if err != nil { - return nil, fmt.Errorf("error reading data: %v", err) - } - - b, err := c.opts.Encoder.Encode(data) - if err != nil { - return nil, fmt.Errorf("error reading source: %v", err) - } - - cs := &source.ChangeSet{ - Timestamp: time.Now(), - Format: c.opts.Encoder.String(), - Source: c.String(), - Data: b, - } - cs.Checksum = cs.Sum() - - return cs, nil -} - -func (c *consul) String() string { - return "consul" -} - -func (c *consul) Watch() (source.Watcher, error) { - w, err := newWatcher(c.prefix, c.addr, c.String(), c.stripPrefix, c.opts.Encoder) - if err != nil { - return nil, err - } - return w, nil -} - -// NewSource creates a new consul source -func NewSource(opts ...source.Option) source.Source { - options := source.NewOptions(opts...) - - // use default config - config := api.DefaultConfig() - - // use the consul config passed in the options if any - if co, ok := options.Context.Value(configKey{}).(*api.Config); ok { - config = co - } - - // check if there are any addrs - a, ok := options.Context.Value(addressKey{}).(string) - if ok { - addr, port, err := net.SplitHostPort(a) - if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { - port = "8500" - addr = a - config.Address = fmt.Sprintf("%s:%s", addr, port) - } else if err == nil { - config.Address = fmt.Sprintf("%s:%s", addr, port) - } - } - - dc, ok := options.Context.Value(dcKey{}).(string) - if ok { - config.Datacenter = dc - } - - token, ok := options.Context.Value(tokenKey{}).(string) - if ok { - config.Token = token - } - - // create the client - client, _ := api.NewClient(config) - - prefix := DefaultPrefix - sp := "" - f, ok := options.Context.Value(prefixKey{}).(string) - if ok { - prefix = f - } - - if b, ok := options.Context.Value(stripPrefixKey{}).(bool); ok && b { - sp = prefix - } - - return &consul{ - prefix: prefix, - stripPrefix: sp, - addr: config.Address, - opts: options, - client: client, - } -} diff --git a/config/source/consul/util.go b/config/source/consul/util.go deleted file mode 100644 index 1deacbb4..00000000 --- a/config/source/consul/util.go +++ /dev/null @@ -1,89 +0,0 @@ -package consul - -import ( - "fmt" - "strings" - - "github.com/hashicorp/consul/api" - "github.com/micro/go-micro/config/encoder" -) - -type configValue interface { - Value() interface{} - Decode(encoder.Encoder, []byte) error -} -type configArrayValue struct { - v []interface{} -} - -func (a *configArrayValue) Value() interface{} { return a.v } -func (a *configArrayValue) Decode(e encoder.Encoder, b []byte) error { - return e.Decode(b, &a.v) -} - -type configMapValue struct { - v map[string]interface{} -} - -func (m *configMapValue) Value() interface{} { return m.v } -func (m *configMapValue) Decode(e encoder.Encoder, b []byte) error { - return e.Decode(b, &m.v) -} - -func makeMap(e encoder.Encoder, kv api.KVPairs, stripPrefix string) (map[string]interface{}, error) { - - data := make(map[string]interface{}) - - // consul guarantees lexicographic order, so no need to sort - for _, v := range kv { - pathString := strings.TrimPrefix(strings.TrimPrefix(v.Key, strings.TrimPrefix(stripPrefix, "/")), "/") - if pathString == "" { - continue - } - var val configValue - var err error - - // ensure a valid value is stored at this location - if len(v.Value) > 0 { - // try to decode into map value or array value - arrayV := &configArrayValue{v: []interface{}{}} - mapV := &configMapValue{v: map[string]interface{}{}} - switch { - case arrayV.Decode(e, v.Value) == nil: - val = arrayV - case mapV.Decode(e, v.Value) == nil: - val = mapV - default: - return nil, fmt.Errorf("faild decode value. path: %s, error: %s", pathString, err) - } - } - - // set target at the root - target := data - path := strings.Split(pathString, "/") - // find (or create) the leaf node we want to put this value at - for _, dir := range path[:len(path)-1] { - if _, ok := target[dir]; !ok { - target[dir] = make(map[string]interface{}) - } - target = target[dir].(map[string]interface{}) - } - - leafDir := path[len(path)-1] - - // copy over the keys from the value - switch val.(type) { - case *configArrayValue: - target[leafDir] = val.Value() - case *configMapValue: - target[leafDir] = make(map[string]interface{}) - target = target[leafDir].(map[string]interface{}) - mapv := val.Value().(map[string]interface{}) - for k := range mapv { - target[k] = mapv[k] - } - } - } - - return data, nil -} diff --git a/config/source/consul/watcher.go b/config/source/consul/watcher.go deleted file mode 100644 index a20c8f9b..00000000 --- a/config/source/consul/watcher.go +++ /dev/null @@ -1,95 +0,0 @@ -package consul - -import ( - "time" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/api/watch" - "github.com/micro/go-micro/config/encoder" - "github.com/micro/go-micro/config/source" -) - -type watcher struct { - e encoder.Encoder - name string - stripPrefix string - - wp *watch.Plan - ch chan *source.ChangeSet - exit chan bool -} - -func newWatcher(key, addr, name, stripPrefix string, e encoder.Encoder) (source.Watcher, error) { - w := &watcher{ - e: e, - name: name, - stripPrefix: stripPrefix, - ch: make(chan *source.ChangeSet), - exit: make(chan bool), - } - - wp, err := watch.Parse(map[string]interface{}{"type": "keyprefix", "prefix": key}) - if err != nil { - return nil, err - } - - wp.Handler = w.handle - - // wp.Run is a blocking call and will prevent newWatcher from returning - go wp.Run(addr) - - w.wp = wp - - return w, nil -} - -func (w *watcher) handle(idx uint64, data interface{}) { - if data == nil { - return - } - - kvs, ok := data.(api.KVPairs) - if !ok { - return - } - - d, err := makeMap(w.e, kvs, w.stripPrefix) - if err != nil { - return - } - - b, err := w.e.Encode(d) - if err != nil { - return - } - - cs := &source.ChangeSet{ - Timestamp: time.Now(), - Format: w.e.String(), - Source: w.name, - Data: b, - } - cs.Checksum = cs.Sum() - - w.ch <- cs -} - -func (w *watcher) Next() (*source.ChangeSet, error) { - select { - case cs := <-w.ch: - return cs, nil - case <-w.exit: - return nil, source.ErrWatcherStopped - } -} - -func (w *watcher) Stop() error { - select { - case <-w.exit: - return nil - default: - w.wp.Stop() - close(w.exit) - } - return nil -} diff --git a/config/source/etcd/README.md b/config/source/etcd/README.md new file mode 100644 index 00000000..a3025ad4 --- /dev/null +++ b/config/source/etcd/README.md @@ -0,0 +1,51 @@ +# Etcd Source + +The etcd source reads config from etcd key/values + +This source supports etcd version 3 and beyond. + +## Etcd Format + +The etcd source expects keys under the default prefix `/micro/config` (prefix can be changed) + +Values are expected to be JSON + +``` +// set database +etcdctl put /micro/config/database '{"address": "10.0.0.1", "port": 3306}' +// set cache +etcdctl put /micro/config/cache '{"address": "10.0.0.2", "port": 6379}' +``` + +Keys are split on `/` so access becomes + +``` +conf.Get("micro", "config", "database") +``` + +## New Source + +Specify source with data + +```go +etcdSource := etcd.NewSource( + // optionally specify etcd address; default to localhost:8500 + etcd.WithAddress("10.0.0.10:8500"), + // optionally specify prefix; defaults to /micro/config + etcd.WithPrefix("/my/prefix"), + // optionally strip the provided prefix from the keys, defaults to false + etcd.StripPrefix(true), +) +``` + +## Load Source + +Load the source into config + +```go +// Create new config +conf := config.NewConfig() + +// Load file source +conf.Load(etcdSource) +``` diff --git a/config/source/etcd/etcd.go b/config/source/etcd/etcd.go new file mode 100644 index 00000000..5cbe1286 --- /dev/null +++ b/config/source/etcd/etcd.go @@ -0,0 +1,141 @@ +package etcd + +import ( + "context" + "fmt" + "net" + "time" + + cetcd "github.com/coreos/etcd/clientv3" + "github.com/coreos/etcd/mvcc/mvccpb" + "github.com/micro/go-micro/config/source" +) + +// Currently a single etcd reader +type etcd struct { + prefix string + stripPrefix string + opts source.Options + client *cetcd.Client + cerr error +} + +var ( + DefaultPrefix = "/micro/config/" +) + +func (c *etcd) Read() (*source.ChangeSet, error) { + if c.cerr != nil { + return nil, c.cerr + } + + rsp, err := c.client.Get(context.Background(), c.prefix, cetcd.WithPrefix()) + if err != nil { + return nil, err + } + + if rsp == nil || len(rsp.Kvs) == 0 { + return nil, fmt.Errorf("source not found: %s", c.prefix) + } + + var kvs []*mvccpb.KeyValue + for _, v := range rsp.Kvs { + kvs = append(kvs, (*mvccpb.KeyValue)(v)) + } + + data := makeMap(c.opts.Encoder, kvs, c.stripPrefix) + + b, err := c.opts.Encoder.Encode(data) + if err != nil { + return nil, fmt.Errorf("error reading source: %v", err) + } + + cs := &source.ChangeSet{ + Timestamp: time.Now(), + Source: c.String(), + Data: b, + Format: c.opts.Encoder.String(), + } + cs.Checksum = cs.Sum() + + return cs, nil +} + +func (c *etcd) String() string { + return "etcd" +} + +func (c *etcd) Watch() (source.Watcher, error) { + if c.cerr != nil { + return nil, c.cerr + } + cs, err := c.Read() + if err != nil { + return nil, err + } + return newWatcher(c.prefix, c.stripPrefix, c.client.Watcher, cs, c.opts) +} + +func NewSource(opts ...source.Option) source.Source { + options := source.NewOptions(opts...) + + var endpoints []string + + // check if there are any addrs + addrs, ok := options.Context.Value(addressKey{}).([]string) + if ok { + for _, a := range addrs { + addr, port, err := net.SplitHostPort(a) + if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { + port = "2379" + addr = a + endpoints = append(endpoints, fmt.Sprintf("%s:%s", addr, port)) + } else if err == nil { + endpoints = append(endpoints, fmt.Sprintf("%s:%s", addr, port)) + } + } + } + + if len(endpoints) == 0 { + endpoints = []string{"localhost:2379"} + } + + // check dial timeout option + dialTimeout, ok := options.Context.Value(dialTimeoutKey{}).(time.Duration) + if !ok { + dialTimeout = 3 * time.Second // default dial timeout + } + + config := cetcd.Config{ + Endpoints: endpoints, + DialTimeout: dialTimeout, + } + + u, ok := options.Context.Value(authKey{}).(*authCreds) + if ok { + config.Username = u.Username + config.Password = u.Password + } + + // use default config + client, err := cetcd.New(config) + + prefix := DefaultPrefix + sp := "" + f, ok := options.Context.Value(prefixKey{}).(string) + if ok { + prefix = f + } + + if b, ok := options.Context.Value(stripPrefixKey{}).(bool); ok && b { + sp = prefix + } + + return &etcd{ + prefix: prefix, + stripPrefix: sp, + opts: options, + client: client, + cerr: err, + } +} diff --git a/config/source/consul/options.go b/config/source/etcd/options.go similarity index 61% rename from config/source/consul/options.go rename to config/source/etcd/options.go index 8bca6a66..325d2f46 100644 --- a/config/source/consul/options.go +++ b/config/source/etcd/options.go @@ -1,21 +1,25 @@ -package consul +package etcd import ( "context" + "time" - "github.com/hashicorp/consul/api" "github.com/micro/go-micro/config/source" ) type addressKey struct{} type prefixKey struct{} type stripPrefixKey struct{} -type dcKey struct{} -type tokenKey struct{} -type configKey struct{} +type authKey struct{} +type dialTimeoutKey struct{} -// WithAddress sets the consul address -func WithAddress(a string) source.Option { +type authCreds struct { + Username string + Password string +} + +// WithAddress sets the etcd address +func WithAddress(a ...string) source.Option { return func(o *source.Options) { if o.Context == nil { o.Context = context.Background() @@ -45,31 +49,22 @@ func StripPrefix(strip bool) source.Option { } } -func WithDatacenter(p string) source.Option { +// Auth allows you to specify username/password +func Auth(username, password string) source.Option { return func(o *source.Options) { if o.Context == nil { o.Context = context.Background() } - o.Context = context.WithValue(o.Context, dcKey{}, p) + o.Context = context.WithValue(o.Context, authKey{}, &authCreds{Username: username, Password: password}) } } -// WithToken sets the key token to use -func WithToken(p string) source.Option { +// WithDialTimeout set the time out for dialing to etcd +func WithDialTimeout(timeout time.Duration) source.Option { return func(o *source.Options) { if o.Context == nil { o.Context = context.Background() } - o.Context = context.WithValue(o.Context, tokenKey{}, p) - } -} - -// WithConfig set consul-specific options -func WithConfig(c *api.Config) source.Option { - return func(o *source.Options) { - if o.Context == nil { - o.Context = context.Background() - } - o.Context = context.WithValue(o.Context, configKey{}, c) + o.Context = context.WithValue(o.Context, dialTimeoutKey{}, timeout) } } diff --git a/config/source/etcd/util.go b/config/source/etcd/util.go new file mode 100644 index 00000000..31887fc9 --- /dev/null +++ b/config/source/etcd/util.go @@ -0,0 +1,89 @@ +package etcd + +import ( + "strings" + + "github.com/coreos/etcd/clientv3" + "github.com/coreos/etcd/mvcc/mvccpb" + "github.com/micro/go-micro/config/encoder" +) + +func makeEvMap(e encoder.Encoder, data map[string]interface{}, kv []*clientv3.Event, stripPrefix string) map[string]interface{} { + if data == nil { + data = make(map[string]interface{}) + } + + for _, v := range kv { + switch mvccpb.Event_EventType(v.Type) { + case mvccpb.DELETE: + data = update(e, data, (*mvccpb.KeyValue)(v.Kv), "delete", stripPrefix) + default: + data = update(e, data, (*mvccpb.KeyValue)(v.Kv), "insert", stripPrefix) + } + } + + return data +} + +func makeMap(e encoder.Encoder, kv []*mvccpb.KeyValue, stripPrefix string) map[string]interface{} { + data := make(map[string]interface{}) + + for _, v := range kv { + data = update(e, data, v, "put", stripPrefix) + } + + return data +} + +func update(e encoder.Encoder, data map[string]interface{}, v *mvccpb.KeyValue, action, stripPrefix string) map[string]interface{} { + // remove prefix if non empty, and ensure leading / is removed as well + vkey := strings.TrimPrefix(strings.TrimPrefix(string(v.Key), stripPrefix), "/") + // split on prefix + haveSplit := strings.Contains(vkey, "/") + keys := strings.Split(vkey, "/") + + var vals interface{} + e.Decode(v.Value, &vals) + + if !haveSplit && len(keys) == 1 { + switch action { + case "delete": + data = make(map[string]interface{}) + default: + v, ok := vals.(map[string]interface{}) + if ok { + data = v + } + } + return data + } + + // set data for first iteration + kvals := data + // iterate the keys and make maps + for i, k := range keys { + kval, ok := kvals[k].(map[string]interface{}) + if !ok { + // create next map + kval = make(map[string]interface{}) + // set it + kvals[k] = kval + } + + // last key: write vals + if l := len(keys) - 1; i == l { + switch action { + case "delete": + delete(kvals, k) + default: + kvals[k] = vals + } + break + } + + // set kvals for next iterator + kvals = kval + } + + return data +} diff --git a/config/source/etcd/watcher.go b/config/source/etcd/watcher.go new file mode 100644 index 00000000..2f9b3189 --- /dev/null +++ b/config/source/etcd/watcher.go @@ -0,0 +1,113 @@ +package etcd + +import ( + "context" + "errors" + "sync" + "time" + + cetcd "github.com/coreos/etcd/clientv3" + "github.com/micro/go-micro/config/source" +) + +type watcher struct { + opts source.Options + name string + stripPrefix string + + sync.RWMutex + cs *source.ChangeSet + + ch chan *source.ChangeSet + exit chan bool +} + +func newWatcher(key, strip string, wc cetcd.Watcher, cs *source.ChangeSet, opts source.Options) (source.Watcher, error) { + w := &watcher{ + opts: opts, + name: "etcd", + stripPrefix: strip, + cs: cs, + ch: make(chan *source.ChangeSet), + exit: make(chan bool), + } + + ch := wc.Watch(context.Background(), key, cetcd.WithPrefix()) + + go w.run(wc, ch) + + return w, nil +} + +func (w *watcher) handle(evs []*cetcd.Event) { + w.RLock() + data := w.cs.Data + w.RUnlock() + + var vals map[string]interface{} + + // unpackage existing changeset + if err := w.opts.Encoder.Decode(data, &vals); err != nil { + return + } + + // update base changeset + d := makeEvMap(w.opts.Encoder, vals, evs, w.stripPrefix) + + // pack the changeset + b, err := w.opts.Encoder.Encode(d) + if err != nil { + return + } + + // create new changeset + cs := &source.ChangeSet{ + Timestamp: time.Now(), + Source: w.name, + Data: b, + Format: w.opts.Encoder.String(), + } + cs.Checksum = cs.Sum() + + // set base change set + w.Lock() + w.cs = cs + w.Unlock() + + // send update + w.ch <- cs +} + +func (w *watcher) run(wc cetcd.Watcher, ch cetcd.WatchChan) { + for { + select { + case rsp, ok := <-ch: + if !ok { + return + } + w.handle(rsp.Events) + case <-w.exit: + wc.Close() + return + } + } +} + +func (w *watcher) Next() (*source.ChangeSet, error) { + select { + case cs := <-w.ch: + return cs, nil + case <-w.exit: + return nil, errors.New("watcher stopped") + } +} + +func (w *watcher) Stop() error { + select { + case <-w.exit: + return nil + default: + close(w.exit) + } + return nil +} diff --git a/sync/leader/consul/consul.go b/sync/leader/consul/consul.go deleted file mode 100644 index b5b344c6..00000000 --- a/sync/leader/consul/consul.go +++ /dev/null @@ -1,158 +0,0 @@ -package consul - -import ( - "fmt" - "log" - "net" - "os" - "path" - "sync" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/api/watch" - "github.com/micro/go-micro/sync/leader" -) - -type consulLeader struct { - opts leader.Options - c *api.Client -} - -type consulElected struct { - c *api.Client - l *api.Lock - id string - key string - opts leader.ElectOptions - - mtx sync.RWMutex - rv <-chan struct{} -} - -func (c *consulLeader) Elect(id string, opts ...leader.ElectOption) (leader.Elected, error) { - var options leader.ElectOptions - for _, o := range opts { - o(&options) - } - - key := path.Join("micro/leader", c.opts.Group) - - lc, err := c.c.LockOpts(&api.LockOptions{ - Key: key, - Value: []byte(id), - }) - if err != nil { - return nil, err - } - - rv, err := lc.Lock(nil) - if err != nil { - return nil, err - } - - return &consulElected{ - c: c.c, - key: key, - rv: rv, - id: id, - l: lc, - opts: options, - }, nil -} - -func (c *consulLeader) Follow() chan string { - ch := make(chan string, 1) - - key := path.Join("/micro/leader", c.opts.Group) - - p, err := watch.Parse(map[string]interface{}{ - "type": "key", - "key": key, - }) - if err != nil { - return ch - } - p.Handler = func(idx uint64, raw interface{}) { - if raw == nil { - return // ignore - } - v, ok := raw.(*api.KVPair) - if !ok || v == nil { - return // ignore - } - ch <- string(v.Value) - } - - go p.RunWithClientAndLogger(c.c, log.New(os.Stdout, "consul: ", log.Lshortfile)) - return ch -} - -func (c *consulLeader) String() string { - return "consul" -} - -func (c *consulElected) Id() string { - return c.id -} - -func (c *consulElected) Reelect() error { - rv, err := c.l.Lock(nil) - if err != nil { - return err - } - - c.mtx.Lock() - c.rv = rv - c.mtx.Unlock() - return nil -} - -func (c *consulElected) Revoked() chan bool { - ch := make(chan bool, 1) - c.mtx.RLock() - rv := c.rv - c.mtx.RUnlock() - - go func() { - <-rv - ch <- true - close(ch) - }() - - return ch -} - -func (c *consulElected) Resign() error { - return c.l.Unlock() -} - -func NewLeader(opts ...leader.Option) leader.Leader { - options := leader.Options{ - Group: "default", - } - for _, o := range opts { - o(&options) - } - - config := api.DefaultConfig() - - // set host - // config.Host something - // check if there are any addrs - if len(options.Nodes) > 0 { - addr, port, err := net.SplitHostPort(options.Nodes[0]) - if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { - port = "8500" - config.Address = fmt.Sprintf("%s:%s", addr, port) - } else if err == nil { - config.Address = fmt.Sprintf("%s:%s", addr, port) - } - } - - client, _ := api.NewClient(config) - - return &consulLeader{ - opts: options, - c: client, - } -} diff --git a/sync/leader/etcd/etcd.go b/sync/leader/etcd/etcd.go new file mode 100644 index 00000000..6179bf0b --- /dev/null +++ b/sync/leader/etcd/etcd.go @@ -0,0 +1,145 @@ +package etcd + +import ( + "context" + "log" + "path" + "strings" + + client "github.com/coreos/etcd/clientv3" + cc "github.com/coreos/etcd/clientv3/concurrency" + "github.com/micro/go-micro/sync/leader" +) + +type etcdLeader struct { + opts leader.Options + path string + client *client.Client +} + +type etcdElected struct { + s *cc.Session + e *cc.Election + id string +} + +func (e *etcdLeader) Elect(id string, opts ...leader.ElectOption) (leader.Elected, error) { + var options leader.ElectOptions + for _, o := range opts { + o(&options) + } + + // make path + path := path.Join(e.path, strings.Replace(id, "/", "-", -1)) + + s, err := cc.NewSession(e.client) + if err != nil { + return nil, err + } + + l := cc.NewElection(s, path) + + ctx, _ := context.WithCancel(context.Background()) + + if err := l.Campaign(ctx, id); err != nil { + return nil, err + } + + return &etcdElected{ + e: l, + id: id, + }, nil +} + +func (e *etcdLeader) Follow() chan string { + ch := make(chan string) + + s, err := cc.NewSession(e.client) + if err != nil { + return ch + } + + l := cc.NewElection(s, e.path) + ech := l.Observe(context.Background()) + + go func() { + for { + select { + case r, ok := <-ech: + if !ok { + return + } + ch <- string(r.Kvs[0].Value) + } + } + }() + + return ch +} + +func (e *etcdLeader) String() string { + return "etcd" +} + +func (e *etcdElected) Reelect() error { + ctx, _ := context.WithCancel(context.Background()) + return e.e.Campaign(ctx, e.id) +} + +func (e *etcdElected) Revoked() chan bool { + ch := make(chan bool, 1) + ech := e.e.Observe(context.Background()) + + go func() { + for r := range ech { + if string(r.Kvs[0].Value) != e.id { + ch <- true + close(ch) + return + } + } + }() + + return ch +} + +func (e *etcdElected) Resign() error { + return e.e.Resign(context.Background()) +} + +func (e *etcdElected) Id() string { + return e.id +} + +func NewLeader(opts ...leader.Option) leader.Leader { + var options leader.Options + for _, o := range opts { + o(&options) + } + + var endpoints []string + + for _, addr := range options.Nodes { + if len(addr) > 0 { + endpoints = append(endpoints, addr) + } + } + + if len(endpoints) == 0 { + endpoints = []string{"http://127.0.0.1:2379"} + } + + // TODO: parse addresses + c, err := client.New(client.Config{ + Endpoints: endpoints, + }) + if err != nil { + log.Fatal(err) + } + + return &etcdLeader{ + path: "/micro/leader", + client: c, + opts: options, + } +} From b1163b9dee9ff79c3908bc95b1c92236586cab82 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 11:26:24 +0100 Subject: [PATCH 025/344] Fix breaking import --- sync/cron.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sync/cron.go b/sync/cron.go index f5dcdb0f..0fd479a1 100644 --- a/sync/cron.go +++ b/sync/cron.go @@ -5,7 +5,7 @@ import ( "math" "time" - "github.com/micro/go-micro/sync/leader/consul" + "github.com/micro/go-micro/sync/leader/etcd" "github.com/micro/go-micro/sync/task" "github.com/micro/go-micro/sync/task/local" "github.com/micro/go-micro/util/log" @@ -80,7 +80,7 @@ func NewCron(opts ...Option) Cron { } if options.Leader == nil { - options.Leader = consul.NewLeader() + options.Leader = etcd.NewLeader() } if options.Task == nil { From b8815dff14e81ab2b17611eba916c12e38be33f5 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 3 Oct 2019 16:16:25 +0100 Subject: [PATCH 026/344] Append a port to address if it does not exist --- registry/consul/consul.go | 4 ++-- registry/etcd/etcd.go | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/registry/consul/consul.go b/registry/consul/consul.go index 007d7369..152aae69 100644 --- a/registry/consul/consul.go +++ b/registry/consul/consul.go @@ -107,9 +107,9 @@ func configure(c *consulRegistry, opts ...registry.Option) { if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { port = "8500" addr = address - addrs = append(addrs, fmt.Sprintf("%s:%s", addr, port)) + addrs = append(addrs, net.JoinHostPort(addr, port)) } else if err == nil { - addrs = append(addrs, fmt.Sprintf("%s:%s", addr, port)) + addrs = append(addrs, net.JoinHostPort(addr, port)) } } diff --git a/registry/etcd/etcd.go b/registry/etcd/etcd.go index c4419487..f2780058 100644 --- a/registry/etcd/etcd.go +++ b/registry/etcd/etcd.go @@ -6,6 +6,7 @@ import ( "crypto/tls" "encoding/json" "errors" + "net" "path" "strings" "sync" @@ -74,11 +75,18 @@ func configure(e *etcdRegistry, opts ...registry.Option) error { var cAddrs []string - for _, addr := range e.options.Addrs { - if len(addr) == 0 { + for _, address := range e.options.Addrs { + if len(address) == 0 { continue } - cAddrs = append(cAddrs, addr) + addr, port, err := net.SplitHostPort(address) + if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { + port = "2379" + addr = address + cAddrs = append(cAddrs, net.JoinHostPort(addr, port)) + } else if err == nil { + cAddrs = append(cAddrs, net.JoinHostPort(addr, port)) + } } // if we got addrs then we'll update From 4de346920f60cb92e46121d648e8b647607032b5 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 16:19:02 +0100 Subject: [PATCH 027/344] Add broker service implementation --- broker/service/handler/handler.go | 57 +++++ broker/service/proto/broker.micro.go | 173 +++++++++++++ broker/service/proto/broker.pb.go | 364 +++++++++++++++++++++++++++ broker/service/proto/broker.proto | 25 ++ broker/service/service.go | 102 ++++++++ broker/service/subscriber.go | 79 ++++++ 6 files changed, 800 insertions(+) create mode 100644 broker/service/handler/handler.go create mode 100644 broker/service/proto/broker.micro.go create mode 100644 broker/service/proto/broker.pb.go create mode 100644 broker/service/proto/broker.proto create mode 100644 broker/service/service.go create mode 100644 broker/service/subscriber.go diff --git a/broker/service/handler/handler.go b/broker/service/handler/handler.go new file mode 100644 index 00000000..6e78905f --- /dev/null +++ b/broker/service/handler/handler.go @@ -0,0 +1,57 @@ +package handler + +import ( + "context" + + "github.com/micro/go-micro/broker" + pb "github.com/micro/go-micro/broker/service/proto" + "github.com/micro/go-micro/errors" +) + +type Broker struct { + Broker broker.Broker +} + +func (b *Broker) Publish(ctx context.Context, req *pb.PublishRequest, rsp *pb.Empty) error { + err := b.Broker.Publish(req.Topic, &broker.Message{ + Header: req.Message.Header, + Body: req.Message.Body, + }) + if err != nil { + return errors.InternalServerError("go.micro.broker", err.Error()) + } + return nil +} + +func (b *Broker) Subscribe(ctx context.Context, req *pb.SubscribeRequest, stream pb.Broker_SubscribeStream) error { + errChan := make(chan error, 1) + + // message handler to stream back messages from broker + handler := func(p broker.Event) error { + if err := stream.Send(&pb.Message{ + Header: p.Message().Header, + Body: p.Message().Body, + }); err != nil { + select { + case errChan <- err: + return err + default: + return err + } + } + return nil + } + + sub, err := b.Broker.Subscribe(req.Topic, handler, broker.Queue(req.Queue)) + if err != nil { + return errors.InternalServerError("go.micro.broker", err.Error()) + } + defer sub.Unsubscribe() + + select { + case <-ctx.Done(): + return nil + case <-errChan: + return err + } +} diff --git a/broker/service/proto/broker.micro.go b/broker/service/proto/broker.micro.go new file mode 100644 index 00000000..577132c5 --- /dev/null +++ b/broker/service/proto/broker.micro.go @@ -0,0 +1,173 @@ +// Code generated by protoc-gen-micro. DO NOT EDIT. +// source: github.com/micro/go-micro/broker/proto/broker.proto + +package go_micro_broker + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +import ( + context "context" + client "github.com/micro/go-micro/client" + server "github.com/micro/go-micro/server" +) + +// 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.ProtoPackageIsVersion3 // please upgrade the proto package + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ client.Option +var _ server.Option + +// Client API for Broker service + +type BrokerService interface { + Publish(ctx context.Context, in *PublishRequest, opts ...client.CallOption) (*Empty, error) + Subscribe(ctx context.Context, in *SubscribeRequest, opts ...client.CallOption) (Broker_SubscribeService, error) +} + +type brokerService struct { + c client.Client + name string +} + +func NewBrokerService(name string, c client.Client) BrokerService { + if c == nil { + c = client.NewClient() + } + if len(name) == 0 { + name = "go.micro.broker" + } + return &brokerService{ + c: c, + name: name, + } +} + +func (c *brokerService) Publish(ctx context.Context, in *PublishRequest, opts ...client.CallOption) (*Empty, error) { + req := c.c.NewRequest(c.name, "Broker.Publish", in) + out := new(Empty) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *brokerService) Subscribe(ctx context.Context, in *SubscribeRequest, opts ...client.CallOption) (Broker_SubscribeService, error) { + req := c.c.NewRequest(c.name, "Broker.Subscribe", &SubscribeRequest{}) + stream, err := c.c.Stream(ctx, req, opts...) + if err != nil { + return nil, err + } + if err := stream.Send(in); err != nil { + return nil, err + } + return &brokerServiceSubscribe{stream}, nil +} + +type Broker_SubscribeService interface { + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Recv() (*Message, error) +} + +type brokerServiceSubscribe struct { + stream client.Stream +} + +func (x *brokerServiceSubscribe) Close() error { + return x.stream.Close() +} + +func (x *brokerServiceSubscribe) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *brokerServiceSubscribe) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *brokerServiceSubscribe) Recv() (*Message, error) { + m := new(Message) + err := x.stream.Recv(m) + if err != nil { + return nil, err + } + return m, nil +} + +// Server API for Broker service + +type BrokerHandler interface { + Publish(context.Context, *PublishRequest, *Empty) error + Subscribe(context.Context, *SubscribeRequest, Broker_SubscribeStream) error +} + +func RegisterBrokerHandler(s server.Server, hdlr BrokerHandler, opts ...server.HandlerOption) error { + type broker interface { + Publish(ctx context.Context, in *PublishRequest, out *Empty) error + Subscribe(ctx context.Context, stream server.Stream) error + } + type Broker struct { + broker + } + h := &brokerHandler{hdlr} + return s.Handle(s.NewHandler(&Broker{h}, opts...)) +} + +type brokerHandler struct { + BrokerHandler +} + +func (h *brokerHandler) Publish(ctx context.Context, in *PublishRequest, out *Empty) error { + return h.BrokerHandler.Publish(ctx, in, out) +} + +func (h *brokerHandler) Subscribe(ctx context.Context, stream server.Stream) error { + m := new(SubscribeRequest) + if err := stream.Recv(m); err != nil { + return err + } + return h.BrokerHandler.Subscribe(ctx, m, &brokerSubscribeStream{stream}) +} + +type Broker_SubscribeStream interface { + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Send(*Message) error +} + +type brokerSubscribeStream struct { + stream server.Stream +} + +func (x *brokerSubscribeStream) Close() error { + return x.stream.Close() +} + +func (x *brokerSubscribeStream) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *brokerSubscribeStream) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *brokerSubscribeStream) Send(m *Message) error { + return x.stream.Send(m) +} diff --git a/broker/service/proto/broker.pb.go b/broker/service/proto/broker.pb.go new file mode 100644 index 00000000..b54a5480 --- /dev/null +++ b/broker/service/proto/broker.pb.go @@ -0,0 +1,364 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: github.com/micro/go-micro/broker/proto/broker.proto + +package go_micro_broker + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + 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.ProtoPackageIsVersion3 // please upgrade the proto package + +type Empty struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Empty) Reset() { *m = Empty{} } +func (m *Empty) String() string { return proto.CompactTextString(m) } +func (*Empty) ProtoMessage() {} +func (*Empty) Descriptor() ([]byte, []int) { + return fileDescriptor_5edf81766900dd99, []int{0} +} + +func (m *Empty) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Empty.Unmarshal(m, b) +} +func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Empty.Marshal(b, m, deterministic) +} +func (m *Empty) XXX_Merge(src proto.Message) { + xxx_messageInfo_Empty.Merge(m, src) +} +func (m *Empty) XXX_Size() int { + return xxx_messageInfo_Empty.Size(m) +} +func (m *Empty) XXX_DiscardUnknown() { + xxx_messageInfo_Empty.DiscardUnknown(m) +} + +var xxx_messageInfo_Empty proto.InternalMessageInfo + +type PublishRequest struct { + Topic string `protobuf:"bytes,1,opt,name=topic,proto3" json:"topic,omitempty"` + Message *Message `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PublishRequest) Reset() { *m = PublishRequest{} } +func (m *PublishRequest) String() string { return proto.CompactTextString(m) } +func (*PublishRequest) ProtoMessage() {} +func (*PublishRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_5edf81766900dd99, []int{1} +} + +func (m *PublishRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PublishRequest.Unmarshal(m, b) +} +func (m *PublishRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PublishRequest.Marshal(b, m, deterministic) +} +func (m *PublishRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PublishRequest.Merge(m, src) +} +func (m *PublishRequest) XXX_Size() int { + return xxx_messageInfo_PublishRequest.Size(m) +} +func (m *PublishRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PublishRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PublishRequest proto.InternalMessageInfo + +func (m *PublishRequest) GetTopic() string { + if m != nil { + return m.Topic + } + return "" +} + +func (m *PublishRequest) GetMessage() *Message { + if m != nil { + return m.Message + } + return nil +} + +type SubscribeRequest struct { + Topic string `protobuf:"bytes,1,opt,name=topic,proto3" json:"topic,omitempty"` + Queue string `protobuf:"bytes,2,opt,name=queue,proto3" json:"queue,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SubscribeRequest) Reset() { *m = SubscribeRequest{} } +func (m *SubscribeRequest) String() string { return proto.CompactTextString(m) } +func (*SubscribeRequest) ProtoMessage() {} +func (*SubscribeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_5edf81766900dd99, []int{2} +} + +func (m *SubscribeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SubscribeRequest.Unmarshal(m, b) +} +func (m *SubscribeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SubscribeRequest.Marshal(b, m, deterministic) +} +func (m *SubscribeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SubscribeRequest.Merge(m, src) +} +func (m *SubscribeRequest) XXX_Size() int { + return xxx_messageInfo_SubscribeRequest.Size(m) +} +func (m *SubscribeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SubscribeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SubscribeRequest proto.InternalMessageInfo + +func (m *SubscribeRequest) GetTopic() string { + if m != nil { + return m.Topic + } + return "" +} + +func (m *SubscribeRequest) GetQueue() string { + if m != nil { + return m.Queue + } + return "" +} + +type Message struct { + Header map[string]string `protobuf:"bytes,1,rep,name=header,proto3" json:"header,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_5edf81766900dd99, []int{3} +} + +func (m *Message) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Message.Unmarshal(m, b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) +} +func (m *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(m, src) +} +func (m *Message) XXX_Size() int { + return xxx_messageInfo_Message.Size(m) +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +func (m *Message) GetHeader() map[string]string { + if m != nil { + return m.Header + } + return nil +} + +func (m *Message) GetBody() []byte { + if m != nil { + return m.Body + } + return nil +} + +func init() { + proto.RegisterType((*Empty)(nil), "go.micro.broker.Empty") + proto.RegisterType((*PublishRequest)(nil), "go.micro.broker.PublishRequest") + proto.RegisterType((*SubscribeRequest)(nil), "go.micro.broker.SubscribeRequest") + proto.RegisterType((*Message)(nil), "go.micro.broker.Message") + proto.RegisterMapType((map[string]string)(nil), "go.micro.broker.Message.HeaderEntry") +} + +func init() { + proto.RegisterFile("github.com/micro/go-micro/broker/proto/broker.proto", fileDescriptor_5edf81766900dd99) +} + +var fileDescriptor_5edf81766900dd99 = []byte{ + // 309 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xcf, 0x4a, 0xf3, 0x40, + 0x14, 0xc5, 0x3b, 0xed, 0xd7, 0x86, 0xde, 0x7e, 0x68, 0x19, 0x8a, 0x84, 0x6e, 0x8c, 0xc1, 0x45, + 0x36, 0x4e, 0x24, 0xdd, 0xa8, 0x88, 0x0b, 0xb1, 0xe0, 0x42, 0x41, 0xc6, 0x9d, 0xbb, 0x4c, 0x3a, + 0x24, 0xa1, 0x8d, 0x93, 0x4e, 0x66, 0x84, 0xbc, 0x88, 0x2b, 0x1f, 0x56, 0x3a, 0x93, 0xfa, 0xa7, + 0xa1, 0xee, 0xee, 0x49, 0x7e, 0x73, 0xee, 0xe1, 0x5c, 0x98, 0xa5, 0xb9, 0xca, 0x34, 0x23, 0x89, + 0x28, 0xc2, 0x22, 0x4f, 0xa4, 0x08, 0x53, 0x71, 0x66, 0x07, 0x26, 0xc5, 0x92, 0xcb, 0xb0, 0x94, + 0x42, 0x6d, 0x05, 0x31, 0x02, 0x1f, 0xa6, 0x82, 0x18, 0x86, 0xd8, 0xcf, 0xbe, 0x03, 0xfd, 0x79, + 0x51, 0xaa, 0xda, 0x7f, 0x81, 0x83, 0x27, 0xcd, 0x56, 0x79, 0x95, 0x51, 0xbe, 0xd6, 0xbc, 0x52, + 0x78, 0x02, 0x7d, 0x25, 0xca, 0x3c, 0x71, 0x91, 0x87, 0x82, 0x21, 0xb5, 0x02, 0x47, 0xe0, 0x14, + 0xbc, 0xaa, 0xe2, 0x94, 0xbb, 0x5d, 0x0f, 0x05, 0xa3, 0xc8, 0x25, 0x3b, 0x9e, 0xe4, 0xd1, 0xfe, + 0xa7, 0x5b, 0xd0, 0xbf, 0x81, 0xf1, 0xb3, 0x66, 0x55, 0x22, 0x73, 0xc6, 0xff, 0x76, 0x9f, 0x40, + 0x7f, 0xad, 0xb9, 0xb6, 0xde, 0x43, 0x6a, 0x85, 0xff, 0x8e, 0xc0, 0x69, 0x4c, 0xf1, 0x35, 0x0c, + 0x32, 0x1e, 0x2f, 0xb8, 0x74, 0x91, 0xd7, 0x0b, 0x46, 0xd1, 0xe9, 0xbe, 0xf5, 0xe4, 0xde, 0x60, + 0xf3, 0x57, 0x25, 0x6b, 0xda, 0xbc, 0xc1, 0x18, 0xfe, 0x31, 0xb1, 0xa8, 0x8d, 0xfd, 0x7f, 0x6a, + 0xe6, 0xe9, 0x25, 0x8c, 0x7e, 0xa0, 0x78, 0x0c, 0xbd, 0x25, 0xaf, 0x9b, 0x58, 0x9b, 0x71, 0x13, + 0xea, 0x2d, 0x5e, 0x7d, 0x87, 0x32, 0xe2, 0xaa, 0x7b, 0x81, 0xa2, 0x0f, 0x04, 0x83, 0x5b, 0xb3, + 0x15, 0xdf, 0x81, 0xd3, 0xf4, 0x87, 0x8f, 0x5b, 0x91, 0x7e, 0x37, 0x3b, 0x3d, 0x6a, 0x01, 0xf6, + 0x06, 0x1d, 0xfc, 0x00, 0xc3, 0xaf, 0xa6, 0xf0, 0x49, 0x0b, 0xdb, 0x6d, 0x71, 0xba, 0xb7, 0x7c, + 0xbf, 0x73, 0x8e, 0xd8, 0xc0, 0x1c, 0x7d, 0xf6, 0x19, 0x00, 0x00, 0xff, 0xff, 0x25, 0x38, 0xfa, + 0x02, 0x2b, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// BrokerClient is the client API for Broker service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type BrokerClient interface { + Publish(ctx context.Context, in *PublishRequest, opts ...grpc.CallOption) (*Empty, error) + Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (Broker_SubscribeClient, error) +} + +type brokerClient struct { + cc *grpc.ClientConn +} + +func NewBrokerClient(cc *grpc.ClientConn) BrokerClient { + return &brokerClient{cc} +} + +func (c *brokerClient) Publish(ctx context.Context, in *PublishRequest, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := c.cc.Invoke(ctx, "/go.micro.broker.Broker/Publish", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *brokerClient) Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (Broker_SubscribeClient, error) { + stream, err := c.cc.NewStream(ctx, &_Broker_serviceDesc.Streams[0], "/go.micro.broker.Broker/Subscribe", opts...) + if err != nil { + return nil, err + } + x := &brokerSubscribeClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Broker_SubscribeClient interface { + Recv() (*Message, error) + grpc.ClientStream +} + +type brokerSubscribeClient struct { + grpc.ClientStream +} + +func (x *brokerSubscribeClient) Recv() (*Message, error) { + m := new(Message) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// BrokerServer is the server API for Broker service. +type BrokerServer interface { + Publish(context.Context, *PublishRequest) (*Empty, error) + Subscribe(*SubscribeRequest, Broker_SubscribeServer) error +} + +func RegisterBrokerServer(s *grpc.Server, srv BrokerServer) { + s.RegisterService(&_Broker_serviceDesc, srv) +} + +func _Broker_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PublishRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BrokerServer).Publish(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.broker.Broker/Publish", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BrokerServer).Publish(ctx, req.(*PublishRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Broker_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SubscribeRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(BrokerServer).Subscribe(m, &brokerSubscribeServer{stream}) +} + +type Broker_SubscribeServer interface { + Send(*Message) error + grpc.ServerStream +} + +type brokerSubscribeServer struct { + grpc.ServerStream +} + +func (x *brokerSubscribeServer) Send(m *Message) error { + return x.ServerStream.SendMsg(m) +} + +var _Broker_serviceDesc = grpc.ServiceDesc{ + ServiceName: "go.micro.broker.Broker", + HandlerType: (*BrokerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Publish", + Handler: _Broker_Publish_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Subscribe", + Handler: _Broker_Subscribe_Handler, + ServerStreams: true, + }, + }, + Metadata: "github.com/micro/go-micro/broker/proto/broker.proto", +} diff --git a/broker/service/proto/broker.proto b/broker/service/proto/broker.proto new file mode 100644 index 00000000..3fc877e6 --- /dev/null +++ b/broker/service/proto/broker.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; + +package go.micro.broker; + +service Broker { + rpc Publish(PublishRequest) returns (Empty) {}; + rpc Subscribe(SubscribeRequest) returns (stream Message) {}; +} + +message Empty {} + +message PublishRequest { + string topic = 1; + Message message = 2; +} + +message SubscribeRequest { + string topic = 1; + string queue = 2; +} + +message Message { + map header = 1; + bytes body = 2; +} diff --git a/broker/service/service.go b/broker/service/service.go new file mode 100644 index 00000000..63c09624 --- /dev/null +++ b/broker/service/service.go @@ -0,0 +1,102 @@ +// Package service provides the broker service client +package service + +import ( + "context" + + "github.com/micro/go-micro/broker" + pb "github.com/micro/go-micro/broker/service/proto" + "github.com/micro/go-micro/client" +) + +type serviceBroker struct { + Addrs []string + Client pb.BrokerService + options broker.Options +} + +var ( + DefaultName = "go.micro.broker" +) + +func (b *serviceBroker) Address() string { + return b.Addrs[0] +} + +func (b *serviceBroker) Connect() error { + return nil +} + +func (b *serviceBroker) Disconnect() error { + return nil +} + +func (b *serviceBroker) Init(opts ...broker.Option) error { + for _, o := range opts { + o(&b.options) + } + return nil +} + +func (b *serviceBroker) Options() broker.Options { + return b.options +} + +func (b *serviceBroker) Publish(topic string, msg *broker.Message, opts ...broker.PublishOption) error { + _, err := b.Client.Publish(context.TODO(), &pb.PublishRequest{ + Topic: topic, + Message: &pb.Message{ + Header: msg.Header, + Body: msg.Body, + }, + }, client.WithAddress(b.Addrs...)) + return err +} + +func (b *serviceBroker) Subscribe(topic string, handler broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) { + var options broker.SubscribeOptions + for _, o := range opts { + o(&options) + } + stream, err := b.Client.Subscribe(context.TODO(), &pb.SubscribeRequest{ + Topic: topic, + Queue: options.Queue, + }, client.WithAddress(b.Addrs...)) + if err != nil { + return nil, err + } + + sub := &serviceSub{ + topic: topic, + queue: options.Queue, + handler: handler, + stream: stream, + closed: make(chan bool), + options: options, + } + go sub.run() + + return sub, nil +} + +func (b *serviceBroker) String() string { + return "service" +} + +func NewBroker(opts ...broker.Option) broker.Broker { + var options broker.Options + for _, o := range opts { + o(&options) + } + + addrs := options.Addrs + if len(addrs) == 0 { + addrs = []string{"127.0.0.1:8001"} + } + + return &serviceBroker{ + Addrs: addrs, + Client: pb.NewBrokerService(DefaultName, client.DefaultClient), + options: options, + } +} diff --git a/broker/service/subscriber.go b/broker/service/subscriber.go new file mode 100644 index 00000000..09a942c8 --- /dev/null +++ b/broker/service/subscriber.go @@ -0,0 +1,79 @@ +package service + +import ( + "github.com/micro/go-micro/broker" + pb "github.com/micro/go-micro/broker/service/proto" +) + +type serviceSub struct { + topic string + queue string + handler broker.Handler + stream pb.Broker_SubscribeService + closed chan bool + options broker.SubscribeOptions +} + +type serviceEvent struct { + topic string + message *broker.Message +} + +func (s *serviceEvent) Topic() string { + return s.topic +} + +func (s *serviceEvent) Message() *broker.Message { + return s.message +} + +func (s *serviceEvent) Ack() error { + return nil +} + +func (s *serviceSub) run() { + exit := make(chan bool) + go func() { + select { + case <-exit: + return + case <-s.closed: + s.stream.Close() + } + }() + + for { + // TODO: do not fail silently + msg, err := s.stream.Recv() + if err != nil { + close(exit) + return + } + // TODO: handle error + s.handler(&serviceEvent{ + topic: s.topic, + message: &broker.Message{ + Header: msg.Header, + Body: msg.Body, + }, + }) + } +} + +func (s *serviceSub) Options() broker.SubscribeOptions { + return s.options +} + +func (s *serviceSub) Topic() string { + return s.topic +} + +func (s *serviceSub) Unsubscribe() error { + select { + case <-s.closed: + return nil + default: + close(s.closed) + } + return nil +} From b80654bf7e81c13b4434659c238ca8200e78702d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 16:22:26 +0100 Subject: [PATCH 028/344] Add broker service to config/cmd --- config/cmd/cmd.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/config/cmd/cmd.go b/config/cmd/cmd.go index cfb8b313..6cb6835b 100644 --- a/config/cmd/cmd.go +++ b/config/cmd/cmd.go @@ -23,6 +23,7 @@ import ( "github.com/micro/go-micro/broker/http" "github.com/micro/go-micro/broker/memory" "github.com/micro/go-micro/broker/nats" + brokerSrv "github.com/micro/go-micro/broker/service" // registries "github.com/micro/go-micro/registry" @@ -179,9 +180,11 @@ var ( } DefaultBrokers = map[string]func(...broker.Option) broker.Broker{ - "http": http.NewBroker, - "memory": memory.NewBroker, - "nats": nats.NewBroker, + "go.micro.broker": brokerSrv.NewBroker, + "service": brokerSrv.NewBroker, + "http": http.NewBroker, + "memory": memory.NewBroker, + "nats": nats.NewBroker, } DefaultClients = map[string]func(...client.Option) client.Client{ From 05eacd74c85179d8f03871827f5467d52744d8fb Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 17:30:37 +0100 Subject: [PATCH 029/344] Add logging for broker handler --- broker/service/handler/handler.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/broker/service/handler/handler.go b/broker/service/handler/handler.go index 6e78905f..3d59dc2e 100644 --- a/broker/service/handler/handler.go +++ b/broker/service/handler/handler.go @@ -3,6 +3,7 @@ package handler import ( "context" + "github.com/micro/go-micro/util/log" "github.com/micro/go-micro/broker" pb "github.com/micro/go-micro/broker/service/proto" "github.com/micro/go-micro/errors" @@ -13,6 +14,7 @@ type Broker struct { } func (b *Broker) Publish(ctx context.Context, req *pb.PublishRequest, rsp *pb.Empty) error { + log.Debugf("Publishing message to %s topic", req.Topic) err := b.Broker.Publish(req.Topic, &broker.Message{ Header: req.Message.Header, Body: req.Message.Body, @@ -42,6 +44,7 @@ func (b *Broker) Subscribe(ctx context.Context, req *pb.SubscribeRequest, stream return nil } + log.Debugf("Subscribing to %s topic", req.Topic) sub, err := b.Broker.Subscribe(req.Topic, handler, broker.Queue(req.Queue)) if err != nil { return errors.InternalServerError("go.micro.broker", err.Error()) From 2244eb85970c0c60eeb91da15ed8c467611dd4cf Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 17:37:29 +0100 Subject: [PATCH 030/344] Advertise your peer address as advertised address --- network/default.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index 8d482b24..78f48fd5 100644 --- a/network/default.go +++ b/network/default.go @@ -93,11 +93,14 @@ func newNetwork(opts ...Option) Network { // set the address to advertise var advertise string + var peerAddress string if len(options.Advertise) > 0 { advertise = options.Advertise + peerAddress = options.Advertise } else { advertise = options.Address + peerAddress = address } // server is network server @@ -122,7 +125,7 @@ func newNetwork(opts ...Option) Network { network := &network{ node: &node{ id: options.Id, - address: address, + address: peerAddress, peers: make(map[string]*node), }, options: options, From 3c6b6553fb82734d9303beb8728c534f1b5d144e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Oct 2019 18:35:54 +0100 Subject: [PATCH 031/344] Use peerAddress as the thing to listen on --- network/default.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index 78f48fd5..315c8f19 100644 --- a/network/default.go +++ b/network/default.go @@ -106,7 +106,7 @@ func newNetwork(opts ...Option) Network { // server is network server server := server.NewServer( server.Id(options.Id), - server.Address(address), + server.Address(peerAddress), server.Advertise(advertise), server.Name(options.Name), server.Transport(tunTransport), From c4b6d0f3a891b462a88e87c1bd0953e95a731587 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 4 Oct 2019 16:29:56 +0100 Subject: [PATCH 032/344] fix major deadlock in registry cache --- registry/cache/cache.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/registry/cache/cache.go b/registry/cache/cache.go index 64ec6843..46460f7d 100644 --- a/registry/cache/cache.go +++ b/registry/cache/cache.go @@ -100,7 +100,7 @@ func (c *cache) quit() bool { func (c *cache) del(service string) { // don't blow away cache in error state - if err := c.getStatus(); err != nil { + if err := c.status; err != nil { return } // otherwise delete entries @@ -116,13 +116,14 @@ func (c *cache) get(service string) ([]*registry.Service, error) { services := c.cache[service] // get cache ttl ttl := c.ttls[service] + // make a copy + cp := registry.Copy(services) + + // unlock the read lock + c.RUnlock() // got services && within ttl so return cache - if c.isValid(services, ttl) { - // make a copy - cp := registry.Copy(services) - // unlock the read - c.RUnlock() + if c.isValid(cp, ttl) { // return servics return cp, nil } @@ -136,8 +137,9 @@ func (c *cache) get(service string) ([]*registry.Service, error) { if len(cached) > 0 { // set the error status c.setStatus(err) + // return the stale cache - return registry.Copy(cached), nil + return cached, nil } // otherwise return error return nil, err @@ -161,9 +163,6 @@ func (c *cache) get(service string) ([]*registry.Service, error) { go c.run(service) } - // unlock the read lock - c.RUnlock() - // get and return services return get(service, services) } From 04320d69ff124fbad0e1a1afb0ef238834b89c4b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 4 Oct 2019 16:30:03 +0100 Subject: [PATCH 033/344] Fix and comment broker service --- broker/http_broker.go | 15 ++++++++++----- broker/service/handler/handler.go | 10 ++++++++-- broker/service/service.go | 32 ++++++++++++++++++++++++++++++- broker/service/subscriber.go | 30 +++++++++++++++++++++++++---- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index 5b362c14..4a22fe12 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -324,15 +324,21 @@ func (h *httpBroker) ServeHTTP(w http.ResponseWriter, req *http.Request) { p := &httpEvent{m: m, t: topic} id := req.Form.Get("id") + var subs []Handler + h.RLock() for _, subscriber := range h.subscribers[topic] { - if id == subscriber.id { - // sub is sync; crufty rate limiting - // so we don't hose the cpu - subscriber.fn(p) + if id != subscriber.id { + continue } + subs = append(subs, subscriber.fn) } h.RUnlock() + + // execute the handler + for _, fn := range subs { + fn(p) + } } func (h *httpBroker) Address() string { @@ -420,7 +426,6 @@ func (h *httpBroker) Connect() error { } func (h *httpBroker) Disconnect() error { - h.RLock() if !h.running { h.RUnlock() diff --git a/broker/service/handler/handler.go b/broker/service/handler/handler.go index 3d59dc2e..e0b5c3d4 100644 --- a/broker/service/handler/handler.go +++ b/broker/service/handler/handler.go @@ -19,6 +19,7 @@ func (b *Broker) Publish(ctx context.Context, req *pb.PublishRequest, rsp *pb.Em Header: req.Message.Header, Body: req.Message.Body, }) + log.Debugf("Published message to %s topic", req.Topic) if err != nil { return errors.InternalServerError("go.micro.broker", err.Error()) } @@ -49,12 +50,17 @@ func (b *Broker) Subscribe(ctx context.Context, req *pb.SubscribeRequest, stream if err != nil { return errors.InternalServerError("go.micro.broker", err.Error()) } - defer sub.Unsubscribe() + defer func() { + log.Debugf("Unsubscribing from topic %s", req.Topic) + sub.Unsubscribe() + }() select { case <-ctx.Done(): + log.Debugf("Context done for subscription to topic %s", req.Topic) return nil - case <-errChan: + case err := <-errChan: + log.Debugf("Subscription error for topic %s: %v", req.Topic, err) return err } } diff --git a/broker/service/service.go b/broker/service/service.go index 63c09624..58942fe3 100644 --- a/broker/service/service.go +++ b/broker/service/service.go @@ -3,7 +3,9 @@ package service import ( "context" + "time" + "github.com/micro/go-micro/util/log" "github.com/micro/go-micro/broker" pb "github.com/micro/go-micro/broker/service/proto" "github.com/micro/go-micro/client" @@ -43,6 +45,7 @@ func (b *serviceBroker) Options() broker.Options { } func (b *serviceBroker) Publish(topic string, msg *broker.Message, opts ...broker.PublishOption) error { + log.Debugf("Publishing to topic %s broker %v", topic, b.Addrs) _, err := b.Client.Publish(context.TODO(), &pb.PublishRequest{ Topic: topic, Message: &pb.Message{ @@ -58,6 +61,7 @@ func (b *serviceBroker) Subscribe(topic string, handler broker.Handler, opts ... for _, o := range opts { o(&options) } + log.Debugf("Subscribing to topic %s queue %s broker %v", topic, options.Queue, b.Addrs) stream, err := b.Client.Subscribe(context.TODO(), &pb.SubscribeRequest{ Topic: topic, Queue: options.Queue, @@ -74,7 +78,33 @@ func (b *serviceBroker) Subscribe(topic string, handler broker.Handler, opts ... closed: make(chan bool), options: options, } - go sub.run() + + go func() { + for { + select { + case <-sub.closed: + log.Debugf("Unsubscribed from topic %s", topic) + return + default: + // run the subscriber + log.Debugf("Streaming from broker %v to topic [%s] queue [%s]", b.Addrs, topic, options.Queue) + if err := sub.run(); err != nil { + log.Debugf("Resubscribing to topic %s broker %v", topic, b.Addrs) + stream, err := b.Client.Subscribe(context.TODO(), &pb.SubscribeRequest{ + Topic: topic, + Queue: options.Queue, + }, client.WithAddress(b.Addrs...)) + if err != nil { + log.Debugf("Failed to resubscribe to topic %s: %v", topic, err) + time.Sleep(time.Second) + continue + } + // new stream + sub.stream = stream + } + } + } + }() return sub, nil } diff --git a/broker/service/subscriber.go b/broker/service/subscriber.go index 09a942c8..02511196 100644 --- a/broker/service/subscriber.go +++ b/broker/service/subscriber.go @@ -1,6 +1,7 @@ package service import ( + "github.com/micro/go-micro/util/log" "github.com/micro/go-micro/broker" pb "github.com/micro/go-micro/broker/service/proto" ) @@ -31,24 +32,45 @@ func (s *serviceEvent) Ack() error { return nil } -func (s *serviceSub) run() { +func (s *serviceSub) isClosed() bool { + select { + case <-s.closed: + return true + default: + return false + } +} + +func (s *serviceSub) run() error { exit := make(chan bool) go func() { select { case <-exit: - return case <-s.closed: - s.stream.Close() } + + // close the stream + s.stream.Close() }() for { // TODO: do not fail silently msg, err := s.stream.Recv() if err != nil { + log.Debugf("Streaming error for subcription to topic %s: %v", s.Topic(), err) + + // close the exit channel close(exit) - return + + // don't return an error if we unsubscribed + if s.isClosed() { + return nil + } + + // return stream error + return err } + // TODO: handle error s.handler(&serviceEvent{ topic: s.topic, From e36960612a353c454c4727c5a7a9badb3357e30a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 4 Oct 2019 16:40:16 +0100 Subject: [PATCH 034/344] go fmt --- broker/service/handler/handler.go | 2 +- broker/service/service.go | 2 +- broker/service/subscriber.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/broker/service/handler/handler.go b/broker/service/handler/handler.go index e0b5c3d4..3c96fd0d 100644 --- a/broker/service/handler/handler.go +++ b/broker/service/handler/handler.go @@ -3,10 +3,10 @@ package handler import ( "context" - "github.com/micro/go-micro/util/log" "github.com/micro/go-micro/broker" pb "github.com/micro/go-micro/broker/service/proto" "github.com/micro/go-micro/errors" + "github.com/micro/go-micro/util/log" ) type Broker struct { diff --git a/broker/service/service.go b/broker/service/service.go index 58942fe3..b2fb1bd1 100644 --- a/broker/service/service.go +++ b/broker/service/service.go @@ -5,10 +5,10 @@ import ( "context" "time" - "github.com/micro/go-micro/util/log" "github.com/micro/go-micro/broker" pb "github.com/micro/go-micro/broker/service/proto" "github.com/micro/go-micro/client" + "github.com/micro/go-micro/util/log" ) type serviceBroker struct { diff --git a/broker/service/subscriber.go b/broker/service/subscriber.go index 02511196..085b578a 100644 --- a/broker/service/subscriber.go +++ b/broker/service/subscriber.go @@ -1,9 +1,9 @@ package service import ( - "github.com/micro/go-micro/util/log" "github.com/micro/go-micro/broker" pb "github.com/micro/go-micro/broker/service/proto" + "github.com/micro/go-micro/util/log" ) type serviceSub struct { From cfb846ee7ef2af8b583b6fcc062d023b73801c2c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 4 Oct 2019 16:40:21 +0100 Subject: [PATCH 035/344] Fix race in cache --- registry/cache/cache.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/registry/cache/cache.go b/registry/cache/cache.go index 46460f7d..a17960e5 100644 --- a/registry/cache/cache.go +++ b/registry/cache/cache.go @@ -119,12 +119,10 @@ func (c *cache) get(service string) ([]*registry.Service, error) { // make a copy cp := registry.Copy(services) - // unlock the read lock - c.RUnlock() - // got services && within ttl so return cache if c.isValid(cp, ttl) { - // return servics + c.RUnlock() + // return services return cp, nil } @@ -163,8 +161,11 @@ func (c *cache) get(service string) ([]*registry.Service, error) { go c.run(service) } + // unlock the read lock + c.RUnlock() + // get and return services - return get(service, services) + return get(service, cp) } func (c *cache) set(service string, services []*registry.Service) { From 86984a8a8a2e37d6ae4de6bd3d6b0422361d9cf2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 4 Oct 2019 16:44:21 +0100 Subject: [PATCH 036/344] Extend the stream timeout --- broker/service/service.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/broker/service/service.go b/broker/service/service.go index b2fb1bd1..fff207fd 100644 --- a/broker/service/service.go +++ b/broker/service/service.go @@ -65,7 +65,7 @@ func (b *serviceBroker) Subscribe(topic string, handler broker.Handler, opts ... stream, err := b.Client.Subscribe(context.TODO(), &pb.SubscribeRequest{ Topic: topic, Queue: options.Queue, - }, client.WithAddress(b.Addrs...)) + }, client.WithAddress(b.Addrs...), client.WithRequestTimeout(time.Hour)) if err != nil { return nil, err } @@ -93,7 +93,7 @@ func (b *serviceBroker) Subscribe(topic string, handler broker.Handler, opts ... stream, err := b.Client.Subscribe(context.TODO(), &pb.SubscribeRequest{ Topic: topic, Queue: options.Queue, - }, client.WithAddress(b.Addrs...)) + }, client.WithAddress(b.Addrs...), client.WithRequestTimeout(time.Hour)) if err != nil { log.Debugf("Failed to resubscribe to topic %s: %v", topic, err) time.Sleep(time.Second) From 2fb2d7145e1a23cdcee775236159bab93d13ea24 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 6 Oct 2019 09:54:26 +0100 Subject: [PATCH 037/344] Fix etcd registry lease processing and suppression --- registry/etcd/etcd.go | 143 ++++++++++++++++++++++++++++++------------ 1 file changed, 102 insertions(+), 41 deletions(-) diff --git a/registry/etcd/etcd.go b/registry/etcd/etcd.go index f2780058..d328a2d7 100644 --- a/registry/etcd/etcd.go +++ b/registry/etcd/etcd.go @@ -13,9 +13,9 @@ import ( "time" "github.com/coreos/etcd/clientv3" - "github.com/micro/go-micro/registry" - "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" + "github.com/micro/go-micro/registry" + "github.com/micro/go-micro/util/log" hash "github.com/mitchellh/hashstructure" ) @@ -26,7 +26,8 @@ var ( type etcdRegistry struct { client *clientv3.Client options registry.Options - sync.Mutex + + sync.RWMutex register map[string]uint64 leases map[string]clientv3.LeaseID } @@ -131,62 +132,77 @@ func (e *etcdRegistry) Options() registry.Options { return e.options } -func (e *etcdRegistry) Deregister(s *registry.Service) error { +func (e *etcdRegistry) registerNode(s *registry.Service, node *registry.Node, opts ...registry.RegisterOption) error { if len(s.Nodes) == 0 { return errors.New("Require at least one node") } - e.Lock() - // delete our hash of the service - delete(e.register, s.Name) - // delete our lease of the service - delete(e.leases, s.Name) - e.Unlock() + // check existing lease cache + e.RLock() + leaseID, ok := e.leases[s.Name+node.Id] + e.RUnlock() - ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) - defer cancel() + if !ok { + // missing lease, check if the key exists + ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) + defer cancel() - for _, node := range s.Nodes { - _, err := e.client.Delete(ctx, nodePath(s.Name, node.Id)) + // look for the existing key + rsp, err := e.client.Get(ctx, nodePath(s.Name, node.Id)) if err != nil { return err } - } - return nil -} -func (e *etcdRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { - if len(s.Nodes) == 0 { - return errors.New("Require at least one node") + // get the existing lease + for _, kv := range rsp.Kvs { + if kv.Lease > 0 { + leaseID = clientv3.LeaseID(kv.Lease) + // create hash of service; uint64 + h, err := hash.Hash(node, nil) + if err != nil { + return err + } + + // save the info + e.Lock() + e.leases[s.Name+node.Id] = leaseID + e.register[s.Name+node.Id] = h + e.Unlock() + break + } + } } var leaseNotFound bool - //refreshing lease if existing - leaseID, ok := e.leases[s.Name] - if ok { + + // renew the lease if it exists + if leaseID > 0 { + log.Tracef("Renewing existing lease for %s %d", s.Name, leaseID) if _, err := e.client.KeepAliveOnce(context.TODO(), leaseID); err != nil { if err != rpctypes.ErrLeaseNotFound { return err } + log.Tracef("Lease not found for %s %d", s.Name, leaseID) // lease not found do register leaseNotFound = true } } // create hash of service; uint64 - h, err := hash.Hash(s, nil) + h, err := hash.Hash(node, nil) if err != nil { return err } - // get existing hash + // get existing hash for the service node e.Lock() - v, ok := e.register[s.Name] + v, ok := e.register[s.Name+node.Id] e.Unlock() // the service is unchanged, skip registering if ok && v == h && !leaseNotFound { + log.Tracef("Service %s node %s unchanged skipping registration", s.Name, node.Id) return nil } @@ -195,6 +211,7 @@ func (e *etcdRegistry) Register(s *registry.Service, opts ...registry.RegisterOp Version: s.Version, Metadata: s.Metadata, Endpoints: s.Endpoints, + Nodes: []*registry.Node{node}, } var options registry.RegisterOptions @@ -207,36 +224,80 @@ func (e *etcdRegistry) Register(s *registry.Service, opts ...registry.RegisterOp var lgr *clientv3.LeaseGrantResponse if options.TTL.Seconds() > 0 { + // get a lease used to expire keys since we have a ttl lgr, err = e.client.Grant(ctx, int64(options.TTL.Seconds())) if err != nil { return err } } + log.Tracef("Registering %s id %s with lease %v and ttl %v", service.Name, node.Id, lgr, options.TTL) + // create an entry for the node + if lgr != nil { + _, err = e.client.Put(ctx, nodePath(service.Name, node.Id), encode(service), clientv3.WithLease(lgr.ID)) + } else { + _, err = e.client.Put(ctx, nodePath(service.Name, node.Id), encode(service)) + } + if err != nil { + return err + } + + e.Lock() + // save our hash of the service + e.register[s.Name+node.Id] = h + // save our leaseID of the service + if lgr != nil { + e.leases[s.Name+node.Id] = lgr.ID + } + e.Unlock() + + return nil +} + +func (e *etcdRegistry) Deregister(s *registry.Service) error { + if len(s.Nodes) == 0 { + return errors.New("Require at least one node") + } + for _, node := range s.Nodes { - service.Nodes = []*registry.Node{node} - if lgr != nil { - _, err = e.client.Put(ctx, nodePath(service.Name, node.Id), encode(service), clientv3.WithLease(lgr.ID)) - } else { - _, err = e.client.Put(ctx, nodePath(service.Name, node.Id), encode(service)) - } + e.Lock() + // delete our hash of the service + delete(e.register, s.Name+node.Id) + // delete our lease of the service + delete(e.leases, s.Name+node.Id) + e.Unlock() + + ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) + defer cancel() + + log.Tracef("Deregistering %s id %s", s.Name, node.Id) + _, err := e.client.Delete(ctx, nodePath(s.Name, node.Id)) if err != nil { return err } } - e.Lock() - // save our hash of the service - e.register[s.Name] = h - // save our leaseID of the service - if lgr != nil { - e.leases[s.Name] = lgr.ID - } - e.Unlock() - return nil } +func (e *etcdRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { + if len(s.Nodes) == 0 { + return errors.New("Require at least one node") + } + + var gerr error + + // register each node individually + for _, node := range s.Nodes { + err := e.registerNode(s, node, opts...) + if err != nil { + gerr = err + } + } + + return gerr +} + func (e *etcdRegistry) GetService(name string) ([]*registry.Service, error) { ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) defer cancel() From 2c00e726b653650a71322ae229cdbe58432d4a24 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 6 Oct 2019 13:43:41 +0100 Subject: [PATCH 038/344] Decode and hash the existing node --- registry/etcd/etcd.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/registry/etcd/etcd.go b/registry/etcd/etcd.go index d328a2d7..73415530 100644 --- a/registry/etcd/etcd.go +++ b/registry/etcd/etcd.go @@ -157,10 +157,17 @@ func (e *etcdRegistry) registerNode(s *registry.Service, node *registry.Node, op for _, kv := range rsp.Kvs { if kv.Lease > 0 { leaseID = clientv3.LeaseID(kv.Lease) + + // decode the existing node + srv := decode(kv.Value) + if srv == nil || len(srv.Nodes) == 0 { + continue + } + // create hash of service; uint64 - h, err := hash.Hash(node, nil) + h, err := hash.Hash(srv.Nodes[0], nil) if err != nil { - return err + continue } // save the info @@ -168,6 +175,7 @@ func (e *etcdRegistry) registerNode(s *registry.Service, node *registry.Node, op e.leases[s.Name+node.Id] = leaseID e.register[s.Name+node.Id] = h e.Unlock() + break } } From b59454740852128b7e0b23591f8774e581ff921f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Oct 2019 08:32:28 +0100 Subject: [PATCH 039/344] Add service Name --- micro.go | 8 ++++++++ service.go | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/micro.go b/micro.go index 44bc52fc..295c08c5 100644 --- a/micro.go +++ b/micro.go @@ -14,11 +14,19 @@ type serviceKey struct{} // within go-micro. Its a convenience method for building // and initialising services. type Service interface { + // The service name + Name() string + // Init initialises options Init(...Option) + // Options returns the current options Options() Options + // Client is used to call services Client() client.Client + // Server is for handling requests and events Server() server.Server + // Run the service Run() error + // The service implementation String() string } diff --git a/service.go b/service.go index eed7f8ac..a0f9817c 100644 --- a/service.go +++ b/service.go @@ -37,6 +37,10 @@ func newService(opts ...Option) Service { } } +func (s *service) Name() string { + return s.opts.Server.Options().Name +} + // Init initialises options. Additionally it calls cmd.Init // which parses command line flags. cmd.Init is only called // on first Init. From fd8a0fb2f5141c1458637f308b529198619241b6 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Oct 2019 08:34:15 +0100 Subject: [PATCH 040/344] Update internal service definition --- service/service.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/service/service.go b/service/service.go index 5b9d3027..aca8acd6 100644 --- a/service/service.go +++ b/service/service.go @@ -6,11 +6,20 @@ import ( "github.com/micro/go-micro/server" ) +// Service is an interface for a micro service type Service interface { + // The service name + Name() string + // Init initialises options Init(...Option) + // Options returns the current options Options() Options + // Client is used to call services Client() client.Client + // Server is for handling requests and events Server() server.Server + // Run the service Run() error + // The service implementation String() string } From e9dcff49e087d2912053ddde06e79545edfb39f7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Oct 2019 16:11:52 +0100 Subject: [PATCH 041/344] Support listing full service info in etcd --- registry/etcd/etcd.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/registry/etcd/etcd.go b/registry/etcd/etcd.go index 73415530..9f01de8d 100644 --- a/registry/etcd/etcd.go +++ b/registry/etcd/etcd.go @@ -349,7 +349,7 @@ func (e *etcdRegistry) GetService(name string) ([]*registry.Service, error) { func (e *etcdRegistry) ListServices() ([]*registry.Service, error) { var services []*registry.Service - nameSet := make(map[string]struct{}) + versions := make(map[string]*registry.Service) ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) defer cancel() @@ -364,13 +364,20 @@ func (e *etcdRegistry) ListServices() ([]*registry.Service, error) { } for _, n := range rsp.Kvs { - if sn := decode(n.Value); sn != nil { - nameSet[sn.Name] = struct{}{} + sn := decode(n.Value) + if sn == nil { + continue } + v, ok := versions[sn.Name+sn.Version] + if !ok { + versions[sn.Name+sn.Version] = sn + continue + } + // append to service:version nodes + v.Nodes = append(v.Nodes, sn.Nodes...) } - for k := range nameSet { - service := ®istry.Service{} - service.Name = k + + for _, service := range versions { services = append(services, service) } From 2e1432d5dcc4e29c787edb448ade54023d023fe0 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Oct 2019 18:29:49 +0100 Subject: [PATCH 042/344] wait for response on accept message --- tunnel/session.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tunnel/session.go b/tunnel/session.go index e0eb8829..5d93fc32 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -163,7 +163,7 @@ func (s *session) Accept() error { case <-s.closed: return io.EOF case s.send <- msg: - return nil + // no op here } // wait for send response From 9d9683b6f9599afea16b0e3fa51c07fbac67dde3 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Mon, 7 Oct 2019 19:07:56 +0100 Subject: [PATCH 043/344] Recover net channel Accept errors. Init tunnel nodes before Connect --- network/default.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/network/default.go b/network/default.go index 315c8f19..3e8b4d61 100644 --- a/network/default.go +++ b/network/default.go @@ -213,6 +213,9 @@ func (n *network) handleNetConn(sess tunnel.Session, msg chan *transport.Message m := new(transport.Message) if err := sess.Recv(m); err != nil { log.Debugf("Network tunnel [%s] receive error: %v", NetworkChannel, err) + if sessErr := sess.Close(); sessErr != nil { + log.Debugf("Network tunnel [%s] closing connection error: %v", sessErr) + } return } @@ -230,9 +233,7 @@ func (n *network) acceptNetConn(l tunnel.Listener, recv chan *transport.Message) // accept a connection conn, err := l.Accept() if err != nil { - // TODO: handle this log.Debugf("Network tunnel [%s] accept error: %v", NetworkChannel, err) - return } select { @@ -730,6 +731,11 @@ func (n *network) Connect() error { log.Debugf("Network failed to resolve nodes: %v", err) } + // initialize the tunnel to resolved nodes + n.tunnel.Init( + tunnel.Nodes(nodes...), + ) + // connect network tunnel if err := n.tunnel.Connect(); err != nil { n.Unlock() @@ -742,11 +748,6 @@ func (n *network) Connect() error { n.server.Init(server.Advertise(n.tunnel.Address())) } - // initialize the tunnel to resolved nodes - n.tunnel.Init( - tunnel.Nodes(nodes...), - ) - // dial into ControlChannel to send route adverts ctrlClient, err := n.tunnel.Dial(ControlChannel, tunnel.DialMulticast()) if err != nil { From ad823d5177805a707ec3e2d3d8923b5a9b58ec6b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 8 Oct 2019 09:04:13 +0100 Subject: [PATCH 044/344] Add dns net.LookupHost resolver! --- network/resolver/dns/dns.go | 21 ++++++++++++++------- network/resolver/dnssrv/dnssrv.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 network/resolver/dnssrv/dnssrv.go diff --git a/network/resolver/dns/dns.go b/network/resolver/dns/dns.go index 3cfa2746..fe022d93 100644 --- a/network/resolver/dns/dns.go +++ b/network/resolver/dns/dns.go @@ -1,8 +1,7 @@ -// Package dns resolves names to dns srv records +// Package dns resolves names to dns records package dns import ( - "fmt" "net" "github.com/micro/go-micro/network/resolver" @@ -13,19 +12,27 @@ type Resolver struct{} // Resolve assumes ID is a domain name e.g micro.mu func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { - _, addrs, err := net.LookupSRV("network", "udp", name) + host, port, err := net.SplitHostPort(name) + if err != nil { + host = name + port = "8085" + } + + addrs, err := net.LookupHost(host) if err != nil { return nil, err } + var records []*resolver.Record + for _, addr := range addrs { - address := addr.Target - if addr.Port > 0 { - address = fmt.Sprintf("%s:%d", addr.Target, addr.Port) - } + // join resolved record with port + address := net.JoinHostPort(addr, port) + // append to record set records = append(records, &resolver.Record{ Address: address, }) } + return records, nil } diff --git a/network/resolver/dnssrv/dnssrv.go b/network/resolver/dnssrv/dnssrv.go new file mode 100644 index 00000000..75a11795 --- /dev/null +++ b/network/resolver/dnssrv/dnssrv.go @@ -0,0 +1,31 @@ +// Package dns srv resolves names to dns srv records +package dnssrv + +import ( + "fmt" + "net" + + "github.com/micro/go-micro/network/resolver" +) + +// Resolver is a DNS network resolve +type Resolver struct{} + +// Resolve assumes ID is a domain name e.g micro.mu +func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { + _, addrs, err := net.LookupSRV("network", "udp", name) + if err != nil { + return nil, err + } + var records []*resolver.Record + for _, addr := range addrs { + address := addr.Target + if addr.Port > 0 { + address = fmt.Sprintf("%s:%d", addr.Target, addr.Port) + } + records = append(records, &resolver.Record{ + Address: address, + }) + } + return records, nil +} From 94adeebed49405818533908a3bf801650fdcc87c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 8 Oct 2019 09:25:23 +0100 Subject: [PATCH 045/344] Use dns resolver on peer nodes --- network/default.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/network/default.go b/network/default.go index 3e8b4d61..422dfedf 100644 --- a/network/default.go +++ b/network/default.go @@ -11,6 +11,7 @@ import ( "github.com/micro/go-micro/client" rtr "github.com/micro/go-micro/client/selector/router" pbNet "github.com/micro/go-micro/network/proto" + "github.com/micro/go-micro/network/resolver/dns" "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/router" pbRtr "github.com/micro/go-micro/router/proto" @@ -73,7 +74,6 @@ func newNetwork(opts ...Option) Network { // init tunnel address to the network bind address options.Tunnel.Init( tunnel.Address(options.Address), - tunnel.Nodes(options.Peers...), ) // init router Id to the network id @@ -174,10 +174,22 @@ func (n *network) resolveNodes() ([]string, error) { nodeMap[record.Address] = true } + // use the dns resolver to expand peers + dns := &dns.Resolver{} + // append seed nodes if we have them for _, node := range n.options.Peers { - if _, ok := nodeMap[node]; !ok { - nodes = append(nodes, node) + // resolve anything that looks like a host name + records, err := dns.Resolve(node) + if err != nil { + continue + } + + // add to the node map + for _, record := range records { + if _, ok := nodeMap[record.Address]; !ok { + nodes = append(nodes, record.Address) + } } } From ec2fbde9793b91c0225acba8736c4e468503da11 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 8 Oct 2019 14:48:04 +0100 Subject: [PATCH 046/344] Limit the number of outbound connections to MaxConnections This commit also fixes control channel shenanigans: - recover error in control channel accept --- network/default.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/network/default.go b/network/default.go index 422dfedf..7e6abc4a 100644 --- a/network/default.go +++ b/network/default.go @@ -29,6 +29,8 @@ var ( ControlChannel = "control" // DefaultLink is default network link DefaultLink = "network" + // MaxCconnections is the max number of network client connections + MaxCconnections = 3 ) var ( @@ -193,6 +195,15 @@ func (n *network) resolveNodes() ([]string, error) { } } + // only return MaxCconnections nodes + if len(nodes) > MaxCconnections { + resNodes := make([]string, MaxCconnections) + for i, _ := range resNodes { + resNodes[i] = nodes[i] + } + return resNodes, nil + } + return nodes, nil } @@ -497,7 +508,6 @@ func (n *network) handleCtrlConn(sess tunnel.Session, msg chan *transport.Messag for { m := new(transport.Message) if err := sess.Recv(m); err != nil { - // TODO: should we bail here? log.Debugf("Network tunnel advert receive error: %v", err) return } @@ -516,9 +526,7 @@ func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *transport.Message // accept a connection conn, err := l.Accept() if err != nil { - // TODO: handle this log.Debugf("Network tunnel [%s] accept error: %v", ControlChannel, err) - return } select { From 61800fb7d71d07f31950b0d6a217de434fcdbbf2 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 8 Oct 2019 15:15:50 +0100 Subject: [PATCH 047/344] Fix typo: MaxCconnections -> MaxConnections --- network/default.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/network/default.go b/network/default.go index 7e6abc4a..19a414f4 100644 --- a/network/default.go +++ b/network/default.go @@ -29,8 +29,8 @@ var ( ControlChannel = "control" // DefaultLink is default network link DefaultLink = "network" - // MaxCconnections is the max number of network client connections - MaxCconnections = 3 + // MaxConnections is the max number of network client connections + MaxConnections = 3 ) var ( @@ -195,9 +195,9 @@ func (n *network) resolveNodes() ([]string, error) { } } - // only return MaxCconnections nodes - if len(nodes) > MaxCconnections { - resNodes := make([]string, MaxCconnections) + // only return MaxConnections nodes + if len(nodes) > MaxConnections { + resNodes := make([]string, MaxConnections) for i, _ := range resNodes { resNodes[i] = nodes[i] } From fe5846603a60d22662609b6f531ff6b45a455d2b Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 8 Oct 2019 15:48:52 +0100 Subject: [PATCH 048/344] Only limit the number of nodes returned by network resolver. --- network/default.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/network/default.go b/network/default.go index 19a414f4..de7ad719 100644 --- a/network/default.go +++ b/network/default.go @@ -171,9 +171,16 @@ func (n *network) resolveNodes() ([]string, error) { // collect network node addresses var nodes []string + + i := 0 for _, record := range records { nodes = append(nodes, record.Address) nodeMap[record.Address] = true + i++ + // break once MaxConnection nodes has been reached + if i == MaxConnections { + break + } } // use the dns resolver to expand peers @@ -195,15 +202,6 @@ func (n *network) resolveNodes() ([]string, error) { } } - // only return MaxConnections nodes - if len(nodes) > MaxConnections { - resNodes := make([]string, MaxConnections) - for i, _ := range resNodes { - resNodes[i] = nodes[i] - } - return resNodes, nil - } - return nodes, nil } From 88ef7851276e4b7d522c75ae7c18bd9e5492bbc2 Mon Sep 17 00:00:00 2001 From: orb li Date: Wed, 9 Oct 2019 14:45:51 +0800 Subject: [PATCH 049/344] Add dialoptions and calloptions --- client/grpc/grpc.go | 80 ++++++++++++++++++++++++++++++++++++++---- client/grpc/options.go | 26 ++++++++++++++ 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/client/grpc/grpc.go b/client/grpc/grpc.go index 439be459..36e9a927 100644 --- a/client/grpc/grpc.go +++ b/client/grpc/grpc.go @@ -109,13 +109,22 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R maxSendMsgSize := g.maxSendMsgSizeValue() var grr error - - cc, err := g.pool.getConn(address, grpc.WithDefaultCallOptions(grpc.ForceCodec(cf)), - grpc.WithTimeout(opts.DialTimeout), g.secure(), + + grpcDialOptions := []grpc.DialOption{ + grpc.WithDefaultCallOptions(grpc.ForceCodec(cf)), + grpc.WithTimeout(opts.DialTimeout), + g.secure(), grpc.WithDefaultCallOptions( grpc.MaxCallRecvMsgSize(maxRecvMsgSize), grpc.MaxCallSendMsgSize(maxSendMsgSize), - )) + ), + } + + if opts := g.getGrpcDialOptions(); opts != nil { + grpcDialOptions = append(grpcDialOptions, opts...) + } + + cc, err := g.pool.getConn(address, grpcDialOptions...) if err != nil { return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error sending request: %v", err)) } @@ -127,7 +136,11 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R ch := make(chan error, 1) go func() { - err := cc.Invoke(ctx, methodToGRPC(req.Service(), req.Endpoint()), req.Body(), rsp, grpc.CallContentSubtype(cf.Name())) + grpcCallOptions := []grpc.CallOption{grpc.CallContentSubtype(cf.Name())} + if opts := g.getGrpcCallOptions(); opts != nil { + grpcCallOptions = append(grpcCallOptions, opts...) + } + err := cc.Invoke(ctx, methodToGRPC(req.Service(), req.Endpoint()), req.Body(), rsp, grpcCallOptions...) ch <- microError(err) }() @@ -174,8 +187,17 @@ func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client defer cancel() wc := wrapCodec{cf} + + grpcDialOptions := []grpc.DialOption{ + grpc.WithDefaultCallOptions(grpc.ForceCodec(wc)), + g.secure(), + } + + if opts := g.getGrpcDialOptions(); opts != nil { + grpcDialOptions = append(grpcDialOptions, opts...) + } - cc, err := grpc.DialContext(dialCtx, address, grpc.WithDefaultCallOptions(grpc.ForceCodec(wc)), g.secure()) + cc, err := grpc.DialContext(dialCtx, address, grpcDialOptions...) if err != nil { return nil, errors.InternalServerError("go.micro.client", fmt.Sprintf("Error sending request: %v", err)) } @@ -186,7 +208,11 @@ func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client ServerStreams: true, } - st, err := cc.NewStream(ctx, desc, methodToGRPC(req.Service(), req.Endpoint())) + grpcCallOptions := []grpc.CallOption{} + if opts := g.getGrpcCallOptions(); opts != nil { + grpcCallOptions = append(grpcCallOptions, opts...) + } + st, err := cc.NewStream(ctx, desc, methodToGRPC(req.Service(), req.Endpoint()), grpcCallOptions...) if err != nil { return nil, errors.InternalServerError("go.micro.client", fmt.Sprintf("Error creating stream: %v", err)) } @@ -514,6 +540,46 @@ func (g *grpcClient) String() string { return "grpc" } +func (g *grpcClient) getGrpcDialOptions() []grpc.DialOption { + if g.opts.Context == nil { + return nil + } + + v := g.opts.Context.Value(grpcDialOptions{}) + + if v == nil { + return nil + } + + opts, ok := v.([]grpc.DialOption) + + if !ok { + return nil + } + + return opts +} + +func (g *grpcClient) getGrpcCallOptions() []grpc.CallOption { + if g.opts.CallOptions.Context == nil { + return nil + } + + v := g.opts.CallOptions.Context.Value(grpcCallOptions{}) + + if v == nil { + return nil + } + + opts, ok := v.([]grpc.CallOption) + + if !ok { + return nil + } + + return opts +} + func newClient(opts ...client.Option) client.Client { options := client.Options{ Codecs: make(map[string]codec.NewCodec), diff --git a/client/grpc/options.go b/client/grpc/options.go index c702ade3..e24924a9 100644 --- a/client/grpc/options.go +++ b/client/grpc/options.go @@ -23,6 +23,8 @@ type codecsKey struct{} type tlsAuth struct{} type maxRecvMsgSizeKey struct{} type maxSendMsgSizeKey struct{} +type grpcDialOptions struct{} +type grpcCallOptions struct{} // gRPC Codec to be used to encode/decode requests for a given content type func Codec(contentType string, c encoding.Codec) client.Option { @@ -72,3 +74,27 @@ func MaxSendMsgSize(s int) client.Option { o.Context = context.WithValue(o.Context, maxSendMsgSizeKey{}, s) } } + +// +// DialOptions to be used to configure gRPC dial options +// +func DialOptions(opts ...grpc.DialOption) client.Option { + return func(o *client.Options) { + if o.Context == nil { + o.Context = context.Background() + } + o.Context = context.WithValue(o.Context, grpcDialOptions{}, opts) + } +} + +// +// CallOptions to be used to configure gRPC call options +// +func CallOptions(opts ...grpc.CallOption) client.Option { + return func(o *client.Options) { + if o.CallOptions.Context == nil { + o.CallOptions.Context = context.Background() + } + o.CallOptions.Context = context.WithValue(o.CallOptions.Context, grpcCallOptions{}, opts) + } +} From 226d55d752b60cb5c8db761d0d892c61b13f3f25 Mon Sep 17 00:00:00 2001 From: orb li Date: Wed, 9 Oct 2019 16:48:45 +0800 Subject: [PATCH 050/344] Adding dependency --- client/grpc/options.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client/grpc/options.go b/client/grpc/options.go index e24924a9..dc674195 100644 --- a/client/grpc/options.go +++ b/client/grpc/options.go @@ -6,6 +6,7 @@ import ( "crypto/tls" "github.com/micro/go-micro/client" + "google.golang.org/grpc" "google.golang.org/grpc/encoding" ) From 107b7419b7830e8af99fa0f4fb6da35479ddcff8 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Wed, 9 Oct 2019 16:42:05 +0100 Subject: [PATCH 051/344] Start abstracting away the ACME provider (#830) * Start abstracting away the ACME provider * Move ACME to interface with sub-package implementations * Addressing comments * Library -> Provider * Missed a couple of Library -> Provider * One more Library -> Provider * remove constants --- api/server/acme/acme.go | 16 ++++++++++++++++ api/server/acme/autocert/autocert.go | 22 ++++++++++++++++++++++ api/server/acme/autocert/autocert_test.go | 15 +++++++++++++++ api/server/http/http.go | 3 +-- api/server/options.go | 21 +++++++++++++++------ 5 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 api/server/acme/acme.go create mode 100644 api/server/acme/autocert/autocert.go create mode 100644 api/server/acme/autocert/autocert_test.go diff --git a/api/server/acme/acme.go b/api/server/acme/acme.go new file mode 100644 index 00000000..0bf3698d --- /dev/null +++ b/api/server/acme/acme.go @@ -0,0 +1,16 @@ +// Package acme abstracts away various ACME libraries +package acme + +import ( + "errors" + "net" +) + +var ( + ErrProviderNotImplemented = errors.New("Provider not implemented") +) + +// Provider is a ACME provider interface +type Provider interface { + NewListener(...string) (net.Listener, error) +} diff --git a/api/server/acme/autocert/autocert.go b/api/server/acme/autocert/autocert.go new file mode 100644 index 00000000..9a760baf --- /dev/null +++ b/api/server/acme/autocert/autocert.go @@ -0,0 +1,22 @@ +// Package autocert is the ACME interpreter from golang.org/x/crypto/acme/autocert +package autocert + +import ( + "net" + + "github.com/micro/go-micro/api/server/acme" + "golang.org/x/crypto/acme/autocert" +) + +// autoCertACME is the ACME provider from golang.org/x/crypto/acme/autocert +type autocertProvider struct{} + +// NewListener implements acme.Provider +func (a *autocertProvider) NewListener(ACMEHosts ...string) (net.Listener, error) { + return autocert.NewListener(ACMEHosts...), nil +} + +// New returns an autocert acme.Provider +func New() acme.Provider { + return &autocertProvider{} +} diff --git a/api/server/acme/autocert/autocert_test.go b/api/server/acme/autocert/autocert_test.go new file mode 100644 index 00000000..4b8ab27c --- /dev/null +++ b/api/server/acme/autocert/autocert_test.go @@ -0,0 +1,15 @@ +package autocert + +import ( + "testing" +) + +func TestAutocert(t *testing.T) { + l := New() + if _, ok := l.(*autocertProvider); !ok { + t.Error("New() didn't return an autocertProvider") + } + if _, err := l.NewListener(); err != nil { + t.Error(err.Error()) + } +} diff --git a/api/server/http/http.go b/api/server/http/http.go index 0990dd8f..91d16339 100644 --- a/api/server/http/http.go +++ b/api/server/http/http.go @@ -11,7 +11,6 @@ import ( "github.com/gorilla/handlers" "github.com/micro/go-micro/api/server" "github.com/micro/go-micro/util/log" - "golang.org/x/crypto/acme/autocert" ) type httpServer struct { @@ -55,7 +54,7 @@ func (s *httpServer) Start() error { if s.opts.EnableACME { // should we check the address to make sure its using :443? - l = autocert.NewListener(s.opts.ACMEHosts...) + l, err = s.opts.ACMEProvider.NewListener(s.opts.ACMEHosts...) } else if s.opts.EnableTLS && s.opts.TLSConfig != nil { l, err = tls.Listen("tcp", s.address, s.opts.TLSConfig) } else { diff --git a/api/server/options.go b/api/server/options.go index cd47562f..b94c3da8 100644 --- a/api/server/options.go +++ b/api/server/options.go @@ -2,15 +2,24 @@ package server import ( "crypto/tls" + + "github.com/micro/go-micro/api/server/acme" ) type Option func(o *Options) type Options struct { - EnableACME bool - EnableTLS bool - ACMEHosts []string - TLSConfig *tls.Config + EnableACME bool + ACMEProvider acme.Provider + EnableTLS bool + ACMEHosts []string + TLSConfig *tls.Config +} + +func EnableACME(b bool) Option { + return func(o *Options) { + o.EnableACME = b + } } func ACMEHosts(hosts ...string) Option { @@ -19,9 +28,9 @@ func ACMEHosts(hosts ...string) Option { } } -func EnableACME(b bool) Option { +func ACMEProvider(p acme.Provider) Option { return func(o *Options) { - o.EnableACME = b + o.ACMEProvider = p } } From fe942374489b80da759bf4c531f97c0a2d383554 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 9 Oct 2019 17:13:52 +0100 Subject: [PATCH 052/344] Update router querying method (#834) * Add address to router query options. Drop Query interface for QueryOptions * Cleanup isMatch function * Update network proto --- client/selector/router/router.go | 4 +- network/default.go | 16 +-- network/handler/handler.go | 25 ++++- network/proto/network.pb.go | 165 +++++++++++++++++++++++-------- network/proto/network.proto | 11 +++ proxy/mucp/mucp.go | 2 +- router/default.go | 4 +- router/handler/router.go | 6 +- router/handler/table.go | 6 +- router/query.go | 32 +++--- router/router.go | 4 +- router/service/service.go | 10 +- router/service/table.go | 10 +- router/table.go | 53 +++++++--- router/table_test.go | 23 ++--- 15 files changed, 249 insertions(+), 122 deletions(-) diff --git a/client/selector/router/router.go b/client/selector/router/router.go index 90f74a9a..0f1f6c58 100644 --- a/client/selector/router/router.go +++ b/client/selector/router/router.go @@ -43,9 +43,9 @@ type routerKey struct{} func (r *routerSelector) getRoutes(service string) ([]router.Route, error) { if !r.remote { // lookup router for routes for the service - return r.r.Lookup(router.NewQuery( + return r.r.Lookup( router.QueryService(service), - )) + ) } // lookup the remote router diff --git a/network/default.go b/network/default.go index de7ad719..04385dcc 100644 --- a/network/default.go +++ b/network/default.go @@ -443,8 +443,8 @@ func (n *network) announce(client transport.Client) { } // pruneRoutes prunes routes return by given query -func (n *network) pruneRoutes(q router.Query) error { - routes, err := n.router.Table().Query(q) +func (n *network) pruneRoutes(q ...router.QueryOption) error { + routes, err := n.router.Table().Query(q...) if err != nil && err != router.ErrRouteNotFound { return err } @@ -461,18 +461,18 @@ func (n *network) pruneRoutes(q router.Query) error { // pruneNodeRoutes prunes routes that were either originated by or routable via given node func (n *network) prunePeerRoutes(peer *node) error { // lookup all routes originated by router - q := router.NewQuery( + q := []router.QueryOption{ router.QueryRouter(peer.id), - ) - if err := n.pruneRoutes(q); err != nil { + } + if err := n.pruneRoutes(q...); err != nil { return err } // lookup all routes routable via gw - q = router.NewQuery( + q = []router.QueryOption{ router.QueryGateway(peer.id), - ) - if err := n.pruneRoutes(q); err != nil { + } + if err := n.pruneRoutes(q...); err != nil { return err } diff --git a/network/handler/handler.go b/network/handler/handler.go index 840d6ce5..218d931a 100644 --- a/network/handler/handler.go +++ b/network/handler/handler.go @@ -7,6 +7,7 @@ import ( "github.com/micro/go-micro/errors" "github.com/micro/go-micro/network" pbNet "github.com/micro/go-micro/network/proto" + "github.com/micro/go-micro/router" pbRtr "github.com/micro/go-micro/router/proto" ) @@ -100,7 +101,29 @@ func (n *Network) Graph(ctx context.Context, req *pbNet.GraphRequest, resp *pbNe // Routes returns a list of routing table routes func (n *Network) Routes(ctx context.Context, req *pbNet.RoutesRequest, resp *pbNet.RoutesResponse) error { - routes, err := n.Network.Options().Router.Table().List() + // build query + + var qOpts []router.QueryOption + + if q := req.Query; q != nil { + if len(q.Service) > 0 { + qOpts = append(qOpts, router.QueryService(q.Service)) + } + if len(q.Address) > 0 { + qOpts = append(qOpts, router.QueryAddress(q.Address)) + } + if len(q.Gateway) > 0 { + qOpts = append(qOpts, router.QueryGateway(q.Gateway)) + } + if len(q.Router) > 0 { + qOpts = append(qOpts, router.QueryRouter(q.Router)) + } + if len(q.Network) > 0 { + qOpts = append(qOpts, router.QueryNetwork(q.Network)) + } + } + + routes, err := n.Network.Options().Router.Table().Query(qOpts...) if err != nil { return errors.InternalServerError("go.micro.network", "failed to list routes: %s", err) } diff --git a/network/proto/network.pb.go b/network/proto/network.pb.go index 0b339d69..694c9ecd 100644 --- a/network/proto/network.pb.go +++ b/network/proto/network.pb.go @@ -23,6 +23,78 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +// Query is passed in a LookupRequest +type Query struct { + Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Gateway string `protobuf:"bytes,3,opt,name=gateway,proto3" json:"gateway,omitempty"` + Router string `protobuf:"bytes,4,opt,name=router,proto3" json:"router,omitempty"` + Network string `protobuf:"bytes,5,opt,name=network,proto3" json:"network,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Query) Reset() { *m = Query{} } +func (m *Query) String() string { return proto.CompactTextString(m) } +func (*Query) ProtoMessage() {} +func (*Query) Descriptor() ([]byte, []int) { + return fileDescriptor_0b7953b26a7c4730, []int{0} +} + +func (m *Query) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Query.Unmarshal(m, b) +} +func (m *Query) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Query.Marshal(b, m, deterministic) +} +func (m *Query) XXX_Merge(src proto.Message) { + xxx_messageInfo_Query.Merge(m, src) +} +func (m *Query) XXX_Size() int { + return xxx_messageInfo_Query.Size(m) +} +func (m *Query) XXX_DiscardUnknown() { + xxx_messageInfo_Query.DiscardUnknown(m) +} + +var xxx_messageInfo_Query proto.InternalMessageInfo + +func (m *Query) GetService() string { + if m != nil { + return m.Service + } + return "" +} + +func (m *Query) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *Query) GetGateway() string { + if m != nil { + return m.Gateway + } + return "" +} + +func (m *Query) GetRouter() string { + if m != nil { + return m.Router + } + return "" +} + +func (m *Query) GetNetwork() string { + if m != nil { + return m.Network + } + return "" +} + // PeerRequest requests list of peers type NodesRequest struct { // node topology depth @@ -36,7 +108,7 @@ func (m *NodesRequest) Reset() { *m = NodesRequest{} } func (m *NodesRequest) String() string { return proto.CompactTextString(m) } func (*NodesRequest) ProtoMessage() {} func (*NodesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{0} + return fileDescriptor_0b7953b26a7c4730, []int{1} } func (m *NodesRequest) XXX_Unmarshal(b []byte) error { @@ -77,7 +149,7 @@ func (m *NodesResponse) Reset() { *m = NodesResponse{} } func (m *NodesResponse) String() string { return proto.CompactTextString(m) } func (*NodesResponse) ProtoMessage() {} func (*NodesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{1} + return fileDescriptor_0b7953b26a7c4730, []int{2} } func (m *NodesResponse) XXX_Unmarshal(b []byte) error { @@ -117,7 +189,7 @@ func (m *GraphRequest) Reset() { *m = GraphRequest{} } func (m *GraphRequest) String() string { return proto.CompactTextString(m) } func (*GraphRequest) ProtoMessage() {} func (*GraphRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{2} + return fileDescriptor_0b7953b26a7c4730, []int{3} } func (m *GraphRequest) XXX_Unmarshal(b []byte) error { @@ -156,7 +228,7 @@ func (m *GraphResponse) Reset() { *m = GraphResponse{} } func (m *GraphResponse) String() string { return proto.CompactTextString(m) } func (*GraphResponse) ProtoMessage() {} func (*GraphResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{3} + return fileDescriptor_0b7953b26a7c4730, []int{4} } func (m *GraphResponse) XXX_Unmarshal(b []byte) error { @@ -185,6 +257,8 @@ func (m *GraphResponse) GetRoot() *Peer { } type RoutesRequest struct { + // filter based on + Query *Query `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -194,7 +268,7 @@ func (m *RoutesRequest) Reset() { *m = RoutesRequest{} } func (m *RoutesRequest) String() string { return proto.CompactTextString(m) } func (*RoutesRequest) ProtoMessage() {} func (*RoutesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{4} + return fileDescriptor_0b7953b26a7c4730, []int{5} } func (m *RoutesRequest) XXX_Unmarshal(b []byte) error { @@ -215,6 +289,13 @@ func (m *RoutesRequest) XXX_DiscardUnknown() { var xxx_messageInfo_RoutesRequest proto.InternalMessageInfo +func (m *RoutesRequest) GetQuery() *Query { + if m != nil { + return m.Query + } + return nil +} + type RoutesResponse struct { Routes []*proto1.Route `protobuf:"bytes,1,rep,name=routes,proto3" json:"routes,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -226,7 +307,7 @@ func (m *RoutesResponse) Reset() { *m = RoutesResponse{} } func (m *RoutesResponse) String() string { return proto.CompactTextString(m) } func (*RoutesResponse) ProtoMessage() {} func (*RoutesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{5} + return fileDescriptor_0b7953b26a7c4730, []int{6} } func (m *RoutesResponse) XXX_Unmarshal(b []byte) error { @@ -264,7 +345,7 @@ func (m *ServicesRequest) Reset() { *m = ServicesRequest{} } func (m *ServicesRequest) String() string { return proto.CompactTextString(m) } func (*ServicesRequest) ProtoMessage() {} func (*ServicesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{6} + return fileDescriptor_0b7953b26a7c4730, []int{7} } func (m *ServicesRequest) XXX_Unmarshal(b []byte) error { @@ -296,7 +377,7 @@ func (m *ServicesResponse) Reset() { *m = ServicesResponse{} } func (m *ServicesResponse) String() string { return proto.CompactTextString(m) } func (*ServicesResponse) ProtoMessage() {} func (*ServicesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{7} + return fileDescriptor_0b7953b26a7c4730, []int{8} } func (m *ServicesResponse) XXX_Unmarshal(b []byte) error { @@ -339,7 +420,7 @@ func (m *Node) Reset() { *m = Node{} } func (m *Node) String() string { return proto.CompactTextString(m) } func (*Node) ProtoMessage() {} func (*Node) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{8} + return fileDescriptor_0b7953b26a7c4730, []int{9} } func (m *Node) XXX_Unmarshal(b []byte) error { @@ -387,7 +468,7 @@ func (m *Connect) Reset() { *m = Connect{} } func (m *Connect) String() string { return proto.CompactTextString(m) } func (*Connect) ProtoMessage() {} func (*Connect) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{9} + return fileDescriptor_0b7953b26a7c4730, []int{10} } func (m *Connect) XXX_Unmarshal(b []byte) error { @@ -428,7 +509,7 @@ func (m *Close) Reset() { *m = Close{} } func (m *Close) String() string { return proto.CompactTextString(m) } func (*Close) ProtoMessage() {} func (*Close) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{10} + return fileDescriptor_0b7953b26a7c4730, []int{11} } func (m *Close) XXX_Unmarshal(b []byte) error { @@ -471,7 +552,7 @@ func (m *Peer) Reset() { *m = Peer{} } func (m *Peer) String() string { return proto.CompactTextString(m) } func (*Peer) ProtoMessage() {} func (*Peer) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{11} + return fileDescriptor_0b7953b26a7c4730, []int{12} } func (m *Peer) XXX_Unmarshal(b []byte) error { @@ -507,6 +588,7 @@ func (m *Peer) GetPeers() []*Peer { } func init() { + proto.RegisterType((*Query)(nil), "go.micro.network.Query") proto.RegisterType((*NodesRequest)(nil), "go.micro.network.NodesRequest") proto.RegisterType((*NodesResponse)(nil), "go.micro.network.NodesResponse") proto.RegisterType((*GraphRequest)(nil), "go.micro.network.GraphRequest") @@ -526,33 +608,38 @@ func init() { } var fileDescriptor_0b7953b26a7c4730 = []byte{ - // 416 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x5d, 0x6f, 0xda, 0x30, - 0x14, 0x86, 0x21, 0x10, 0x3e, 0xce, 0x16, 0x60, 0xd6, 0x34, 0x45, 0xb9, 0xd8, 0x98, 0xb5, 0x0b, - 0x34, 0x6d, 0x66, 0x02, 0x71, 0x35, 0x4d, 0x9a, 0xc4, 0x45, 0xa5, 0x4a, 0x45, 0x95, 0xf9, 0x03, - 0x85, 0xc4, 0x82, 0xa8, 0x25, 0x4e, 0x1d, 0xd3, 0xfe, 0xc2, 0xfe, 0xaf, 0xca, 0x1f, 0xe1, 0x33, - 0x41, 0xed, 0x1d, 0xe7, 0xf0, 0xf8, 0x3d, 0x3e, 0xaf, 0xdf, 0xc0, 0x64, 0x15, 0xcb, 0xf5, 0x76, - 0x49, 0x42, 0xbe, 0x19, 0x6e, 0xe2, 0x50, 0xf0, 0xe1, 0x8a, 0xff, 0x36, 0x3f, 0x12, 0x26, 0x9f, - 0xb9, 0xb8, 0x1f, 0xa6, 0x82, 0xcb, 0x5d, 0x45, 0x74, 0x85, 0x7a, 0x2b, 0x4e, 0x34, 0x45, 0x6c, - 0x3f, 0x18, 0x97, 0x0b, 0x09, 0xbe, 0x95, 0x4c, 0x58, 0x1d, 0x53, 0x18, 0x19, 0xfc, 0x03, 0x3e, - 0xce, 0x78, 0xc4, 0x32, 0xca, 0x1e, 0xb7, 0x2c, 0x93, 0xe8, 0x33, 0xb8, 0x11, 0x4b, 0xe5, 0xda, - 0xaf, 0xf6, 0xab, 0x03, 0x8f, 0x9a, 0x02, 0xff, 0x03, 0xcf, 0x52, 0x59, 0xca, 0x93, 0x8c, 0xa1, - 0x5f, 0xe0, 0x26, 0xaa, 0xe1, 0x57, 0xfb, 0xb5, 0xc1, 0x87, 0xd1, 0x17, 0x72, 0x7a, 0x1b, 0xa2, - 0x78, 0x6a, 0x20, 0x35, 0xe4, 0x4a, 0x2c, 0xd2, 0xf5, 0xe5, 0x21, 0x7f, 0xc1, 0xb3, 0x94, 0x1d, - 0xf2, 0x13, 0xea, 0x82, 0x73, 0xa9, 0xa9, 0xc2, 0x19, 0xb7, 0x8c, 0x09, 0xaa, 0x19, 0xdc, 0x05, - 0x8f, 0xaa, 0xbd, 0xf2, 0x45, 0xf0, 0x7f, 0xe8, 0xe4, 0x0d, 0x2b, 0x47, 0xa0, 0xa1, 0x57, 0x2f, - 0xb8, 0xb4, 0xb5, 0x44, 0x1f, 0xa0, 0x96, 0xc2, 0x9f, 0xa0, 0x3b, 0x67, 0xe2, 0x29, 0x0e, 0xf7, - 0xa2, 0x04, 0x7a, 0xfb, 0x96, 0x95, 0x0d, 0xa0, 0x95, 0xd9, 0x9e, 0x16, 0x6e, 0xd3, 0x5d, 0x8d, - 0xff, 0x40, 0x5d, 0xf9, 0x80, 0x3a, 0xe0, 0xc4, 0x91, 0xde, 0xa3, 0x4d, 0x9d, 0x38, 0x42, 0x3e, - 0x34, 0x17, 0x51, 0x24, 0x58, 0x96, 0xf9, 0x8e, 0x6e, 0xe6, 0x25, 0x9e, 0x40, 0x73, 0xca, 0x93, - 0x84, 0x85, 0x52, 0xad, 0xaf, 0xec, 0x2b, 0x5f, 0x5f, 0x5b, 0xac, 0x19, 0x3c, 0x06, 0x77, 0xfa, - 0xc0, 0x8d, 0x67, 0x6f, 0x3e, 0x74, 0x07, 0x75, 0xe5, 0xe0, 0x7b, 0xce, 0xa8, 0x87, 0x4f, 0x19, - 0x13, 0xea, 0xde, 0xb5, 0x0b, 0x8f, 0x62, 0xa0, 0xd1, 0x8b, 0x03, 0xcd, 0x99, 0xe9, 0xa3, 0x6b, - 0x70, 0xf5, 0xf3, 0xa2, 0xaf, 0xe7, 0x67, 0x0e, 0xd3, 0x11, 0x7c, 0x2b, 0xfd, 0xdf, 0x38, 0x8e, - 0x2b, 0x4a, 0x4b, 0xe7, 0xb1, 0x48, 0xeb, 0x30, 0xce, 0x45, 0x5a, 0x47, 0x41, 0xc6, 0x15, 0x74, - 0x03, 0x0d, 0x13, 0x14, 0x54, 0x00, 0x1f, 0x65, 0x2a, 0xe8, 0x97, 0x03, 0x3b, 0xb9, 0x39, 0xb4, - 0xf2, 0x88, 0xa0, 0xef, 0xe7, 0xfc, 0x49, 0xa2, 0x02, 0x7c, 0x09, 0xc9, 0x45, 0x97, 0x0d, 0xfd, - 0xb1, 0x8e, 0x5f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x3a, 0x63, 0x7a, 0x7b, 0x2c, 0x04, 0x00, 0x00, + // 482 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0x6d, 0x3e, 0x9c, 0xb4, 0x03, 0x29, 0x65, 0x85, 0x8a, 0xe5, 0x03, 0x84, 0x15, 0x87, 0x0a, + 0x51, 0x07, 0x35, 0xea, 0x09, 0x81, 0x90, 0x7a, 0x40, 0x42, 0xa2, 0x82, 0xed, 0x1f, 0x20, 0x8d, + 0x47, 0x89, 0x05, 0xf5, 0xba, 0xbb, 0x1b, 0xaa, 0xfe, 0x02, 0x7e, 0x19, 0xff, 0x0b, 0xed, 0xce, + 0xd8, 0xb4, 0x89, 0x1d, 0xc1, 0xcd, 0x6f, 0xe7, 0xcd, 0x9b, 0xdd, 0x37, 0x4f, 0x86, 0xd3, 0x45, + 0xee, 0x96, 0xab, 0xcb, 0x74, 0xae, 0xaf, 0x26, 0x57, 0xf9, 0xdc, 0xe8, 0xc9, 0x42, 0x1f, 0xd3, + 0x47, 0x81, 0xee, 0x46, 0x9b, 0xef, 0x93, 0xd2, 0x68, 0x57, 0xa3, 0x34, 0x20, 0x71, 0xb0, 0xd0, + 0x69, 0x60, 0xa5, 0x7c, 0x9e, 0x4c, 0xdb, 0x85, 0x8c, 0x5e, 0x39, 0x34, 0xac, 0x43, 0x80, 0x64, + 0xe4, 0xaf, 0x0e, 0x44, 0x5f, 0x57, 0x68, 0x6e, 0x45, 0x0c, 0x43, 0x8b, 0xe6, 0x67, 0x3e, 0xc7, + 0xb8, 0x33, 0xee, 0x1c, 0xed, 0xa9, 0x0a, 0xfa, 0xca, 0x2c, 0xcb, 0x0c, 0x5a, 0x1b, 0x77, 0xa9, + 0xc2, 0xd0, 0x57, 0x16, 0x33, 0x87, 0x37, 0xb3, 0xdb, 0xb8, 0x47, 0x15, 0x86, 0xe2, 0x10, 0x06, + 0x34, 0x27, 0xee, 0x87, 0x02, 0x23, 0xdf, 0xc1, 0xf7, 0x8d, 0x23, 0xea, 0x60, 0x28, 0x5f, 0xc2, + 0xc3, 0x73, 0x9d, 0xa1, 0x55, 0x78, 0xbd, 0x42, 0xeb, 0xc4, 0x13, 0x88, 0x32, 0x2c, 0xdd, 0x32, + 0xdc, 0x66, 0xa4, 0x08, 0xc8, 0x77, 0x30, 0x62, 0x96, 0x2d, 0x75, 0x61, 0x51, 0xbc, 0x86, 0xa8, + 0xf0, 0x07, 0x71, 0x67, 0xdc, 0x3b, 0x7a, 0x70, 0x72, 0x98, 0xae, 0xfb, 0x92, 0x7a, 0xbe, 0x22, + 0x92, 0x1f, 0xf2, 0xd1, 0xcc, 0xca, 0xe5, 0xf6, 0x21, 0x6f, 0x61, 0xc4, 0x2c, 0x1e, 0xf2, 0x0a, + 0xfa, 0x46, 0x6b, 0x17, 0x58, 0x8d, 0x33, 0xbe, 0x20, 0x1a, 0x15, 0x38, 0xf2, 0x3d, 0x8c, 0x94, + 0x7f, 0x6b, 0xfd, 0x90, 0x63, 0x88, 0xae, 0xbd, 0xc3, 0xdc, 0xfd, 0x74, 0xb3, 0x3b, 0x2c, 0x40, + 0x11, 0x4b, 0x7e, 0x80, 0xfd, 0xaa, 0x9f, 0xa7, 0xa7, 0xec, 0x65, 0xc3, 0x1b, 0x79, 0x97, 0xa1, + 0x81, 0x3d, 0xb6, 0xf2, 0x31, 0x3c, 0xba, 0xa0, 0xd5, 0x55, 0x77, 0x90, 0x29, 0x1c, 0xfc, 0x3d, + 0x62, 0xd9, 0x04, 0x76, 0x79, 0xc3, 0x24, 0xbc, 0xa7, 0x6a, 0x2c, 0xdf, 0x40, 0xdf, 0xdb, 0x26, + 0xf6, 0xa1, 0x9b, 0x67, 0x9c, 0x87, 0x6e, 0x9e, 0xb5, 0x47, 0x41, 0x9e, 0xc2, 0xf0, 0x4c, 0x17, + 0x05, 0xce, 0x9d, 0x77, 0xcb, 0xbb, 0xdd, 0xee, 0x56, 0xd8, 0x48, 0xe0, 0xc8, 0x29, 0x44, 0x67, + 0x3f, 0x34, 0x59, 0xfc, 0xcf, 0x4d, 0xdf, 0xa0, 0xef, 0x0d, 0xff, 0x9f, 0x1e, 0x9f, 0x93, 0x12, + 0xd1, 0xf8, 0x7b, 0xf7, 0xb6, 0xec, 0x90, 0x48, 0x27, 0xbf, 0xbb, 0x30, 0x3c, 0xa7, 0x73, 0xf1, + 0x09, 0xa2, 0x90, 0x06, 0xf1, 0x6c, 0xb3, 0xe7, 0x6e, 0x98, 0x92, 0xe7, 0xad, 0x75, 0x72, 0x5c, + 0xee, 0x78, 0xad, 0x10, 0xdf, 0x26, 0xad, 0xbb, 0xe9, 0x6f, 0xd2, 0xba, 0x97, 0x7b, 0xb9, 0x23, + 0x3e, 0xc3, 0x80, 0x82, 0x22, 0x1a, 0xc8, 0xf7, 0x22, 0x98, 0x8c, 0xdb, 0x09, 0xb5, 0xdc, 0x05, + 0xec, 0x56, 0x11, 0x11, 0x2f, 0x36, 0xf9, 0x6b, 0x89, 0x4a, 0xe4, 0x36, 0x4a, 0x25, 0x7a, 0x39, + 0x08, 0x7f, 0x99, 0xe9, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x84, 0x80, 0x26, 0xe5, 0x04, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/network/proto/network.proto b/network/proto/network.proto index a82d75a1..8097f8c0 100644 --- a/network/proto/network.proto +++ b/network/proto/network.proto @@ -16,6 +16,15 @@ service Network { rpc Services(ServicesRequest) returns (ServicesResponse) {}; } +// Query is passed in a LookupRequest +message Query { + string service = 1; + string address = 2; + string gateway = 3; + string router = 4; + string network = 5; +} + // PeerRequest requests list of peers message NodesRequest { // node topology depth @@ -38,6 +47,8 @@ message GraphResponse { } message RoutesRequest { + // filter based on + Query query = 1; } message RoutesResponse { diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index 8cd6df85..ce02c6b6 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -128,7 +128,7 @@ func (p *Proxy) getRoute(service string) ([]router.Route, error) { p.Unlock() // lookup the routes in the router - results, err := p.Router.Lookup(router.NewQuery(router.QueryService(service))) + results, err := p.Router.Lookup(router.QueryService(service)) if err != nil { // check the status of the router if status := p.Router.Status(); status.Code == router.Error { diff --git a/router/default.go b/router/default.go index aa5561ee..a25990a2 100644 --- a/router/default.go +++ b/router/default.go @@ -722,8 +722,8 @@ func (r *router) Solicit() error { } // Lookup routes in the routing table -func (r *router) Lookup(q Query) ([]Route, error) { - return r.table.Query(q) +func (r *router) Lookup(q ...QueryOption) ([]Route, error) { + return r.table.Query(q...) } // Watch routes diff --git a/router/handler/router.go b/router/handler/router.go index 6c681742..f8b8cc51 100644 --- a/router/handler/router.go +++ b/router/handler/router.go @@ -17,11 +17,7 @@ type Router struct { // Lookup looks up routes in the routing table and returns them func (r *Router) Lookup(ctx context.Context, req *pb.LookupRequest, resp *pb.LookupResponse) error { - query := router.NewQuery( - router.QueryService(req.Query.Service), - ) - - routes, err := r.Router.Lookup(query) + routes, err := r.Router.Lookup(router.QueryService(req.Query.Service)) if err != nil { return errors.InternalServerError("go.micro.router", "failed to lookup routes: %v", err) } diff --git a/router/handler/table.go b/router/handler/table.go index 63e3c96c..899a2795 100644 --- a/router/handler/table.go +++ b/router/handler/table.go @@ -90,11 +90,7 @@ func (t *Table) List(ctx context.Context, req *pb.Request, resp *pb.ListResponse } func (t *Table) Query(ctx context.Context, req *pb.QueryRequest, resp *pb.QueryResponse) error { - query := router.NewQuery( - router.QueryService(req.Query.Service), - ) - - routes, err := t.Router.Table().Query(query) + routes, err := t.Router.Table().Query(router.QueryService(req.Query.Service)) if err != nil { return errors.InternalServerError("go.micro.router", "failed to lookup routes: %s", err) } diff --git a/router/query.go b/router/query.go index 3e2c3d38..557d44e0 100644 --- a/router/query.go +++ b/router/query.go @@ -7,6 +7,8 @@ type QueryOption func(*QueryOptions) type QueryOptions struct { // Service is destination service name Service string + // Address of the service + Address string // Gateway is route gateway Gateway string // Network is network address @@ -22,6 +24,13 @@ func QueryService(s string) QueryOption { } } +// QueryAddress sets service to query +func QueryAddress(a string) QueryOption { + return func(o *QueryOptions) { + o.Address = a + } +} + // QueryGateway sets gateway address to query func QueryGateway(g string) QueryOption { return func(o *QueryOptions) { @@ -43,22 +52,12 @@ func QueryRouter(r string) QueryOption { } } -// Query is routing table query -type Query interface { - // Options returns query options - Options() QueryOptions -} - -// query is a basic implementation of Query -type query struct { - opts QueryOptions -} - // NewQuery creates new query and returns it -func NewQuery(opts ...QueryOption) Query { +func NewQuery(opts ...QueryOption) QueryOptions { // default options qopts := QueryOptions{ Service: "*", + Address: "*", Gateway: "*", Network: "*", Router: "*", @@ -68,12 +67,5 @@ func NewQuery(opts ...QueryOption) Query { o(&qopts) } - return &query{ - opts: qopts, - } -} - -// Options returns query options -func (q *query) Options() QueryOptions { - return q.opts + return qopts } diff --git a/router/router.go b/router/router.go index 3e8f00cd..756a5a42 100644 --- a/router/router.go +++ b/router/router.go @@ -31,7 +31,7 @@ type Router interface { // Solicit advertises the whole routing table to the network Solicit() error // Lookup queries routes in the routing table - Lookup(Query) ([]Route, error) + Lookup(...QueryOption) ([]Route, error) // Watch returns a watcher which tracks updates to the routing table Watch(opts ...WatchOption) (Watcher, error) // Start starts the router @@ -55,7 +55,7 @@ type Table interface { // List all routes in the table List() ([]Route, error) // Query routes in the routing table - Query(Query) ([]Route, error) + Query(...QueryOption) ([]Route, error) } // Option used by the router diff --git a/router/service/service.go b/router/service/service.go index 7f521e8d..068d0ae3 100644 --- a/router/service/service.go +++ b/router/service/service.go @@ -321,13 +321,15 @@ func (s *svc) Stop() error { } // Lookup looks up routes in the routing table and returns them -func (s *svc) Lookup(q router.Query) ([]router.Route, error) { +func (s *svc) Lookup(q ...router.QueryOption) ([]router.Route, error) { // call the router + query := router.NewQuery(q...) + resp, err := s.router.Lookup(context.Background(), &pb.LookupRequest{ Query: &pb.Query{ - Service: q.Options().Service, - Gateway: q.Options().Gateway, - Network: q.Options().Network, + Service: query.Service, + Gateway: query.Gateway, + Network: query.Network, }, }, s.callOpts...) diff --git a/router/service/table.go b/router/service/table.go index a6c44fd3..940fbd41 100644 --- a/router/service/table.go +++ b/router/service/table.go @@ -90,13 +90,15 @@ func (t *table) List() ([]router.Route, error) { } // Lookup looks up routes in the routing table and returns them -func (t *table) Query(q router.Query) ([]router.Route, error) { +func (t *table) Query(q ...router.QueryOption) ([]router.Route, error) { + query := router.NewQuery(q...) + // call the router resp, err := t.table.Query(context.Background(), &pb.QueryRequest{ Query: &pb.Query{ - Service: q.Options().Service, - Gateway: q.Options().Gateway, - Network: q.Options().Network, + Service: query.Service, + Gateway: query.Gateway, + Network: query.Network, }, }, t.callOpts...) diff --git a/router/table.go b/router/table.go index ecef0c62..6701c05f 100644 --- a/router/table.go +++ b/router/table.go @@ -135,22 +135,44 @@ func (t *table) List() ([]Route, error) { } // isMatch checks if the route matches given query options -func isMatch(route Route, gateway, network, router string) bool { - if gateway == "*" || gateway == route.Gateway { - if network == "*" || network == route.Network { - if router == "*" || router == route.Router { - return true - } +func isMatch(route Route, address, gateway, network, router string) bool { + // matches the values provided + match := func(a, b string) bool { + if a == "*" || a == b { + return true + } + return false + } + + // a simple struct to hold our values + type compare struct { + a string + b string + } + + // compare the following values + values := []compare{ + {gateway, route.Gateway}, + {network, route.Network}, + {router, route.Router}, + {address, route.Address}, + } + + for _, v := range values { + // attempt to match each value + if !match(v.a, v.b) { + return false } } - return false + + return true } // findRoutes finds all the routes for given network and router and returns them -func findRoutes(routes map[uint64]Route, gateway, network, router string) []Route { +func findRoutes(routes map[uint64]Route, address, gateway, network, router string) []Route { var results []Route for _, route := range routes { - if isMatch(route, gateway, network, router) { + if isMatch(route, address, gateway, network, router) { results = append(results, route) } } @@ -158,21 +180,24 @@ func findRoutes(routes map[uint64]Route, gateway, network, router string) []Rout } // Lookup queries routing table and returns all routes that match the lookup query -func (t *table) Query(q Query) ([]Route, error) { +func (t *table) Query(q ...QueryOption) ([]Route, error) { t.RLock() defer t.RUnlock() - if q.Options().Service != "*" { - if _, ok := t.routes[q.Options().Service]; !ok { + // create new query options + opts := NewQuery(q...) + + if opts.Service != "*" { + if _, ok := t.routes[opts.Service]; !ok { return nil, ErrRouteNotFound } - return findRoutes(t.routes[q.Options().Service], q.Options().Gateway, q.Options().Network, q.Options().Router), nil + return findRoutes(t.routes[opts.Service], opts.Address, opts.Gateway, opts.Network, opts.Router), nil } var results []Route // search through all destinations for _, routes := range t.routes { - results = append(results, findRoutes(routes, q.Options().Gateway, q.Options().Network, q.Options().Router)...) + results = append(results, findRoutes(routes, opts.Address, opts.Gateway, opts.Network, opts.Router)...) } return results, nil diff --git a/router/table_test.go b/router/table_test.go index d989ee3b..b37de1cb 100644 --- a/router/table_test.go +++ b/router/table_test.go @@ -123,18 +123,15 @@ func TestQuery(t *testing.T) { } // return all routes - query := NewQuery() - - routes, err := table.Query(query) + routes, err := table.Query() if err != nil { t.Errorf("error looking up routes: %s", err) } // query routes particular network network := "net1" - query = NewQuery(QueryNetwork(network)) - routes, err = table.Query(query) + routes, err = table.Query(QueryNetwork(network)) if err != nil { t.Errorf("error looking up routes: %s", err) } @@ -151,9 +148,8 @@ func TestQuery(t *testing.T) { // query routes for particular gateway gateway := "gw1" - query = NewQuery(QueryGateway(gateway)) - routes, err = table.Query(query) + routes, err = table.Query(QueryGateway(gateway)) if err != nil { t.Errorf("error looking up routes: %s", err) } @@ -168,9 +164,8 @@ func TestQuery(t *testing.T) { // query routes for particular router router := "rtr1" - query = NewQuery(QueryRouter(router)) - routes, err = table.Query(query) + routes, err = table.Query(QueryRouter(router)) if err != nil { t.Errorf("error looking up routes: %s", err) } @@ -184,13 +179,13 @@ func TestQuery(t *testing.T) { } // query particular gateway and network - query = NewQuery( + query := []QueryOption{ QueryGateway(gateway), QueryNetwork(network), QueryRouter(router), - ) + } - routes, err = table.Query(query) + routes, err = table.Query(query...) if err != nil { t.Errorf("error looking up routes: %s", err) } @@ -212,9 +207,7 @@ func TestQuery(t *testing.T) { } // non-existen route query - query = NewQuery(QueryService("foobar")) - - routes, err = table.Query(query) + routes, err = table.Query(QueryService("foobar")) if err != ErrRouteNotFound { t.Errorf("error looking up routes. Expected: %s, found: %s", ErrRouteNotFound, err) } From 96e564e40225b4f4ce4ee20a7fd6458020e2d52e Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 9 Oct 2019 16:03:06 +0100 Subject: [PATCH 053/344] Add router advertisement Strategy option to router. --- router/default.go | 21 +++++++-------------- router/options.go | 9 +++++++++ router/router.go | 10 ++++++++++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/router/default.go b/router/default.go index a25990a2..273eeda6 100644 --- a/router/default.go +++ b/router/default.go @@ -319,23 +319,13 @@ func (r *router) advertiseTable() error { for { select { case <-ticker.C: - // list routing table routes to announce - routes, err := r.table.List() + // do full table flush + events, err := r.flushRouteEvents(Update) if err != nil { - return fmt.Errorf("failed listing routes: %s", err) - } - // collect all the added routes before we attempt to add default gateway - events := make([]*Event, len(routes)) - for i, route := range routes { - event := &Event{ - Type: Update, - Timestamp: time.Now(), - Route: route, - } - events[i] = event + return fmt.Errorf("failed flushing routes: %s", err) } - // advertise all routes as Update events to subscribers + // advertise routes to subscribers if len(events) > 0 { log.Debugf("Router flushing table with %d events: %s", len(events), r.options.Id) r.advertWg.Add(1) @@ -692,6 +682,9 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { return nil, fmt.Errorf("failed listing routes: %s", err) } + // TODO: flush the routes based on strategy here + // - collapse the routes per service-metric-locality (prefer your routes) + // build a list of events to advertise events := make([]*Event, len(routes)) for i, route := range routes { diff --git a/router/options.go b/router/options.go index 13119e1b..47fd82e8 100644 --- a/router/options.go +++ b/router/options.go @@ -18,6 +18,8 @@ type Options struct { Network string // Registry is the local registry Registry registry.Registry + // Advertise is the advertising strategy + Advertise Strategy // Client for calling router Client client.Client } @@ -64,6 +66,13 @@ func Registry(r registry.Registry) Option { } } +// Strategy sets route advertising strategy +func Advertise(a Strategy) Option { + return func(o *Options) { + o.Advertise = a + } +} + // DefaultOptions returns router default options func DefaultOptions() Options { return Options{ diff --git a/router/router.go b/router/router.go index 756a5a42..938eaf5d 100644 --- a/router/router.go +++ b/router/router.go @@ -139,6 +139,16 @@ type Advert struct { Events []*Event } +// Strategy is route advertisement strategy +type Strategy int + +const ( + // All advertises all routes to the network + All Strategy = iota + // Optimal advertises optimal routes to the network + Optimal +) + // NewRouter creates new Router and returns it func NewRouter(opts ...Option) Router { return newRouter(opts...) From 837597fe6f296abb9bc89cfaa51551275bb96cb7 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 9 Oct 2019 17:23:02 +0100 Subject: [PATCH 054/344] Make Optimal strategy default. Collapse routing tables based on strategy --- router/default.go | 49 +++++++++++++++++++++++++++++++++++++++++++---- router/options.go | 9 +++++---- router/router.go | 12 ++++++++++++ 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/router/default.go b/router/default.go index 273eeda6..b7845b8e 100644 --- a/router/default.go +++ b/router/default.go @@ -682,18 +682,59 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { return nil, fmt.Errorf("failed listing routes: %s", err) } - // TODO: flush the routes based on strategy here - // - collapse the routes per service-metric-locality (prefer your routes) + r.RLock() + advertStrategy := r.options.Advertise + r.RUnlock() + + if advertStrategy == All { + // build a list of events to advertise + events := make([]*Event, len(routes)) + for i, route := range routes { + event := &Event{ + Type: evType, + Timestamp: time.Now(), + Route: route, + } + events[i] = event + } + return events, nil + } + + // routeMap stores optimal routes per service + optimalRoutes := make(map[string]Route) + + // go through all routes found in the routing table and collapse them to optimal routes + for _, route := range routes { + optimal, ok := optimalRoutes[route.Service] + if !ok { + optimalRoutes[route.Service] = route + continue + } + // if the current optimal route metric is higher than routing table route, replace it + if optimal.Metric > route.Metric { + optimalRoutes[route.Service] = route + continue + } + // if the metrics are the same, prefer advertising your own route + if optimal.Metric == route.Metric { + if route.Router == r.options.Id { + optimalRoutes[route.Service] = route + continue + } + } + } // build a list of events to advertise - events := make([]*Event, len(routes)) - for i, route := range routes { + events := make([]*Event, len(optimalRoutes)) + i := 0 + for _, route := range optimalRoutes { event := &Event{ Type: evType, Timestamp: time.Now(), Route: route, } events[i] = event + i++ } return events, nil diff --git a/router/options.go b/router/options.go index 47fd82e8..37cfe5aa 100644 --- a/router/options.go +++ b/router/options.go @@ -76,9 +76,10 @@ func Advertise(a Strategy) Option { // DefaultOptions returns router default options func DefaultOptions() Options { return Options{ - Id: uuid.New().String(), - Address: DefaultAddress, - Network: DefaultNetwork, - Registry: registry.DefaultRegistry, + Id: uuid.New().String(), + Address: DefaultAddress, + Network: DefaultNetwork, + Registry: registry.DefaultRegistry, + Advertise: Optimal, } } diff --git a/router/router.go b/router/router.go index 938eaf5d..d0d32c0e 100644 --- a/router/router.go +++ b/router/router.go @@ -149,6 +149,18 @@ const ( Optimal ) +// String returns human readable Strategy +func (s Strategy) String() string { + switch s { + case All: + return "all" + case Optimal: + return "optimal" + default: + return "unknown" + } +} + // NewRouter creates new Router and returns it func NewRouter(opts ...Option) Router { return newRouter(opts...) From d5ce96da244b6c6675d56f5f44a7657a3650569f Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 9 Oct 2019 18:19:48 +0100 Subject: [PATCH 055/344] Avoid locking on reading strategy for now --- router/default.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/router/default.go b/router/default.go index b7845b8e..3c8f037e 100644 --- a/router/default.go +++ b/router/default.go @@ -682,11 +682,7 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { return nil, fmt.Errorf("failed listing routes: %s", err) } - r.RLock() - advertStrategy := r.options.Advertise - r.RUnlock() - - if advertStrategy == All { + if r.options.Advertise == All { // build a list of events to advertise events := make([]*Event, len(routes)) for i, route := range routes { From 7a4bff4e9fffa1620cfac5dd66a772336560e237 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 9 Oct 2019 19:08:24 +0100 Subject: [PATCH 056/344] Changed names of some variables. --- router/default.go | 19 +++++++++++-------- router/options.go | 2 +- router/router.go | 14 +++++++------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/router/default.go b/router/default.go index 3c8f037e..48cdb230 100644 --- a/router/default.go +++ b/router/default.go @@ -682,7 +682,7 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { return nil, fmt.Errorf("failed listing routes: %s", err) } - if r.options.Advertise == All { + if r.options.Advertise == AdvertiseAll { // build a list of events to advertise events := make([]*Event, len(routes)) for i, route := range routes { @@ -697,33 +697,36 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { } // routeMap stores optimal routes per service - optimalRoutes := make(map[string]Route) + bestRoutes := make(map[string]Route) // go through all routes found in the routing table and collapse them to optimal routes for _, route := range routes { - optimal, ok := optimalRoutes[route.Service] + routeKey := route.Service + "@" + route.Network + optimal, ok := bestRoutes[routeKey] if !ok { - optimalRoutes[route.Service] = route + bestRoutes[routeKey] = route continue } // if the current optimal route metric is higher than routing table route, replace it if optimal.Metric > route.Metric { - optimalRoutes[route.Service] = route + bestRoutes[routeKey] = route continue } // if the metrics are the same, prefer advertising your own route if optimal.Metric == route.Metric { if route.Router == r.options.Id { - optimalRoutes[route.Service] = route + bestRoutes[routeKey] = route continue } } } + log.Debugf("Router advertising %d best routes out of %d", len(bestRoutes), len(routes)) + // build a list of events to advertise - events := make([]*Event, len(optimalRoutes)) + events := make([]*Event, len(bestRoutes)) i := 0 - for _, route := range optimalRoutes { + for _, route := range bestRoutes { event := &Event{ Type: evType, Timestamp: time.Now(), diff --git a/router/options.go b/router/options.go index 37cfe5aa..31d82ea8 100644 --- a/router/options.go +++ b/router/options.go @@ -80,6 +80,6 @@ func DefaultOptions() Options { Address: DefaultAddress, Network: DefaultNetwork, Registry: registry.DefaultRegistry, - Advertise: Optimal, + Advertise: AdvertiseBest, } } diff --git a/router/router.go b/router/router.go index d0d32c0e..cd300e7e 100644 --- a/router/router.go +++ b/router/router.go @@ -143,19 +143,19 @@ type Advert struct { type Strategy int const ( - // All advertises all routes to the network - All Strategy = iota - // Optimal advertises optimal routes to the network - Optimal + // AdvertiseAll advertises all routes to the network + AdvertiseAll Strategy = iota + // AdvertiseBest advertises optimal routes to the network + AdvertiseBest ) // String returns human readable Strategy func (s Strategy) String() string { switch s { - case All: + case AdvertiseAll: return "all" - case Optimal: - return "optimal" + case AdvertiseBest: + return "best" default: return "unknown" } From 77108771db383631df49ef08732eb5159b85157c Mon Sep 17 00:00:00 2001 From: orb li Date: Thu, 10 Oct 2019 13:55:16 +0800 Subject: [PATCH 057/344] Conceptual deliverable --- client/grpc/grpc.go | 14 +++++++------- client/grpc/options.go | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/client/grpc/grpc.go b/client/grpc/grpc.go index 36e9a927..fd5bc853 100644 --- a/client/grpc/grpc.go +++ b/client/grpc/grpc.go @@ -109,7 +109,7 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R maxSendMsgSize := g.maxSendMsgSizeValue() var grr error - + grpcDialOptions := []grpc.DialOption{ grpc.WithDefaultCallOptions(grpc.ForceCodec(cf)), grpc.WithTimeout(opts.DialTimeout), @@ -119,7 +119,7 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R grpc.MaxCallSendMsgSize(maxSendMsgSize), ), } - + if opts := g.getGrpcDialOptions(); opts != nil { grpcDialOptions = append(grpcDialOptions, opts...) } @@ -187,12 +187,12 @@ func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client defer cancel() wc := wrapCodec{cf} - + grpcDialOptions := []grpc.DialOption{ - grpc.WithDefaultCallOptions(grpc.ForceCodec(wc)), + grpc.WithDefaultCallOptions(grpc.ForceCodec(wc)), g.secure(), } - + if opts := g.getGrpcDialOptions(); opts != nil { grpcDialOptions = append(grpcDialOptions, opts...) } @@ -541,11 +541,11 @@ func (g *grpcClient) String() string { } func (g *grpcClient) getGrpcDialOptions() []grpc.DialOption { - if g.opts.Context == nil { + if g.opts.CallOptions.Context == nil { return nil } - v := g.opts.Context.Value(grpcDialOptions{}) + v := g.opts.CallOptions.Context.Value(grpcDialOptions{}) if v == nil { return nil diff --git a/client/grpc/options.go b/client/grpc/options.go index dc674195..e7f2fceb 100644 --- a/client/grpc/options.go +++ b/client/grpc/options.go @@ -79,8 +79,8 @@ func MaxSendMsgSize(s int) client.Option { // // DialOptions to be used to configure gRPC dial options // -func DialOptions(opts ...grpc.DialOption) client.Option { - return func(o *client.Options) { +func DialOptions(opts ...grpc.DialOption) client.CallOption { + return func(o *client.CallOptions) { if o.Context == nil { o.Context = context.Background() } @@ -91,11 +91,11 @@ func DialOptions(opts ...grpc.DialOption) client.Option { // // CallOptions to be used to configure gRPC call options // -func CallOptions(opts ...grpc.CallOption) client.Option { - return func(o *client.Options) { - if o.CallOptions.Context == nil { - o.CallOptions.Context = context.Background() +func CallOptions(opts ...grpc.CallOption) client.CallOption { + return func(o *client.CallOptions) { + if o.Context == nil { + o.Context = context.Background() } - o.CallOptions.Context = context.WithValue(o.CallOptions.Context, grpcCallOptions{}, opts) + o.Context = context.WithValue(o.Context, grpcCallOptions{}, opts) } } From 0dee11e006a28dc6aa1d05d766861002801e6ce2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Oct 2019 11:25:28 +0100 Subject: [PATCH 058/344] Prune the peer address --- network/default.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index 04385dcc..72b638ef 100644 --- a/network/default.go +++ b/network/default.go @@ -470,7 +470,7 @@ func (n *network) prunePeerRoutes(peer *node) error { // lookup all routes routable via gw q = []router.QueryOption{ - router.QueryGateway(peer.id), + router.QueryGateway(peer.address), } if err := n.pruneRoutes(q...); err != nil { return err From b2f99a27b7c1c53b9b2248acec7226e49227f703 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Oct 2019 14:35:11 +0100 Subject: [PATCH 059/344] Visit all the nodes in flatten --- network/handler/handler.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/network/handler/handler.go b/network/handler/handler.go index 218d931a..62162e64 100644 --- a/network/handler/handler.go +++ b/network/handler/handler.go @@ -27,16 +27,14 @@ func flatten(n network.Node, visited map[string]bool) []network.Node { visited = make(map[string]bool) } - // check if already visited - if visited[n.Id()] == true { - return nil - } - // create new list of nodes var nodes []network.Node - // append the current node - nodes = append(nodes, n) + // check if already visited + if visited[n.Id()] == false { + // append the current node + nodes = append(nodes, n) + } // set to visited visited[n.Id()] = true From f6931f3da7c4434787150e620a69ab8ba44b639a Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 10 Oct 2019 15:25:54 +0100 Subject: [PATCH 060/344] Prune routes from routers that are not in your peer graph --- network/default.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/network/default.go b/network/default.go index 72b638ef..58d74573 100644 --- a/network/default.go +++ b/network/default.go @@ -497,6 +497,25 @@ func (n *network) prune() { log.Debugf("Network failed pruning peer %s routes: %v", id, err) } } + // get a list of all routes + routes, err := n.options.Router.Table().List() + if err != nil { + log.Debugf("Network failed listing routes: %v", err) + continue + } + // collect all the router IDs in the routing table + routers := make(map[string]bool) + for _, route := range routes { + if _, ok := routers[route.Router]; !ok { + routers[route.Router] = true + // if the router is NOT in our peer graph, delete all routes originated by it + if peerNode := n.node.GetPeerNode(route.Router); peerNode == nil { + if err := n.pruneRoutes(router.QueryRouter(route.Router)); err != nil { + log.Debugf("Network failed deleting routes by %s: %v", route.Router, err) + } + } + } + } } } } From 59a3e7d4f496bec0bd2ff5c31e479a1063d8d062 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Oct 2019 19:16:31 +0100 Subject: [PATCH 061/344] Use etcd serializable option --- registry/etcd/etcd.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/registry/etcd/etcd.go b/registry/etcd/etcd.go index 9f01de8d..ed4fec1c 100644 --- a/registry/etcd/etcd.go +++ b/registry/etcd/etcd.go @@ -8,6 +8,7 @@ import ( "errors" "net" "path" + "sort" "strings" "sync" "time" @@ -20,7 +21,7 @@ import ( ) var ( - prefix = "/micro/registry" + prefix = "/micro/registry/" ) type etcdRegistry struct { @@ -148,7 +149,7 @@ func (e *etcdRegistry) registerNode(s *registry.Service, node *registry.Node, op defer cancel() // look for the existing key - rsp, err := e.client.Get(ctx, nodePath(s.Name, node.Id)) + rsp, err := e.client.Get(ctx, nodePath(s.Name, node.Id), clientv3.WithSerializable()) if err != nil { return err } @@ -310,7 +311,7 @@ func (e *etcdRegistry) GetService(name string) ([]*registry.Service, error) { ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) defer cancel() - rsp, err := e.client.Get(ctx, servicePath(name)+"/", clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortDescend)) + rsp, err := e.client.Get(ctx, servicePath(name)+"/", clientv3.WithPrefix(), clientv3.WithSerializable()) if err != nil { return nil, err } @@ -344,6 +345,7 @@ func (e *etcdRegistry) GetService(name string) ([]*registry.Service, error) { for _, service := range serviceMap { services = append(services, service) } + return services, nil } @@ -354,7 +356,7 @@ func (e *etcdRegistry) ListServices() ([]*registry.Service, error) { ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) defer cancel() - rsp, err := e.client.Get(ctx, prefix, clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortDescend)) + rsp, err := e.client.Get(ctx, prefix, clientv3.WithPrefix(), clientv3.WithSerializable()) if err != nil { return nil, err } @@ -381,6 +383,9 @@ func (e *etcdRegistry) ListServices() ([]*registry.Service, error) { services = append(services, service) } + // sort the services + sort.Slice(services, func(i, j int) bool { return services[i].Name < services[j].Name }) + return services, nil } From 5e5d57d9545f4ff7b40f5b012539f11b3844890c Mon Sep 17 00:00:00 2001 From: Peter Theophanous Date: Thu, 10 Oct 2019 22:23:33 +0100 Subject: [PATCH 062/344] bumped quic-go version to v0.12.1 --- go.mod | 26 +++++++++-- go.sum | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 162 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index f5889f4e..bbc95291 100644 --- a/go.mod +++ b/go.mod @@ -6,10 +6,14 @@ require ( github.com/BurntSushi/toml v0.3.1 github.com/beevik/ntp v0.2.0 github.com/bitly/go-simplejson v0.5.0 + github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/bwmarrin/discordgo v0.19.0 + github.com/coreos/bbolt v1.3.3 // indirect github.com/coreos/etcd v3.3.15+incompatible + github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c github.com/fsnotify/fsnotify v1.4.7 github.com/fsouza/go-dockerclient v1.4.4 @@ -17,32 +21,46 @@ require ( github.com/go-log/log v0.1.0 github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect + github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect + github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc // indirect github.com/golang/protobuf v1.3.2 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/websocket v1.4.1 + github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.11.3 // indirect github.com/hashicorp/consul/api v1.2.0 github.com/hashicorp/hcl v1.0.0 - github.com/hashicorp/memberlist v0.1.5 + github.com/hashicorp/memberlist v0.1.5 // indirect github.com/imdario/mergo v0.3.7 + github.com/jonboulle/clockwork v0.1.0 // indirect github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 github.com/leodido/go-urn v1.1.0 // indirect - github.com/lucas-clemente/quic-go v0.12.0 + github.com/lucas-clemente/quic-go v0.12.1 github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 github.com/mitchellh/hashstructure v1.0.0 + github.com/nats-io/nats-server/v2 v2.1.0 // indirect github.com/nats-io/nats.go v1.8.1 github.com/nlopes/slack v0.6.0 github.com/pkg/errors v0.8.1 + github.com/prometheus/client_golang v1.1.0 // indirect + github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 // indirect + github.com/soheilhy/cmux v0.1.4 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect - go.uber.org/atomic v1.4.0 // indirect + github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect + go.etcd.io/bbolt v1.3.3 // indirect go.uber.org/multierr v1.2.0 // indirect - go.uber.org/zap v1.10.0 // indirect golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 + golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 // indirect google.golang.org/grpc v1.24.0 + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v9 v9.30.0 gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/telegram-bot-api.v4 v4.6.4 + sigs.k8s.io/yaml v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 648484b8..d80851cf 100644 --- a/go.sum +++ b/go.sum @@ -7,18 +7,29 @@ github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+q github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +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/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +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/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY= github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= @@ -26,15 +37,22 @@ github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wX 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/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.15+incompatible h1:+9RjdC18gMxNQVvSiXvObLu29mOFmkgdsB4cRTlV+EE= github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/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/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b h1:+Ga+YpCDpcY1fln6GI0fiiirpqHGcob5/Vk3oKNuGdU= @@ -46,6 +64,7 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c h1:pBgVXWDXju1m8W4lnEeIqTHPOzhTUO81a7yknM/xQR4= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY= @@ -55,26 +74,40 @@ github.com/fsouza/go-dockerclient v1.4.4 h1:Sd5nD4wdAgiPxvrbYUzT2ZZNmPk3z+GGnZ+f github.com/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA= 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.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 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-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/gogo/protobuf v1.1.1/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/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-20191002201903-404acd9df4cc h1:55rEp52jU6bkyslZ1+C/7NGfpQsEc6pxGLAGDOctqbw= +github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= @@ -86,9 +119,15 @@ github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/consul v1.6.1 h1:ISPgwOO8/vPYrCXQNyx63eJAYjPGRnmFsXK7aj2XICs= +github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= +github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= +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.11.3 h1:h8+NsYENhxNTuq+dobk3+ODoJtwY4Fu0WQXsxJfL8aM= +github.com/grpc-ecosystem/grpc-gateway v1.11.3/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/consul/api v1.2.0 h1:oPsuzLp2uk7I7rojPKuncWbZ+m5TMoD4Ivs+2Rkeh4Y= github.com/hashicorp/consul/api v1.2.0/go.mod h1:1SIkFYi2ZTXUE5Kgt179+4hH33djo11+0Eo2XgTAtkw= +github.com/hashicorp/consul/sdk v0.2.0 h1:GWFYFmry/k4b1hEoy7kSkmU8e30GAyI4VZHk0fRxeL4= github.com/hashicorp/consul/sdk v0.2.0/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= @@ -106,6 +145,7 @@ github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sL 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 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= 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= @@ -119,6 +159,7 @@ github.com/hashicorp/memberlist v0.1.5 h1:AYBsgJOW9gab/toO5tEB8lWetVgDKZycqkebJ8 github.com/hashicorp/memberlist v0.1.5/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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= @@ -127,29 +168,38 @@ github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +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/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 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.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +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/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= -github.com/lucas-clemente/quic-go v0.12.0 h1:TRbvZ6F++sofeGbh+Z2IIyIOhl8KyGnYuA06g2yrHdI= -github.com/lucas-clemente/quic-go v0.12.0/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= +github.com/lucas-clemente/quic-go v0.12.1 h1:BPITli+6KnKogtTxBk2aS4okr5dUHz2LtIDAP1b8UL4= +github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI= github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/micro/cli v0.2.0 h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA= github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= @@ -161,6 +211,7 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT 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 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/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y= @@ -171,18 +222,31 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats-server/v2 v2.1.0 h1:Yi0+ZhRPtPAGeIxFn5erIeJIV9wXA+JznfSxK621Fbk= +github.com/nats-io/nats-server/v2 v2.1.0/go.mod h1:r5y0WgCag0dTj/qiHkHrXAcKQ/f5GMOZaEGdoxxnJ4I= github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= +github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA= github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk= 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.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= @@ -190,37 +254,72 @@ 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/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +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/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 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/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +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 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.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= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= +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/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +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.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4= go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +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= @@ -231,67 +330,105 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc h1:KyTYo8xkh/2WdbFLUyQwBS0Jfn3qfZ9QmuPbok2oENE= golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc/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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/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-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-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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-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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-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-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-20190129075346-302c3dd5f1cc/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-20190221075227-b4e8571b14e0/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq/5B590r6RlnL/G8Sz7w= +golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-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-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/telegram-bot-api.v4 v4.6.4 h1:hpHWhzn4jTCsAJZZ2loNKfy2QWyPDRJVl3aTFXeMW8g= gopkg.in/telegram-bot-api.v4 v4.6.4/go.mod h1:5DpGO5dbumb40px+dXcwCpcjmeHNYLpk0bp3XRNvWDM= +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/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 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= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From fc89c9831e05b156eac80af26dbfeaea65f639c9 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 11 Oct 2019 10:47:42 +0100 Subject: [PATCH 063/344] heck cache status error --- registry/cache/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/cache/cache.go b/registry/cache/cache.go index a17960e5..8acd79a3 100644 --- a/registry/cache/cache.go +++ b/registry/cache/cache.go @@ -144,7 +144,7 @@ func (c *cache) get(service string) ([]*registry.Service, error) { } // reset the status - if c.getStatus(); err != nil { + if err := c.getStatus(); err != nil { c.setStatus(nil) } From 21469a0427db1773be5395904d48528731fae707 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 11 Oct 2019 11:02:45 +0100 Subject: [PATCH 064/344] Clean up dead tunnel code Running go vet on tunnel package returns: $ go vet ./... ./default.go:929:2: unreachable code ./link.go:104:2: unreachable code ./listener.go:184:2: unreachable code ./session.go:241:2: unreachable code --- tunnel/default.go | 10 ++++------ tunnel/link.go | 1 - tunnel/listener.go | 1 - tunnel/session.go | 2 -- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index 6107021e..c65829b1 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -919,14 +919,12 @@ func (t *tun) Close() error { default: close(t.closed) t.connected = false - - // send a close message - // we don't close the link - // just the tunnel - return t.close() } - return nil + // send a close message + // we don't close the link + // just the tunnel + return t.close() } // Dial an address diff --git a/tunnel/link.go b/tunnel/link.go index f2395727..181121e7 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -98,7 +98,6 @@ func (l *link) Close() error { return nil default: close(l.closed) - return nil } return nil diff --git a/tunnel/listener.go b/tunnel/listener.go index ee394519..f154b2a6 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -181,5 +181,4 @@ func (t *tunListener) Accept() (Session, error) { } return c, nil } - return nil, nil } diff --git a/tunnel/session.go b/tunnel/session.go index 5d93fc32..6757f150 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -237,8 +237,6 @@ func (s *session) Send(m *transport.Message) error { case <-s.closed: return io.EOF } - - return nil } // Recv is used to receive a message From a96f6adf07f334b1ff61bbb8f1c1e547bef1e996 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 11 Oct 2019 14:08:50 +0100 Subject: [PATCH 065/344] store handler implementation --- store/etcd/etcd.go | 59 ++- store/memory/memory.go | 58 +-- store/memory/memory_test.go | 2 +- store/service/handler/handler.go | 89 +++++ store/service/proto/store.micro.go | 207 ++++++++++ store/service/proto/store.pb.go | 618 +++++++++++++++++++++++++++++ store/service/proto/store.proto | 48 +++ store/store.go | 6 +- sync/map.go | 6 +- 9 files changed, 1048 insertions(+), 45 deletions(-) create mode 100644 store/service/handler/handler.go create mode 100644 store/service/proto/store.micro.go create mode 100644 store/service/proto/store.pb.go create mode 100644 store/service/proto/store.proto diff --git a/store/etcd/etcd.go b/store/etcd/etcd.go index 7d866d63..d0094fb4 100644 --- a/store/etcd/etcd.go +++ b/store/etcd/etcd.go @@ -5,6 +5,7 @@ import ( "context" "log" + "github.com/coreos/etcd/mvcc/mvccpb" client "github.com/coreos/etcd/clientv3" "github.com/micro/go-micro/config/options" "github.com/micro/go-micro/store" @@ -15,30 +16,56 @@ type ekv struct { kv client.KV } -func (e *ekv) Read(key string) (*store.Record, error) { - keyval, err := e.kv.Get(context.Background(), key) - if err != nil { - return nil, err +func (e *ekv) Read(keys ...string) ([]*store.Record, error) { + var values []*mvccpb.KeyValue + + for _, key := range keys { + keyval, err := e.kv.Get(context.Background(), key) + if err != nil { + return nil, err + } + + if keyval == nil || len(keyval.Kvs) == 0 { + return nil, store.ErrNotFound + } + + values = append(values, keyval.Kvs...) } - if keyval == nil || len(keyval.Kvs) == 0 { - return nil, store.ErrNotFound + var records []*store.Record + + for _, kv := range values { + records = append(records, &store.Record{ + Key: string(kv.Key), + Value: kv.Value, + // TODO: implement expiry + }) } - return &store.Record{ - Key: string(keyval.Kvs[0].Key), - Value: keyval.Kvs[0].Value, - }, nil + return records, nil } -func (e *ekv) Delete(key string) error { - _, err := e.kv.Delete(context.Background(), key) - return err +func (e *ekv) Delete(keys ...string) error { + var gerr error + for _, key := range keys { + _, err := e.kv.Delete(context.Background(), key) + if err != nil { + gerr = err + } + } + return gerr } -func (e *ekv) Write(record *store.Record) error { - _, err := e.kv.Put(context.Background(), record.Key, string(record.Value)) - return err +func (e *ekv) Write(records ...*store.Record) error { + var gerr error + for _, record := range records { + // TODO create lease to expire keys + _, err := e.kv.Put(context.Background(), record.Key, string(record.Value)) + if err != nil { + gerr = err + } + } + return gerr } func (e *ekv) Sync() ([]*store.Record, error) { diff --git a/store/memory/memory.go b/store/memory/memory.go index a7d5a83c..3eeab31d 100644 --- a/store/memory/memory.go +++ b/store/memory/memory.go @@ -48,51 +48,61 @@ func (m *memoryStore) Sync() ([]*store.Record, error) { return values, nil } -func (m *memoryStore) Read(key string) (*store.Record, error) { +func (m *memoryStore) Read(keys ...string) ([]*store.Record, error) { m.RLock() defer m.RUnlock() - v, ok := m.values[key] - if !ok { - return nil, store.ErrNotFound - } + var records []*store.Record - // get expiry - d := v.r.Expiry - t := time.Since(v.c) - - // expired - if d > time.Duration(0) { - if t > d { + for _, key := range keys { + v, ok := m.values[key] + if !ok { return nil, store.ErrNotFound } - // update expiry - v.r.Expiry -= t - v.c = time.Now() + + // get expiry + d := v.r.Expiry + t := time.Since(v.c) + + // expired + if d > time.Duration(0) { + if t > d { + return nil, store.ErrNotFound + } + // update expiry + v.r.Expiry -= t + v.c = time.Now() + } + + records = append(records, v.r) } - return v.r, nil + return records, nil } -func (m *memoryStore) Write(r *store.Record) error { +func (m *memoryStore) Write(records ...*store.Record) error { m.Lock() defer m.Unlock() - // set the record - m.values[r.Key] = &memoryRecord{ - r: r, - c: time.Now(), + for _, r := range records { + // set the record + m.values[r.Key] = &memoryRecord{ + r: r, + c: time.Now(), + } } return nil } -func (m *memoryStore) Delete(key string) error { +func (m *memoryStore) Delete(keys ...string) error { m.Lock() defer m.Unlock() - // delete the value - delete(m.values, key) + for _, key := range keys { + // delete the value + delete(m.values, key) + } return nil } diff --git a/store/memory/memory_test.go b/store/memory/memory_test.go index 639d18db..de889856 100644 --- a/store/memory/memory_test.go +++ b/store/memory/memory_test.go @@ -25,7 +25,7 @@ func TestReadRecordExpire(t *testing.T) { if err != nil { t.Fatal(err) } - if rrec.Expiry >= expire { + if rrec[0].Expiry >= expire { t.Fatal("expiry of read record is not changed") } diff --git a/store/service/handler/handler.go b/store/service/handler/handler.go new file mode 100644 index 00000000..51af02b6 --- /dev/null +++ b/store/service/handler/handler.go @@ -0,0 +1,89 @@ +package handler + +import ( + "context" + "io" + "time" + + "github.com/micro/go-micro/errors" + "github.com/micro/go-micro/store" + pb "github.com/micro/go-micro/store/service/proto" +) + +type Store struct { + Store store.Store +} + +func (s *Store) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error { + vals, err := s.Store.Read(req.Keys...) + if err != nil { + return errors.InternalServerError("go.micro.store", err.Error()) + } + for _, val := range vals { + rsp.Records = append(rsp.Records, &pb.Record{ + Key: val.Key, + Value: val.Value, + Expiry: int64(val.Expiry.Seconds()), + }) + } + return nil +} + +func (s *Store) Write(ctx context.Context, req *pb.WriteRequest, rsp *pb.WriteResponse) error { + var records []*store.Record + + for _, record := range req.Records { + records = append(records, &store.Record{ + Key: record.Key, + Value: record.Value, + Expiry: time.Duration(record.Expiry) * time.Second, + }) + } + + err := s.Store.Write(records...) + if err != nil { + return errors.InternalServerError("go.micro.store", err.Error()) + } + return nil +} + +func (s *Store) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.DeleteResponse) error { + err := s.Store.Delete(req.Keys...) + if err != nil { + return errors.InternalServerError("go.micro.store", err.Error()) + } + return nil +} + +func (s *Store) Sync(ctx context.Context, req *pb.SyncRequest, stream pb.Store_SyncStream) error { + var vals []*store.Record + var err error + + if len(req.Key) > 0 { + vals, err = s.Store.Read(req.Key) + } else { + vals, err = s.Store.Sync() + } + if err != nil { + return errors.InternalServerError("go.micro.store", err.Error()) + } + rsp := new(pb.SyncResponse) + + // TODO: batch sync + for _, val := range vals { + rsp.Records = append(rsp.Records, &pb.Record{ + Key: val.Key, + Value: val.Value, + Expiry: int64(val.Expiry.Seconds()), + }) + } + + err = stream.Send(rsp) + if err == io.EOF { + return nil + } + if err != nil { + return errors.InternalServerError("go.micro.store", err.Error()) + } + return nil +} diff --git a/store/service/proto/store.micro.go b/store/service/proto/store.micro.go new file mode 100644 index 00000000..ce4885ec --- /dev/null +++ b/store/service/proto/store.micro.go @@ -0,0 +1,207 @@ +// Code generated by protoc-gen-micro. DO NOT EDIT. +// source: micro/go-micro/store/service/proto/store.proto + +package go_micro_store + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +import ( + context "context" + client "github.com/micro/go-micro/client" + server "github.com/micro/go-micro/server" +) + +// 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.ProtoPackageIsVersion3 // please upgrade the proto package + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ client.Option +var _ server.Option + +// Client API for Store service + +type StoreService interface { + Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) + Write(ctx context.Context, in *WriteRequest, opts ...client.CallOption) (*WriteResponse, error) + Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) + Sync(ctx context.Context, in *SyncRequest, opts ...client.CallOption) (Store_SyncService, error) +} + +type storeService struct { + c client.Client + name string +} + +func NewStoreService(name string, c client.Client) StoreService { + if c == nil { + c = client.NewClient() + } + if len(name) == 0 { + name = "go.micro.store" + } + return &storeService{ + c: c, + name: name, + } +} + +func (c *storeService) Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) { + req := c.c.NewRequest(c.name, "Store.Read", in) + out := new(ReadResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *storeService) Write(ctx context.Context, in *WriteRequest, opts ...client.CallOption) (*WriteResponse, error) { + req := c.c.NewRequest(c.name, "Store.Write", in) + out := new(WriteResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *storeService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) { + req := c.c.NewRequest(c.name, "Store.Delete", in) + out := new(DeleteResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *storeService) Sync(ctx context.Context, in *SyncRequest, opts ...client.CallOption) (Store_SyncService, error) { + req := c.c.NewRequest(c.name, "Store.Sync", &SyncRequest{}) + stream, err := c.c.Stream(ctx, req, opts...) + if err != nil { + return nil, err + } + if err := stream.Send(in); err != nil { + return nil, err + } + return &storeServiceSync{stream}, nil +} + +type Store_SyncService interface { + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Recv() (*SyncResponse, error) +} + +type storeServiceSync struct { + stream client.Stream +} + +func (x *storeServiceSync) Close() error { + return x.stream.Close() +} + +func (x *storeServiceSync) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *storeServiceSync) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *storeServiceSync) Recv() (*SyncResponse, error) { + m := new(SyncResponse) + err := x.stream.Recv(m) + if err != nil { + return nil, err + } + return m, nil +} + +// Server API for Store service + +type StoreHandler interface { + Read(context.Context, *ReadRequest, *ReadResponse) error + Write(context.Context, *WriteRequest, *WriteResponse) error + Delete(context.Context, *DeleteRequest, *DeleteResponse) error + Sync(context.Context, *SyncRequest, Store_SyncStream) error +} + +func RegisterStoreHandler(s server.Server, hdlr StoreHandler, opts ...server.HandlerOption) error { + type store interface { + Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error + Write(ctx context.Context, in *WriteRequest, out *WriteResponse) error + Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error + Sync(ctx context.Context, stream server.Stream) error + } + type Store struct { + store + } + h := &storeHandler{hdlr} + return s.Handle(s.NewHandler(&Store{h}, opts...)) +} + +type storeHandler struct { + StoreHandler +} + +func (h *storeHandler) Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error { + return h.StoreHandler.Read(ctx, in, out) +} + +func (h *storeHandler) Write(ctx context.Context, in *WriteRequest, out *WriteResponse) error { + return h.StoreHandler.Write(ctx, in, out) +} + +func (h *storeHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error { + return h.StoreHandler.Delete(ctx, in, out) +} + +func (h *storeHandler) Sync(ctx context.Context, stream server.Stream) error { + m := new(SyncRequest) + if err := stream.Recv(m); err != nil { + return err + } + return h.StoreHandler.Sync(ctx, m, &storeSyncStream{stream}) +} + +type Store_SyncStream interface { + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Send(*SyncResponse) error +} + +type storeSyncStream struct { + stream server.Stream +} + +func (x *storeSyncStream) Close() error { + return x.stream.Close() +} + +func (x *storeSyncStream) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *storeSyncStream) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *storeSyncStream) Send(m *SyncResponse) error { + return x.stream.Send(m) +} diff --git a/store/service/proto/store.pb.go b/store/service/proto/store.pb.go new file mode 100644 index 00000000..ce166cb7 --- /dev/null +++ b/store/service/proto/store.pb.go @@ -0,0 +1,618 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: micro/go-micro/store/service/proto/store.proto + +package go_micro_store + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + 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.ProtoPackageIsVersion3 // please upgrade the proto package + +type Record struct { + // key of the record + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // value in the record + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + // timestamp in unix seconds + Expiry int64 `protobuf:"varint,3,opt,name=expiry,proto3" json:"expiry,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Record) Reset() { *m = Record{} } +func (m *Record) String() string { return proto.CompactTextString(m) } +func (*Record) ProtoMessage() {} +func (*Record) Descriptor() ([]byte, []int) { + return fileDescriptor_f84ccc98e143ed3e, []int{0} +} + +func (m *Record) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Record.Unmarshal(m, b) +} +func (m *Record) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Record.Marshal(b, m, deterministic) +} +func (m *Record) XXX_Merge(src proto.Message) { + xxx_messageInfo_Record.Merge(m, src) +} +func (m *Record) XXX_Size() int { + return xxx_messageInfo_Record.Size(m) +} +func (m *Record) XXX_DiscardUnknown() { + xxx_messageInfo_Record.DiscardUnknown(m) +} + +var xxx_messageInfo_Record proto.InternalMessageInfo + +func (m *Record) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *Record) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *Record) GetExpiry() int64 { + if m != nil { + return m.Expiry + } + return 0 +} + +type ReadRequest struct { + Keys []string `protobuf:"bytes,1,rep,name=keys,proto3" json:"keys,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ReadRequest) Reset() { *m = ReadRequest{} } +func (m *ReadRequest) String() string { return proto.CompactTextString(m) } +func (*ReadRequest) ProtoMessage() {} +func (*ReadRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f84ccc98e143ed3e, []int{1} +} + +func (m *ReadRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ReadRequest.Unmarshal(m, b) +} +func (m *ReadRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ReadRequest.Marshal(b, m, deterministic) +} +func (m *ReadRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ReadRequest.Merge(m, src) +} +func (m *ReadRequest) XXX_Size() int { + return xxx_messageInfo_ReadRequest.Size(m) +} +func (m *ReadRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ReadRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ReadRequest proto.InternalMessageInfo + +func (m *ReadRequest) GetKeys() []string { + if m != nil { + return m.Keys + } + return nil +} + +type ReadResponse struct { + Records []*Record `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ReadResponse) Reset() { *m = ReadResponse{} } +func (m *ReadResponse) String() string { return proto.CompactTextString(m) } +func (*ReadResponse) ProtoMessage() {} +func (*ReadResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f84ccc98e143ed3e, []int{2} +} + +func (m *ReadResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ReadResponse.Unmarshal(m, b) +} +func (m *ReadResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ReadResponse.Marshal(b, m, deterministic) +} +func (m *ReadResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ReadResponse.Merge(m, src) +} +func (m *ReadResponse) XXX_Size() int { + return xxx_messageInfo_ReadResponse.Size(m) +} +func (m *ReadResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ReadResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ReadResponse proto.InternalMessageInfo + +func (m *ReadResponse) GetRecords() []*Record { + if m != nil { + return m.Records + } + return nil +} + +type WriteRequest struct { + Records []*Record `protobuf:"bytes,2,rep,name=records,proto3" json:"records,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *WriteRequest) Reset() { *m = WriteRequest{} } +func (m *WriteRequest) String() string { return proto.CompactTextString(m) } +func (*WriteRequest) ProtoMessage() {} +func (*WriteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f84ccc98e143ed3e, []int{3} +} + +func (m *WriteRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_WriteRequest.Unmarshal(m, b) +} +func (m *WriteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_WriteRequest.Marshal(b, m, deterministic) +} +func (m *WriteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_WriteRequest.Merge(m, src) +} +func (m *WriteRequest) XXX_Size() int { + return xxx_messageInfo_WriteRequest.Size(m) +} +func (m *WriteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_WriteRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_WriteRequest proto.InternalMessageInfo + +func (m *WriteRequest) GetRecords() []*Record { + if m != nil { + return m.Records + } + return nil +} + +type WriteResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *WriteResponse) Reset() { *m = WriteResponse{} } +func (m *WriteResponse) String() string { return proto.CompactTextString(m) } +func (*WriteResponse) ProtoMessage() {} +func (*WriteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f84ccc98e143ed3e, []int{4} +} + +func (m *WriteResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_WriteResponse.Unmarshal(m, b) +} +func (m *WriteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_WriteResponse.Marshal(b, m, deterministic) +} +func (m *WriteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_WriteResponse.Merge(m, src) +} +func (m *WriteResponse) XXX_Size() int { + return xxx_messageInfo_WriteResponse.Size(m) +} +func (m *WriteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_WriteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_WriteResponse proto.InternalMessageInfo + +type DeleteRequest struct { + Keys []string `protobuf:"bytes,1,rep,name=keys,proto3" json:"keys,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } +func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteRequest) ProtoMessage() {} +func (*DeleteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f84ccc98e143ed3e, []int{5} +} + +func (m *DeleteRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteRequest.Unmarshal(m, b) +} +func (m *DeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteRequest.Marshal(b, m, deterministic) +} +func (m *DeleteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteRequest.Merge(m, src) +} +func (m *DeleteRequest) XXX_Size() int { + return xxx_messageInfo_DeleteRequest.Size(m) +} +func (m *DeleteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteRequest proto.InternalMessageInfo + +func (m *DeleteRequest) GetKeys() []string { + if m != nil { + return m.Keys + } + return nil +} + +type DeleteResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } +func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteResponse) ProtoMessage() {} +func (*DeleteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f84ccc98e143ed3e, []int{6} +} + +func (m *DeleteResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteResponse.Unmarshal(m, b) +} +func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteResponse.Marshal(b, m, deterministic) +} +func (m *DeleteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteResponse.Merge(m, src) +} +func (m *DeleteResponse) XXX_Size() int { + return xxx_messageInfo_DeleteResponse.Size(m) +} +func (m *DeleteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo + +type SyncRequest struct { + // optional key + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SyncRequest) Reset() { *m = SyncRequest{} } +func (m *SyncRequest) String() string { return proto.CompactTextString(m) } +func (*SyncRequest) ProtoMessage() {} +func (*SyncRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f84ccc98e143ed3e, []int{7} +} + +func (m *SyncRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SyncRequest.Unmarshal(m, b) +} +func (m *SyncRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SyncRequest.Marshal(b, m, deterministic) +} +func (m *SyncRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SyncRequest.Merge(m, src) +} +func (m *SyncRequest) XXX_Size() int { + return xxx_messageInfo_SyncRequest.Size(m) +} +func (m *SyncRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SyncRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SyncRequest proto.InternalMessageInfo + +func (m *SyncRequest) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +type SyncResponse struct { + Records []*Record `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SyncResponse) Reset() { *m = SyncResponse{} } +func (m *SyncResponse) String() string { return proto.CompactTextString(m) } +func (*SyncResponse) ProtoMessage() {} +func (*SyncResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f84ccc98e143ed3e, []int{8} +} + +func (m *SyncResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SyncResponse.Unmarshal(m, b) +} +func (m *SyncResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SyncResponse.Marshal(b, m, deterministic) +} +func (m *SyncResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SyncResponse.Merge(m, src) +} +func (m *SyncResponse) XXX_Size() int { + return xxx_messageInfo_SyncResponse.Size(m) +} +func (m *SyncResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SyncResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SyncResponse proto.InternalMessageInfo + +func (m *SyncResponse) GetRecords() []*Record { + if m != nil { + return m.Records + } + return nil +} + +func init() { + proto.RegisterType((*Record)(nil), "go.micro.store.Record") + proto.RegisterType((*ReadRequest)(nil), "go.micro.store.ReadRequest") + proto.RegisterType((*ReadResponse)(nil), "go.micro.store.ReadResponse") + proto.RegisterType((*WriteRequest)(nil), "go.micro.store.WriteRequest") + proto.RegisterType((*WriteResponse)(nil), "go.micro.store.WriteResponse") + proto.RegisterType((*DeleteRequest)(nil), "go.micro.store.DeleteRequest") + proto.RegisterType((*DeleteResponse)(nil), "go.micro.store.DeleteResponse") + proto.RegisterType((*SyncRequest)(nil), "go.micro.store.SyncRequest") + proto.RegisterType((*SyncResponse)(nil), "go.micro.store.SyncResponse") +} + +func init() { + proto.RegisterFile("micro/go-micro/store/service/proto/store.proto", fileDescriptor_f84ccc98e143ed3e) +} + +var fileDescriptor_f84ccc98e143ed3e = []byte{ + // 333 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0xcb, 0x6e, 0xf2, 0x30, + 0x10, 0x85, 0x09, 0x81, 0xfc, 0x62, 0xb8, 0xfc, 0x68, 0x54, 0xa1, 0x88, 0xde, 0xd2, 0x74, 0x93, + 0x4d, 0x03, 0xa2, 0x2f, 0x50, 0xa9, 0x17, 0xb5, 0x5b, 0xb3, 0xe8, 0x9a, 0x86, 0x11, 0x8a, 0xa0, + 0x98, 0x3a, 0x01, 0x35, 0x2f, 0xd4, 0xe7, 0xac, 0x6c, 0x27, 0x69, 0x90, 0x41, 0xaa, 0xba, 0x1b, + 0x7b, 0xce, 0x1c, 0x9f, 0xf9, 0x64, 0x08, 0xdf, 0xe3, 0x48, 0xf0, 0xd1, 0x82, 0xdf, 0xe8, 0x22, + 0x49, 0xb9, 0xa0, 0x51, 0x42, 0x62, 0x17, 0x47, 0x34, 0xda, 0x08, 0x9e, 0xe6, 0x77, 0xa1, 0xaa, + 0xb1, 0xb7, 0xe0, 0x7a, 0x24, 0x54, 0xb7, 0xfe, 0x33, 0x38, 0x8c, 0x22, 0x2e, 0xe6, 0xd8, 0x07, + 0x7b, 0x49, 0x99, 0x6b, 0x79, 0x56, 0xd0, 0x62, 0xb2, 0xc4, 0x13, 0x68, 0xee, 0x66, 0xab, 0x2d, + 0xb9, 0x75, 0xcf, 0x0a, 0x3a, 0x4c, 0x1f, 0x70, 0x00, 0x0e, 0x7d, 0x6e, 0x62, 0x91, 0xb9, 0xb6, + 0x67, 0x05, 0x36, 0xcb, 0x4f, 0xfe, 0x15, 0xb4, 0x19, 0xcd, 0xe6, 0x8c, 0x3e, 0xb6, 0x94, 0xa4, + 0x88, 0xd0, 0x58, 0x52, 0x96, 0xb8, 0x96, 0x67, 0x07, 0x2d, 0xa6, 0x6a, 0xff, 0x0e, 0x3a, 0x5a, + 0x92, 0x6c, 0xf8, 0x3a, 0x21, 0x1c, 0xc3, 0x3f, 0xa1, 0x1e, 0xd7, 0xb2, 0xf6, 0x64, 0x10, 0xee, + 0xc7, 0x0b, 0x75, 0x36, 0x56, 0xc8, 0xa4, 0xc3, 0xab, 0x88, 0x53, 0x2a, 0x5e, 0xa9, 0x38, 0xd4, + 0x7f, 0xe7, 0xf0, 0x1f, 0xba, 0xb9, 0x83, 0x0e, 0xe1, 0x5f, 0x43, 0xf7, 0x81, 0x56, 0xf4, 0xe3, + 0x79, 0x28, 0x79, 0x1f, 0x7a, 0x85, 0x28, 0x1f, 0xbb, 0x84, 0xf6, 0x34, 0x5b, 0x47, 0xc5, 0x90, + 0x41, 0x4f, 0x46, 0xd5, 0x82, 0xbf, 0x2e, 0x3b, 0xf9, 0xaa, 0x43, 0x73, 0x2a, 0x3b, 0x78, 0x0f, + 0x0d, 0x09, 0x0e, 0x4f, 0xcd, 0x91, 0x92, 0xf8, 0xf0, 0xec, 0x70, 0x33, 0xcf, 0x5b, 0xc3, 0x27, + 0x68, 0xaa, 0xcd, 0xd1, 0x10, 0x56, 0x91, 0x0e, 0xcf, 0x8f, 0x74, 0x4b, 0x9f, 0x17, 0x70, 0x34, + 0x0b, 0x34, 0xa4, 0x7b, 0x20, 0x87, 0x17, 0xc7, 0xda, 0xa5, 0xd5, 0x23, 0x34, 0x24, 0x23, 0x73, + 0xaf, 0x0a, 0x5a, 0x73, 0xaf, 0x2a, 0x56, 0xbf, 0x36, 0xb6, 0xde, 0x1c, 0xf5, 0xb7, 0x6f, 0xbf, + 0x03, 0x00, 0x00, 0xff, 0xff, 0x30, 0xc8, 0x99, 0x52, 0x0d, 0x03, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// StoreClient is the client API for Store service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type StoreClient interface { + Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error) + Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error) + Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) + Sync(ctx context.Context, in *SyncRequest, opts ...grpc.CallOption) (Store_SyncClient, error) +} + +type storeClient struct { + cc *grpc.ClientConn +} + +func NewStoreClient(cc *grpc.ClientConn) StoreClient { + return &storeClient{cc} +} + +func (c *storeClient) Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error) { + out := new(ReadResponse) + err := c.cc.Invoke(ctx, "/go.micro.store.Store/Read", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *storeClient) Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error) { + out := new(WriteResponse) + err := c.cc.Invoke(ctx, "/go.micro.store.Store/Write", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *storeClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) { + out := new(DeleteResponse) + err := c.cc.Invoke(ctx, "/go.micro.store.Store/Delete", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *storeClient) Sync(ctx context.Context, in *SyncRequest, opts ...grpc.CallOption) (Store_SyncClient, error) { + stream, err := c.cc.NewStream(ctx, &_Store_serviceDesc.Streams[0], "/go.micro.store.Store/Sync", opts...) + if err != nil { + return nil, err + } + x := &storeSyncClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Store_SyncClient interface { + Recv() (*SyncResponse, error) + grpc.ClientStream +} + +type storeSyncClient struct { + grpc.ClientStream +} + +func (x *storeSyncClient) Recv() (*SyncResponse, error) { + m := new(SyncResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// StoreServer is the server API for Store service. +type StoreServer interface { + Read(context.Context, *ReadRequest) (*ReadResponse, error) + Write(context.Context, *WriteRequest) (*WriteResponse, error) + Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) + Sync(*SyncRequest, Store_SyncServer) error +} + +func RegisterStoreServer(s *grpc.Server, srv StoreServer) { + s.RegisterService(&_Store_serviceDesc, srv) +} + +func _Store_Read_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReadRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StoreServer).Read(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.store.Store/Read", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StoreServer).Read(ctx, req.(*ReadRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Store_Write_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(WriteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StoreServer).Write(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.store.Store/Write", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StoreServer).Write(ctx, req.(*WriteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Store_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StoreServer).Delete(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.store.Store/Delete", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StoreServer).Delete(ctx, req.(*DeleteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Store_Sync_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SyncRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(StoreServer).Sync(m, &storeSyncServer{stream}) +} + +type Store_SyncServer interface { + Send(*SyncResponse) error + grpc.ServerStream +} + +type storeSyncServer struct { + grpc.ServerStream +} + +func (x *storeSyncServer) Send(m *SyncResponse) error { + return x.ServerStream.SendMsg(m) +} + +var _Store_serviceDesc = grpc.ServiceDesc{ + ServiceName: "go.micro.store.Store", + HandlerType: (*StoreServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Read", + Handler: _Store_Read_Handler, + }, + { + MethodName: "Write", + Handler: _Store_Write_Handler, + }, + { + MethodName: "Delete", + Handler: _Store_Delete_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Sync", + Handler: _Store_Sync_Handler, + ServerStreams: true, + }, + }, + Metadata: "micro/go-micro/store/service/proto/store.proto", +} diff --git a/store/service/proto/store.proto b/store/service/proto/store.proto new file mode 100644 index 00000000..a5abe4aa --- /dev/null +++ b/store/service/proto/store.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; + +package go.micro.store; + +service Store { + rpc Read(ReadRequest) returns (ReadResponse) {}; + rpc Write(WriteRequest) returns (WriteResponse) {}; + rpc Delete(DeleteRequest) returns (DeleteResponse) {}; + rpc Sync(SyncRequest) returns (stream SyncResponse) {}; +} + +message Record { + // key of the record + string key = 1; + // value in the record + bytes value = 2; + // timestamp in unix seconds + int64 expiry = 3; +} + +message ReadRequest { + repeated string keys = 1; +} + +message ReadResponse { + repeated Record records = 1; +} + +message WriteRequest { + repeated Record records = 2; +} + +message WriteResponse {} + +message DeleteRequest { + repeated string keys = 1; +} + +message DeleteResponse {} + +message SyncRequest { + // optional key + string key = 1; +} + +message SyncResponse { + repeated Record records = 1; +} diff --git a/store/store.go b/store/store.go index c6442947..e3d8efac 100644 --- a/store/store.go +++ b/store/store.go @@ -19,11 +19,11 @@ type Store interface { // Sync all the known records Sync() ([]*Record, error) // Read a record with key - Read(key string) (*Record, error) + Read(keys ...string) ([]*Record, error) // Write a record - Write(r *Record) error + Write(recs ...*Record) error // Delete a record with key - Delete(key string) error + Delete(keys ...string) error } // Record represents a data record diff --git a/sync/map.go b/sync/map.go index a87bd988..a9611ff0 100644 --- a/sync/map.go +++ b/sync/map.go @@ -39,8 +39,12 @@ func (m *syncMap) Read(key, val interface{}) error { return err } + if len(kval) == 0 { + return store.ErrNotFound + } + // decode value - return json.Unmarshal(kval.Value, val) + return json.Unmarshal(kval[0].Value, val) } func (m *syncMap) Write(key, val interface{}) error { From cfa2b668e2b2d4ca3f9f2418f4456c5f5c9e3d79 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 11 Oct 2019 14:44:34 +0100 Subject: [PATCH 066/344] go fmt --- store/etcd/etcd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/etcd/etcd.go b/store/etcd/etcd.go index d0094fb4..bd3697c7 100644 --- a/store/etcd/etcd.go +++ b/store/etcd/etcd.go @@ -5,8 +5,8 @@ import ( "context" "log" - "github.com/coreos/etcd/mvcc/mvccpb" client "github.com/coreos/etcd/clientv3" + "github.com/coreos/etcd/mvcc/mvccpb" "github.com/micro/go-micro/config/options" "github.com/micro/go-micro/store" ) From 76eee089e3d4a430d016ae9a372272fd970af58c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 11 Oct 2019 14:44:42 +0100 Subject: [PATCH 067/344] Add store service client --- store/service/service.go | 119 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 store/service/service.go diff --git a/store/service/service.go b/store/service/service.go new file mode 100644 index 00000000..d7cc3805 --- /dev/null +++ b/store/service/service.go @@ -0,0 +1,119 @@ +// Package service implements the store service interface +package service + +import ( + "context" + "io" + "time" + + "github.com/micro/go-micro/client" + "github.com/micro/go-micro/config/options" + "github.com/micro/go-micro/store" + pb "github.com/micro/go-micro/store/service/proto" +) + +type serviceStore struct { + options.Options + + // Addresses of the nodes + Nodes []string + + // store service client + Client pb.StoreService +} + +// Sync all the known records +func (s *serviceStore) Sync() ([]*store.Record, error) { + stream, err := s.Client.Sync(context.Background(), &pb.SyncRequest{}, client.WithAddress(s.Nodes...)) + if err != nil { + return nil, err + } + defer stream.Close() + + var records []*store.Record + + for { + rsp, err := stream.Recv() + if err == io.EOF { + break + } + if err != nil { + return records, err + } + for _, record := range rsp.Records { + records = append(records, &store.Record{ + Key: record.Key, + Value: record.Value, + Expiry: time.Duration(record.Expiry) * time.Second, + }) + } + } + + return records, nil +} + +// Read a record with key +func (s *serviceStore) Read(keys ...string) ([]*store.Record, error) { + rsp, err := s.Client.Read(context.Background(), &pb.ReadRequest{ + Keys: keys, + }, client.WithAddress(s.Nodes...)) + if err != nil { + return nil, err + } + var records []*store.Record + for _, val := range rsp.Records { + records = append(records, &store.Record{ + Key: val.Key, + Value: val.Value, + Expiry: time.Duration(val.Expiry) * time.Second, + }) + } + return records, nil +} + +// Write a record +func (s *serviceStore) Write(recs ...*store.Record) error { + var records []*pb.Record + + for _, record := range recs { + records = append(records, &pb.Record{ + Key: record.Key, + Value: record.Value, + Expiry: int64(record.Expiry.Seconds()), + }) + } + + _, err := s.Client.Write(context.Background(), &pb.WriteRequest{ + Records: records, + }, client.WithAddress(s.Nodes...)) + + return err +} + +// Delete a record with key +func (s *serviceStore) Delete(keys ...string) error { + _, err := s.Client.Delete(context.Background(), &pb.DeleteRequest{ + Keys: keys, + }, client.WithAddress(s.Nodes...)) + return err +} + +// NewStore returns a new store service implementation +func NewStore(opts ...options.Option) store.Store { + options := options.NewOptions(opts...) + + var nodes []string + + n, ok := options.Values().Get("store.nodes") + if ok { + nodes = n.([]string) + } + + service := &serviceStore{ + Options: options, + Nodes: nodes, + Client: pb.NewStoreService("go.micro.store", client.DefaultClient), + } + + return service +} From 9bd96d4cc12e92ed57878e2c121ca2cb69ef242f Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Fri, 11 Oct 2019 16:24:25 +0100 Subject: [PATCH 068/344] Update go.mod for ACME changes --- go.mod | 21 +++- go.sum | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 327 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index f5889f4e..f1e5b9c1 100644 --- a/go.mod +++ b/go.mod @@ -6,43 +6,58 @@ require ( github.com/BurntSushi/toml v0.3.1 github.com/beevik/ntp v0.2.0 github.com/bitly/go-simplejson v0.5.0 + github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/bwmarrin/discordgo v0.19.0 + github.com/coreos/bbolt v1.3.3 // indirect github.com/coreos/etcd v3.3.15+incompatible + github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c github.com/fsnotify/fsnotify v1.4.7 github.com/fsouza/go-dockerclient v1.4.4 github.com/ghodss/yaml v1.0.0 + github.com/go-acme/lego/v3 v3.1.0 github.com/go-log/log v0.1.0 github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect + github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect + github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc // indirect github.com/golang/protobuf v1.3.2 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/websocket v1.4.1 + github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/hashicorp/consul/api v1.2.0 github.com/hashicorp/hcl v1.0.0 - github.com/hashicorp/memberlist v0.1.5 + github.com/hashicorp/memberlist v0.1.5 // indirect github.com/imdario/mergo v0.3.7 + github.com/jonboulle/clockwork v0.1.0 // indirect github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 github.com/leodido/go-urn v1.1.0 // indirect github.com/lucas-clemente/quic-go v0.12.0 + github.com/mholt/certmagic v0.7.3 github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 github.com/mitchellh/hashstructure v1.0.0 + github.com/nats-io/nats-server/v2 v2.1.0 // indirect github.com/nats-io/nats.go v1.8.1 github.com/nlopes/slack v0.6.0 github.com/pkg/errors v0.8.1 + github.com/soheilhy/cmux v0.1.4 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect - go.uber.org/atomic v1.4.0 // indirect + github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect + go.etcd.io/bbolt v1.3.3 // indirect go.uber.org/multierr v1.2.0 // indirect - go.uber.org/zap v1.10.0 // indirect golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 google.golang.org/grpc v1.24.0 + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v9 v9.30.0 gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/telegram-bot-api.v4 v4.6.4 + sigs.k8s.io/yaml v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 648484b8..f7c8d6d8 100644 --- a/go.sum +++ b/go.sum @@ -1,40 +1,96 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= +github.com/Azure/azure-sdk-for-go v32.4.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/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= +github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw= +github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= +github.com/Azure/go-autorest/autorest/adal v0.2.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= +github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM= +github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= +github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= +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/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +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-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= +github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +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/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY= github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= +github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cloudflare-go v0.10.0 h1:wJPNqfrQO0w3fCiQcf/2T4lR2y6Q2fAwRszllljgb8I= +github.com/cloudflare/cloudflare-go v0.10.0/go.mod h1:fOESqHl/jzAmCtEyjceLkw3v0rVjzl8V9iehxZPynXY= +github.com/cloudflare/cloudflare-go v0.10.2 h1:VBodKICVPnwmDxstcW3biKcDSpFIfS/RELUXsZSBYK4= +github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= 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/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.15+incompatible h1:+9RjdC18gMxNQVvSiXvObLu29mOFmkgdsB4cRTlV+EE= github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/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/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= +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/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/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b h1:+Ga+YpCDpcY1fln6GI0fiiirpqHGcob5/Vk3oKNuGdU= @@ -43,9 +99,15 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +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/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c h1:pBgVXWDXju1m8W4lnEeIqTHPOzhTUO81a7yknM/xQR4= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY= @@ -55,40 +117,81 @@ github.com/fsouza/go-dockerclient v1.4.4 h1:Sd5nD4wdAgiPxvrbYUzT2ZZNmPk3z+GGnZ+f github.com/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA= 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.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-acme/lego/v3 v3.0.2 h1:cnS+URiPzkt2pd7I2WlZtFyt2ihQ762nouBybY4djjw= +github.com/go-acme/lego/v3 v3.0.2/go.mod h1:sMoLjf8BUo4Jexg+6Xw5KeFx98KVZ7Nfczh9tzLyhJU= +github.com/go-acme/lego/v3 v3.1.0 h1:yanYFoYW8azFkCvJfIk7edWWfjkYkhDxe45ZsxoW4Xk= +github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= +github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 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-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +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/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-20191002201903-404acd9df4cc h1:55rEp52jU6bkyslZ1+C/7NGfpQsEc6pxGLAGDOctqbw= +github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 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.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/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/consul v1.6.1 h1:ISPgwOO8/vPYrCXQNyx63eJAYjPGRnmFsXK7aj2XICs= +github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= +github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= +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.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= +github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/consul/api v1.2.0 h1:oPsuzLp2uk7I7rojPKuncWbZ+m5TMoD4Ivs+2Rkeh4Y= github.com/hashicorp/consul/api v1.2.0/go.mod h1:1SIkFYi2ZTXUE5Kgt179+4hH33djo11+0Eo2XgTAtkw= +github.com/hashicorp/consul/sdk v0.2.0 h1:GWFYFmry/k4b1hEoy7kSkmU8e30GAyI4VZHk0fRxeL4= github.com/hashicorp/consul/sdk v0.2.0/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= @@ -106,10 +209,14 @@ github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sL 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 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= 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/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 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/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -119,7 +226,9 @@ github.com/hashicorp/memberlist v0.1.5 h1:AYBsgJOW9gab/toO5tEB8lWetVgDKZycqkebJ8 github.com/hashicorp/memberlist v0.1.5/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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= @@ -127,22 +236,44 @@ github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +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/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 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/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= 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= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +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/labbsr0x/bindman-dns-webhook v1.0.0/go.mod h1:pn4jcNjxSywRWDPDyGkFzgSnwty18OFdiUFc6S6fpgc= +github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= +github.com/labbsr0x/goh v0.0.0-20190417202808-8b16b4848295/go.mod h1:RBxeaayaaMmp7GxwHiKANjkg9e+rxjOm4mB5vD5rt/I= +github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= +github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= +github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= github.com/lucas-clemente/quic-go v0.12.0 h1:TRbvZ6F++sofeGbh+Z2IIyIOhl8KyGnYuA06g2yrHdI= github.com/lucas-clemente/quic-go v0.12.0/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= @@ -150,6 +281,13 @@ github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9s github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +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/certmagic v0.7.3 h1:1QOfAmk5uyWcfXJFQqFZZiEsJbPMBQ1vw/ttpVOUXQU= +github.com/mholt/certmagic v0.7.3/go.mod h1:hqHzDsY32TwZpj/KswVylheSISjquF/eOVOaJTYV15w= github.com/micro/cli v0.2.0 h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA= github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= @@ -157,11 +295,15 @@ github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9A 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.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= +github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +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-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= 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= @@ -171,18 +313,37 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= +github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats-server/v2 v2.1.0 h1:Yi0+ZhRPtPAGeIxFn5erIeJIV9wXA+JznfSxK621Fbk= +github.com/nats-io/nats-server/v2 v2.1.0/go.mod h1:r5y0WgCag0dTj/qiHkHrXAcKQ/f5GMOZaEGdoxxnJ4I= github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= +github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA= github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk= +github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw= +github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ= +github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 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.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= @@ -190,20 +351,60 @@ 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/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= +github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= +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/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +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.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ= +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/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -211,87 +412,194 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ 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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= +github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= +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/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= +github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= +github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +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.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +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/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4= go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/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/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc h1:KyTYo8xkh/2WdbFLUyQwBS0Jfn3qfZ9QmuPbok2oENE= golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc/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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-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-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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/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-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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/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/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq/5B590r6RlnL/G8Sz7w= +golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/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-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-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= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +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/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw= +gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +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/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/telegram-bot-api.v4 v4.6.4 h1:hpHWhzn4jTCsAJZZ2loNKfy2QWyPDRJVl3aTFXeMW8g= gopkg.in/telegram-bot-api.v4 v4.6.4/go.mod h1:5DpGO5dbumb40px+dXcwCpcjmeHNYLpk0bp3XRNvWDM= +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/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 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= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/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-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From 723c17fdd74ee63455e40df46edd11eb34f98663 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Fri, 11 Oct 2019 16:25:15 +0100 Subject: [PATCH 069/344] Implementation of certmagic as an ACME provider --- api/server/acme/acme.go | 69 +++++++++++++++++++++ api/server/acme/autocert/autocert.go | 3 +- api/server/acme/certmagic/certmagic.go | 42 +++++++++++++ api/server/acme/certmagic/certmagic_test.go | 37 +++++++++++ 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 api/server/acme/certmagic/certmagic.go create mode 100644 api/server/acme/certmagic/certmagic_test.go diff --git a/api/server/acme/acme.go b/api/server/acme/acme.go index 0bf3698d..9d61816a 100644 --- a/api/server/acme/acme.go +++ b/api/server/acme/acme.go @@ -4,9 +4,13 @@ package acme import ( "errors" "net" + + "github.com/go-acme/lego/v3/challenge" ) var ( + // ErrProviderNotImplemented can be returned when attempting to + // instantiate an unimplemented provider ErrProviderNotImplemented = errors.New("Provider not implemented") ) @@ -14,3 +18,68 @@ var ( type Provider interface { NewListener(...string) (net.Listener, error) } + +// The Let's Encrypt ACME endpoints +const ( + LetsEncryptStagingCA = "https://acme-staging-v02.api.letsencrypt.org/directory" + LetsEncryptProductionCA = "https://acme-v02.api.letsencrypt.org/directory" +) + +// Option (or Options) are passed to New() to configure providers +type Option func(o *Options) + +// Options represents various options you can present to ACME providers +type Options struct { + // AcceptTLS must be set to true to indicate that you have read your + // provider's terms of service. + AcceptToS bool + // CA is the CA to use + CA string + // ChallengeProvider is a go-acme/lego challenge provider. Set this if you + // want to use DNS Challenges. Otherwise, tls-alpn-01 will be used + ChallengeProvider challenge.Provider + // Issue certificates for domains on demand. Otherwise, certs will be + // retrieved / issued on start-up. + OnDemand bool + // TODO + Cache interface{} +} + +// AcceptTLS indicates whether you accept your CA's terms of service +func AcceptTLS(b bool) Option { + return func(o *Options) { + o.AcceptToS = b + } +} + +// CA sets the CA of an acme.Options +func CA(CA string) Option { + return func(o *Options) { + o.CA = CA + } +} + +// ChallengeProvider sets the Challenge provider of an acme.Options +// if set, it enables the DNS challenge, otherwise tls-alpn-01 will be used. +func ChallengeProvider(p challenge.Provider) Option { + return func(o *Options) { + o.ChallengeProvider = p + } +} + +// OnDemand enables on-demand certificate issuance. Not recommended for use +// with the DNS challenge, as the first connection may be very slow. +func OnDemand(b bool) Option { + return func(o *Options) { + o.OnDemand = b + } +} + +// Default uses the Let's Encrypt Production CA, with DNS Challenge disabled. +func Default() []Option { + return []Option{ + AcceptTLS(true), + CA(LetsEncryptProductionCA), + OnDemand(true), + } +} diff --git a/api/server/acme/autocert/autocert.go b/api/server/acme/autocert/autocert.go index 9a760baf..ad5bf0bd 100644 --- a/api/server/acme/autocert/autocert.go +++ b/api/server/acme/autocert/autocert.go @@ -1,4 +1,5 @@ -// Package autocert is the ACME interpreter from golang.org/x/crypto/acme/autocert +// Package autocert is the ACME provider from golang.org/x/crypto/acme/autocert +// This provider does not take any config. package autocert import ( diff --git a/api/server/acme/certmagic/certmagic.go b/api/server/acme/certmagic/certmagic.go new file mode 100644 index 00000000..68e36f64 --- /dev/null +++ b/api/server/acme/certmagic/certmagic.go @@ -0,0 +1,42 @@ +// Package certmagic is the ACME provider from github.com/mholt/certmagic +package certmagic + +import ( + "net" + + "github.com/mholt/certmagic" + + "github.com/micro/go-micro/api/server/acme" +) + +type certmagicProvider struct { + opts *acme.Options +} + +func (c *certmagicProvider) NewListener(ACMEHosts ...string) (net.Listener, error) { + if c.opts.ChallengeProvider != nil { + // Enabling DNS Challenge disables the other challenges + certmagic.Default.DNSProvider = c.opts.ChallengeProvider + } + if c.opts.OnDemand { + certmagic.Default.OnDemand = new(certmagic.OnDemandConfig) + } + return certmagic.Listen(ACMEHosts) +} + +// New returns a certmagic provider +func New(options ...acme.Option) acme.Provider { + o := &acme.Options{} + if len(options) == 0 { + for _, op := range acme.Default() { + op(o) + } + } else { + for _, op := range options { + op(o) + } + } + return &certmagicProvider{ + opts: o, + } +} diff --git a/api/server/acme/certmagic/certmagic_test.go b/api/server/acme/certmagic/certmagic_test.go new file mode 100644 index 00000000..5aeceb0b --- /dev/null +++ b/api/server/acme/certmagic/certmagic_test.go @@ -0,0 +1,37 @@ +package certmagic + +import ( + "testing" + + "github.com/go-acme/lego/v3/providers/dns/cloudflare" + "github.com/micro/go-micro/api/server/acme" +) + +func TestCertMagic(t *testing.T) { + l, err := New().NewListener() + if err != nil { + t.Error(err.Error()) + } + l.Close() + + c := cloudflare.NewDefaultConfig() + c.AuthEmail = "" + c.AuthKey = "" + c.AuthToken = "test" + c.ZoneToken = "test" + + p, err := cloudflare.NewDNSProviderConfig(c) + if err != nil { + t.Error(err.Error()) + } + + l, err = New(acme.AcceptTLS(true), + acme.CA(acme.LetsEncryptStagingCA), + acme.ChallengeProvider(p), + ).NewListener() + + if err != nil { + t.Error(err.Error()) + } + l.Close() +} From 591e87448bc88c25af1c262192c31deb58f12795 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Fri, 11 Oct 2019 16:47:05 +0100 Subject: [PATCH 070/344] Travis doesn't let us bind :443 --- api/server/acme/autocert/autocert_test.go | 7 +++-- api/server/acme/certmagic/certmagic_test.go | 32 +++++++++++---------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/api/server/acme/autocert/autocert_test.go b/api/server/acme/autocert/autocert_test.go index 4b8ab27c..570769df 100644 --- a/api/server/acme/autocert/autocert_test.go +++ b/api/server/acme/autocert/autocert_test.go @@ -9,7 +9,8 @@ func TestAutocert(t *testing.T) { if _, ok := l.(*autocertProvider); !ok { t.Error("New() didn't return an autocertProvider") } - if _, err := l.NewListener(); err != nil { - t.Error(err.Error()) - } + // TODO: Travis CI doesn't let us bind :443 + // if _, err := l.NewListener(); err != nil { + // t.Error(err.Error()) + // } } diff --git a/api/server/acme/certmagic/certmagic_test.go b/api/server/acme/certmagic/certmagic_test.go index 5aeceb0b..dc727101 100644 --- a/api/server/acme/certmagic/certmagic_test.go +++ b/api/server/acme/certmagic/certmagic_test.go @@ -4,15 +4,16 @@ import ( "testing" "github.com/go-acme/lego/v3/providers/dns/cloudflare" - "github.com/micro/go-micro/api/server/acme" + // "github.com/micro/go-micro/api/server/acme" ) func TestCertMagic(t *testing.T) { - l, err := New().NewListener() - if err != nil { - t.Error(err.Error()) - } - l.Close() + // TODO: Travis doesn't let us bind :443 + // l, err := New().NewListener() + // if err != nil { + // t.Error(err.Error()) + // } + // l.Close() c := cloudflare.NewDefaultConfig() c.AuthEmail = "" @@ -20,18 +21,19 @@ func TestCertMagic(t *testing.T) { c.AuthToken = "test" c.ZoneToken = "test" - p, err := cloudflare.NewDNSProviderConfig(c) + _, err := cloudflare.NewDNSProviderConfig(c) if err != nil { t.Error(err.Error()) } - l, err = New(acme.AcceptTLS(true), - acme.CA(acme.LetsEncryptStagingCA), - acme.ChallengeProvider(p), - ).NewListener() + // TODO: Travis doesn't let us bind :443 + // l, err = New(acme.AcceptTLS(true), + // acme.CA(acme.LetsEncryptStagingCA), + // acme.ChallengeProvider(p), + // ).NewListener() - if err != nil { - t.Error(err.Error()) - } - l.Close() + // if err != nil { + // t.Error(err.Error()) + // } + // l.Close() } From dd7677e6cca1f48e1a41bd7ce3f5edf3f4a8d9dc Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 11 Oct 2019 16:52:57 +0100 Subject: [PATCH 071/344] Add nil check for acme provider --- api/server/http/http.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/server/http/http.go b/api/server/http/http.go index 91d16339..3ff93b1a 100644 --- a/api/server/http/http.go +++ b/api/server/http/http.go @@ -52,7 +52,7 @@ func (s *httpServer) Start() error { var l net.Listener var err error - if s.opts.EnableACME { + if s.opts.EnableACME && s.opts.ACMEProvider != nil { // should we check the address to make sure its using :443? l, err = s.opts.ACMEProvider.NewListener(s.opts.ACMEHosts...) } else if s.opts.EnableTLS && s.opts.TLSConfig != nil { From db843c8d87fd64ad211d4a64d8ac81e0ba726fad Mon Sep 17 00:00:00 2001 From: Peter Theophanous Date: Fri, 11 Oct 2019 17:15:20 +0100 Subject: [PATCH 072/344] reset orig --- go.mod | 9 +-- go.sum | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 181 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index bbc95291..f1e5b9c1 100644 --- a/go.mod +++ b/go.mod @@ -13,11 +13,11 @@ require ( github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect - github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c github.com/fsnotify/fsnotify v1.4.7 github.com/fsouza/go-dockerclient v1.4.4 github.com/ghodss/yaml v1.0.0 + github.com/go-acme/lego/v3 v3.1.0 github.com/go-log/log v0.1.0 github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect @@ -29,7 +29,6 @@ require ( github.com/gorilla/websocket v1.4.1 github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.11.3 // indirect github.com/hashicorp/consul/api v1.2.0 github.com/hashicorp/hcl v1.0.0 github.com/hashicorp/memberlist v0.1.5 // indirect @@ -38,7 +37,8 @@ require ( github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 github.com/leodido/go-urn v1.1.0 // indirect - github.com/lucas-clemente/quic-go v0.12.1 + github.com/lucas-clemente/quic-go v0.12.0 + github.com/mholt/certmagic v0.7.3 github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 github.com/mitchellh/hashstructure v1.0.0 @@ -46,8 +46,6 @@ require ( github.com/nats-io/nats.go v1.8.1 github.com/nlopes/slack v0.6.0 github.com/pkg/errors v0.8.1 - github.com/prometheus/client_golang v1.1.0 // indirect - github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 // indirect github.com/soheilhy/cmux v0.1.4 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect @@ -56,7 +54,6 @@ require ( go.uber.org/multierr v1.2.0 // indirect golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 - golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 // indirect google.golang.org/grpc v1.24.0 gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v9 v9.30.0 diff --git a/go.sum b/go.sum index d80851cf..f7c8d6d8 100644 --- a/go.sum +++ b/go.sum @@ -1,24 +1,49 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= +github.com/Azure/azure-sdk-for-go v32.4.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/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= +github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw= +github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= +github.com/Azure/go-autorest/autorest/adal v0.2.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= +github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM= +github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= +github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= +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/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= 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-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= +github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -32,9 +57,16 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4Yn github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY= github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= +github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cloudflare-go v0.10.0 h1:wJPNqfrQO0w3fCiQcf/2T4lR2y6Q2fAwRszllljgb8I= +github.com/cloudflare/cloudflare-go v0.10.0/go.mod h1:fOESqHl/jzAmCtEyjceLkw3v0rVjzl8V9iehxZPynXY= +github.com/cloudflare/cloudflare-go v0.10.2 h1:VBodKICVPnwmDxstcW3biKcDSpFIfS/RELUXsZSBYK4= +github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= 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/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= @@ -47,12 +79,18 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/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/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= 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/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/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b h1:+Ga+YpCDpcY1fln6GI0fiiirpqHGcob5/Vk3oKNuGdU= @@ -61,9 +99,14 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +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/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c h1:pBgVXWDXju1m8W4lnEeIqTHPOzhTUO81a7yknM/xQR4= @@ -76,6 +119,13 @@ 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.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-acme/lego/v3 v3.0.2 h1:cnS+URiPzkt2pd7I2WlZtFyt2ihQ762nouBybY4djjw= +github.com/go-acme/lego/v3 v3.0.2/go.mod h1:sMoLjf8BUo4Jexg+6Xw5KeFx98KVZ7Nfczh9tzLyhJU= +github.com/go-acme/lego/v3 v3.1.0 h1:yanYFoYW8azFkCvJfIk7edWWfjkYkhDxe45ZsxoW4Xk= +github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= +github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-log/log v0.1.0 h1:wudGTNsiGzrD5ZjgIkVZ517ugi2XRe9Q/xRCzwEO4/U= github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N2M= @@ -88,9 +138,12 @@ github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEK github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 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/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-20191002201903-404acd9df4cc h1:55rEp52jU6bkyslZ1+C/7NGfpQsEc6pxGLAGDOctqbw= @@ -103,17 +156,27 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 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.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/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -123,8 +186,9 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdR github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= 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.11.3 h1:h8+NsYENhxNTuq+dobk3+ODoJtwY4Fu0WQXsxJfL8aM= -github.com/grpc-ecosystem/grpc-gateway v1.11.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/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/consul/api v1.2.0 h1:oPsuzLp2uk7I7rojPKuncWbZ+m5TMoD4Ivs+2Rkeh4Y= github.com/hashicorp/consul/api v1.2.0/go.mod h1:1SIkFYi2ZTXUE5Kgt179+4hH33djo11+0Eo2XgTAtkw= github.com/hashicorp/consul/sdk v0.2.0 h1:GWFYFmry/k4b1hEoy7kSkmU8e30GAyI4VZHk0fRxeL4= @@ -150,6 +214,9 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b 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/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 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/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -161,6 +228,7 @@ github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= @@ -168,20 +236,29 @@ github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +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/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 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/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= 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= @@ -189,17 +266,28 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= 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/labbsr0x/bindman-dns-webhook v1.0.0/go.mod h1:pn4jcNjxSywRWDPDyGkFzgSnwty18OFdiUFc6S6fpgc= +github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= +github.com/labbsr0x/goh v0.0.0-20190417202808-8b16b4848295/go.mod h1:RBxeaayaaMmp7GxwHiKANjkg9e+rxjOm4mB5vD5rt/I= +github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= -github.com/lucas-clemente/quic-go v0.12.1 h1:BPITli+6KnKogtTxBk2aS4okr5dUHz2LtIDAP1b8UL4= -github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= +github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= +github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= +github.com/lucas-clemente/quic-go v0.12.0 h1:TRbvZ6F++sofeGbh+Z2IIyIOhl8KyGnYuA06g2yrHdI= +github.com/lucas-clemente/quic-go v0.12.0/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI= github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= 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/certmagic v0.7.3 h1:1QOfAmk5uyWcfXJFQqFZZiEsJbPMBQ1vw/ttpVOUXQU= +github.com/mholt/certmagic v0.7.3/go.mod h1:hqHzDsY32TwZpj/KswVylheSISjquF/eOVOaJTYV15w= github.com/micro/cli v0.2.0 h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA= github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= @@ -207,12 +295,15 @@ github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9A 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.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= +github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 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-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= 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= @@ -229,6 +320,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats-server/v2 v2.1.0 h1:Yi0+ZhRPtPAGeIxFn5erIeJIV9wXA+JznfSxK621Fbk= @@ -241,8 +333,13 @@ github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA= github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk= +github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw= +github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ= +github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 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= @@ -255,9 +352,13 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM 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.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= +github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= 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/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +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= @@ -265,31 +366,43 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +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/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ= +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/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= @@ -298,42 +411,62 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= +github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= 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/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= +github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= +github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= 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.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +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/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4= go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/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/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc h1:KyTYo8xkh/2WdbFLUyQwBS0Jfn3qfZ9QmuPbok2oENE= golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc/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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/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= @@ -341,22 +474,28 @@ golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73r 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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -364,10 +503,13 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/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-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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -377,25 +519,44 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/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/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq/5B590r6RlnL/G8Sz7w= golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/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-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-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= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +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/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= @@ -409,7 +570,14 @@ gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXa gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw= +gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +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/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= @@ -428,7 +596,10 @@ 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= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/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-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From 62aaa727151dae2b82aee1b8e201ecdf4a6d85fe Mon Sep 17 00:00:00 2001 From: Peter Theophanous Date: Fri, 11 Oct 2019 18:16:56 +0100 Subject: [PATCH 073/344] fix: bumped quic-go version to v0.12.1 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index f1e5b9c1..4d2aa0f8 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 github.com/leodido/go-urn v1.1.0 // indirect - github.com/lucas-clemente/quic-go v0.12.0 + github.com/lucas-clemente/quic-go v0.12.1 github.com/mholt/certmagic v0.7.3 github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 diff --git a/go.sum b/go.sum index f7c8d6d8..89f68358 100644 --- a/go.sum +++ b/go.sum @@ -276,6 +276,8 @@ github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8 github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= github.com/lucas-clemente/quic-go v0.12.0 h1:TRbvZ6F++sofeGbh+Z2IIyIOhl8KyGnYuA06g2yrHdI= github.com/lucas-clemente/quic-go v0.12.0/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= +github.com/lucas-clemente/quic-go v0.12.1 h1:BPITli+6KnKogtTxBk2aS4okr5dUHz2LtIDAP1b8UL4= +github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI= github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= From 18ea19a12209a19d841c8983e422f7d6c6785b42 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 12 Oct 2019 12:04:55 +0100 Subject: [PATCH 074/344] Regenerate go.mod --- go.mod | 27 +++---------- go.sum | 126 ++++++--------------------------------------------------- 2 files changed, 19 insertions(+), 134 deletions(-) diff --git a/go.mod b/go.mod index 4d2aa0f8..c8d22e00 100644 --- a/go.mod +++ b/go.mod @@ -6,11 +6,8 @@ require ( github.com/BurntSushi/toml v0.3.1 github.com/beevik/ntp v0.2.0 github.com/bitly/go-simplejson v0.5.0 - github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/bwmarrin/discordgo v0.19.0 - github.com/coreos/bbolt v1.3.3 // indirect - github.com/coreos/etcd v3.3.15+incompatible - github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/etcd v3.3.17+incompatible github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c @@ -21,43 +18,31 @@ require ( github.com/go-log/log v0.1.0 github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect - github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect - github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc // indirect github.com/golang/protobuf v1.3.2 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/websocket v1.4.1 - github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/hashicorp/consul/api v1.2.0 github.com/hashicorp/hcl v1.0.0 - github.com/hashicorp/memberlist v0.1.5 // indirect - github.com/imdario/mergo v0.3.7 - github.com/jonboulle/clockwork v0.1.0 // indirect + github.com/imdario/mergo v0.3.8 github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 github.com/leodido/go-urn v1.1.0 // indirect github.com/lucas-clemente/quic-go v0.12.1 - github.com/mholt/certmagic v0.7.3 + github.com/mholt/certmagic v0.7.5 github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 github.com/mitchellh/hashstructure v1.0.0 - github.com/nats-io/nats-server/v2 v2.1.0 // indirect github.com/nats-io/nats.go v1.8.1 github.com/nlopes/slack v0.6.0 github.com/pkg/errors v0.8.1 - github.com/soheilhy/cmux v0.1.4 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect - github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect - github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect - go.etcd.io/bbolt v1.3.3 // indirect go.uber.org/multierr v1.2.0 // indirect - golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc - golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 + go.uber.org/zap v1.10.0 // indirect + golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 + golang.org/x/net v0.0.0-20191011234655-491137f69257 google.golang.org/grpc v1.24.0 - gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v9 v9.30.0 gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/telegram-bot-api.v4 v4.6.4 - sigs.k8s.io/yaml v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 89f68358..df9d9044 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= github.com/Azure/azure-sdk-for-go v32.4.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/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw= @@ -19,28 +18,23 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= 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/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= 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-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= @@ -48,13 +42,10 @@ github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -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/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY= github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= @@ -63,18 +54,12 @@ github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.10.0 h1:wJPNqfrQO0w3fCiQcf/2T4lR2y6Q2fAwRszllljgb8I= -github.com/cloudflare/cloudflare-go v0.10.0/go.mod h1:fOESqHl/jzAmCtEyjceLkw3v0rVjzl8V9iehxZPynXY= github.com/cloudflare/cloudflare-go v0.10.2 h1:VBodKICVPnwmDxstcW3biKcDSpFIfS/RELUXsZSBYK4= github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= 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/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= -github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.15+incompatible h1:+9RjdC18gMxNQVvSiXvObLu29mOFmkgdsB4cRTlV+EE= -github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/etcd v3.3.17+incompatible h1:f/Z3EoDSx1yjaIjLQGo1diYUlQYSBrrAQ5vP8NjwXwo= +github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= @@ -83,10 +68,8 @@ github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMEl github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= -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/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= @@ -107,7 +90,6 @@ github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3 github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c h1:pBgVXWDXju1m8W4lnEeIqTHPOzhTUO81a7yknM/xQR4= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY= @@ -117,10 +99,8 @@ github.com/fsouza/go-dockerclient v1.4.4 h1:Sd5nD4wdAgiPxvrbYUzT2ZZNmPk3z+GGnZ+f github.com/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA= 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.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-acme/lego/v3 v3.0.2 h1:cnS+URiPzkt2pd7I2WlZtFyt2ihQ762nouBybY4djjw= -github.com/go-acme/lego/v3 v3.0.2/go.mod h1:sMoLjf8BUo4Jexg+6Xw5KeFx98KVZ7Nfczh9tzLyhJU= +github.com/go-acme/lego v2.7.2+incompatible h1:ThhpPBgf6oa9X/vRd0kEmWOsX7+vmYdckmGZSb+FEp0= github.com/go-acme/lego/v3 v3.1.0 h1:yanYFoYW8azFkCvJfIk7edWWfjkYkhDxe45ZsxoW4Xk= github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= @@ -136,20 +116,14 @@ github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3yg github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= -github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 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/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-20191002201903-404acd9df4cc h1:55rEp52jU6bkyslZ1+C/7NGfpQsEc6pxGLAGDOctqbw= -github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= @@ -157,11 +131,9 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -182,37 +154,26 @@ github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= -github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= -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.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= +github.com/hashicorp/consul v1.6.1 h1:ISPgwOO8/vPYrCXQNyx63eJAYjPGRnmFsXK7aj2XICs= github.com/hashicorp/consul/api v1.2.0 h1:oPsuzLp2uk7I7rojPKuncWbZ+m5TMoD4Ivs+2Rkeh4Y= github.com/hashicorp/consul/api v1.2.0/go.mod h1:1SIkFYi2ZTXUE5Kgt179+4hH33djo11+0Eo2XgTAtkw= -github.com/hashicorp/consul/sdk v0.2.0 h1:GWFYFmry/k4b1hEoy7kSkmU8e30GAyI4VZHk0fRxeL4= github.com/hashicorp/consul/sdk v0.2.0/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-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/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: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-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.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/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= @@ -222,23 +183,18 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.1.5 h1:AYBsgJOW9gab/toO5tEB8lWetVgDKZycqkebJ8xxpqM= -github.com/hashicorp/memberlist v0.1.5/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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= -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/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -255,27 +211,19 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= -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= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -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/labbsr0x/bindman-dns-webhook v1.0.0/go.mod h1:pn4jcNjxSywRWDPDyGkFzgSnwty18OFdiUFc6S6fpgc= github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= -github.com/labbsr0x/goh v0.0.0-20190417202808-8b16b4848295/go.mod h1:RBxeaayaaMmp7GxwHiKANjkg9e+rxjOm4mB5vD5rt/I= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= -github.com/lucas-clemente/quic-go v0.12.0 h1:TRbvZ6F++sofeGbh+Z2IIyIOhl8KyGnYuA06g2yrHdI= -github.com/lucas-clemente/quic-go v0.12.0/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= github.com/lucas-clemente/quic-go v0.12.1 h1:BPITli+6KnKogtTxBk2aS4okr5dUHz2LtIDAP1b8UL4= github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= @@ -286,16 +234,14 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= -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/certmagic v0.7.3 h1:1QOfAmk5uyWcfXJFQqFZZiEsJbPMBQ1vw/ttpVOUXQU= -github.com/mholt/certmagic v0.7.3/go.mod h1:hqHzDsY32TwZpj/KswVylheSISjquF/eOVOaJTYV15w= +github.com/mholt/certmagic v0.7.5 h1:1ZGHwUI4+zg1S17tPUj5Xxb9Q1ghTjLcUZE5G4yV5SM= +github.com/mholt/certmagic v0.7.5/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= github.com/micro/cli v0.2.0 h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA= github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= 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.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -303,7 +249,6 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT 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 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-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= @@ -313,26 +258,18 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= -github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/nats-server/v2 v2.1.0 h1:Yi0+ZhRPtPAGeIxFn5erIeJIV9wXA+JznfSxK621Fbk= -github.com/nats-io/nats-server/v2 v2.1.0/go.mod h1:r5y0WgCag0dTj/qiHkHrXAcKQ/f5GMOZaEGdoxxnJ4I= github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= -github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= @@ -343,9 +280,7 @@ github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2 github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 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.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= @@ -353,37 +288,30 @@ 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/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= -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/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 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.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -392,21 +320,17 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ= 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/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -414,16 +338,12 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ 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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= -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/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= -github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= @@ -431,17 +351,11 @@ github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0B github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -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.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4= go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= @@ -460,8 +374,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc h1:KyTYo8xkh/2WdbFLUyQwBS0Jfn3qfZ9QmuPbok2oENE= -golang.org/x/crypto v0.0.0-20191001170739-f9e2070545dc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -486,8 +400,9 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191011234655-491137f69257 h1:ry8e2D+cwaV6hk7lb3aRTjjZo24shrbK0e11QEOkTIg= +golang.org/x/net v0.0.0-20191011234655-491137f69257/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -495,7 +410,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -516,7 +430,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -525,7 +438,6 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 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-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/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq/5B590r6RlnL/G8Sz7w= golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -547,14 +459,11 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 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/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -564,12 +473,8 @@ google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= @@ -582,13 +487,11 @@ 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/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/telegram-bot-api.v4 v4.6.4 h1:hpHWhzn4jTCsAJZZ2loNKfy2QWyPDRJVl3aTFXeMW8g= gopkg.in/telegram-bot-api.v4 v4.6.4/go.mod h1:5DpGO5dbumb40px+dXcwCpcjmeHNYLpk0bp3XRNvWDM= -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/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= @@ -596,12 +499,9 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl 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= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/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-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From 2e47fdc6f57c5e0e80d4128befe47bf10a0b327b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 12 Oct 2019 20:26:06 +0100 Subject: [PATCH 075/344] Check the node map to avoid dupes in resolved nodes --- network/default.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/network/default.go b/network/default.go index 58d74573..8000255d 100644 --- a/network/default.go +++ b/network/default.go @@ -171,12 +171,18 @@ func (n *network) resolveNodes() ([]string, error) { // collect network node addresses var nodes []string + var i int - i := 0 for _, record := range records { - nodes = append(nodes, record.Address) + if _, ok := nodeMap[record.Address]; ok { + continue + } + nodeMap[record.Address] = true + nodes = append(nodes, record.Address) + i++ + // break once MaxConnection nodes has been reached if i == MaxConnections { break From f7f65b82e680c89ff89346cc36a3afaeed90e6d3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Oct 2019 12:23:13 +0100 Subject: [PATCH 076/344] Cleanup registry handler/service --- registry/{ => service}/handler/handler.go | 2 +- .../{ => service}/proto/registry.micro.go | 2 +- registry/{ => service}/proto/registry.pb.go | 353 +++++++++++++++--- registry/{ => service}/proto/registry.proto | 0 registry/service/service.go | 2 +- registry/service/util.go | 2 +- registry/service/watcher.go | 2 +- 7 files changed, 300 insertions(+), 63 deletions(-) rename registry/{ => service}/handler/handler.go (97%) rename registry/{ => service}/proto/registry.micro.go (99%) rename registry/{ => service}/proto/registry.pb.go (63%) rename registry/{ => service}/proto/registry.proto (100%) diff --git a/registry/handler/handler.go b/registry/service/handler/handler.go similarity index 97% rename from registry/handler/handler.go rename to registry/service/handler/handler.go index a592dffa..2c33153a 100644 --- a/registry/handler/handler.go +++ b/registry/service/handler/handler.go @@ -6,8 +6,8 @@ import ( "github.com/micro/go-micro/errors" "github.com/micro/go-micro/registry" - pb "github.com/micro/go-micro/registry/proto" "github.com/micro/go-micro/registry/service" + pb "github.com/micro/go-micro/registry/service/proto" ) type Registry struct { diff --git a/registry/proto/registry.micro.go b/registry/service/proto/registry.micro.go similarity index 99% rename from registry/proto/registry.micro.go rename to registry/service/proto/registry.micro.go index aa6c6851..254935ed 100644 --- a/registry/proto/registry.micro.go +++ b/registry/service/proto/registry.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: registry.proto +// source: micro/go-micro/registry/service/proto/registry.proto package go_micro_registry diff --git a/registry/proto/registry.pb.go b/registry/service/proto/registry.pb.go similarity index 63% rename from registry/proto/registry.pb.go rename to registry/service/proto/registry.pb.go index c6862d59..6427812b 100644 --- a/registry/proto/registry.pb.go +++ b/registry/service/proto/registry.pb.go @@ -1,11 +1,13 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: registry.proto +// source: micro/go-micro/registry/service/proto/registry.proto package go_micro_registry import ( + context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" math "math" ) @@ -46,7 +48,7 @@ func (x EventType) String() string { } func (EventType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{0} + return fileDescriptor_2f73432195c6499a, []int{0} } // Service represents a go-micro service @@ -66,7 +68,7 @@ func (m *Service) Reset() { *m = Service{} } func (m *Service) String() string { return proto.CompactTextString(m) } func (*Service) ProtoMessage() {} func (*Service) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{0} + return fileDescriptor_2f73432195c6499a, []int{0} } func (m *Service) XXX_Unmarshal(b []byte) error { @@ -144,7 +146,7 @@ func (m *Node) Reset() { *m = Node{} } func (m *Node) String() string { return proto.CompactTextString(m) } func (*Node) ProtoMessage() {} func (*Node) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{1} + return fileDescriptor_2f73432195c6499a, []int{1} } func (m *Node) XXX_Unmarshal(b []byte) error { @@ -208,7 +210,7 @@ func (m *Endpoint) Reset() { *m = Endpoint{} } func (m *Endpoint) String() string { return proto.CompactTextString(m) } func (*Endpoint) ProtoMessage() {} func (*Endpoint) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{2} + return fileDescriptor_2f73432195c6499a, []int{2} } func (m *Endpoint) XXX_Unmarshal(b []byte) error { @@ -271,7 +273,7 @@ func (m *Value) Reset() { *m = Value{} } func (m *Value) String() string { return proto.CompactTextString(m) } func (*Value) ProtoMessage() {} func (*Value) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{3} + return fileDescriptor_2f73432195c6499a, []int{3} } func (m *Value) XXX_Unmarshal(b []byte) error { @@ -325,7 +327,7 @@ func (m *Options) Reset() { *m = Options{} } func (m *Options) String() string { return proto.CompactTextString(m) } func (*Options) ProtoMessage() {} func (*Options) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{4} + return fileDescriptor_2f73432195c6499a, []int{4} } func (m *Options) XXX_Unmarshal(b []byte) error { @@ -367,7 +369,7 @@ func (m *Result) Reset() { *m = Result{} } func (m *Result) String() string { return proto.CompactTextString(m) } func (*Result) ProtoMessage() {} func (*Result) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{5} + return fileDescriptor_2f73432195c6499a, []int{5} } func (m *Result) XXX_Unmarshal(b []byte) error { @@ -419,7 +421,7 @@ func (m *EmptyResponse) Reset() { *m = EmptyResponse{} } func (m *EmptyResponse) String() string { return proto.CompactTextString(m) } func (*EmptyResponse) ProtoMessage() {} func (*EmptyResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{6} + return fileDescriptor_2f73432195c6499a, []int{6} } func (m *EmptyResponse) XXX_Unmarshal(b []byte) error { @@ -451,7 +453,7 @@ func (m *GetRequest) Reset() { *m = GetRequest{} } func (m *GetRequest) String() string { return proto.CompactTextString(m) } func (*GetRequest) ProtoMessage() {} func (*GetRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{7} + return fileDescriptor_2f73432195c6499a, []int{7} } func (m *GetRequest) XXX_Unmarshal(b []byte) error { @@ -490,7 +492,7 @@ func (m *GetResponse) Reset() { *m = GetResponse{} } func (m *GetResponse) String() string { return proto.CompactTextString(m) } func (*GetResponse) ProtoMessage() {} func (*GetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{8} + return fileDescriptor_2f73432195c6499a, []int{8} } func (m *GetResponse) XXX_Unmarshal(b []byte) error { @@ -528,7 +530,7 @@ func (m *ListRequest) Reset() { *m = ListRequest{} } func (m *ListRequest) String() string { return proto.CompactTextString(m) } func (*ListRequest) ProtoMessage() {} func (*ListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{9} + return fileDescriptor_2f73432195c6499a, []int{9} } func (m *ListRequest) XXX_Unmarshal(b []byte) error { @@ -560,7 +562,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} } func (m *ListResponse) String() string { return proto.CompactTextString(m) } func (*ListResponse) ProtoMessage() {} func (*ListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{10} + return fileDescriptor_2f73432195c6499a, []int{10} } func (m *ListResponse) XXX_Unmarshal(b []byte) error { @@ -600,7 +602,7 @@ func (m *WatchRequest) Reset() { *m = WatchRequest{} } func (m *WatchRequest) String() string { return proto.CompactTextString(m) } func (*WatchRequest) ProtoMessage() {} func (*WatchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{11} + return fileDescriptor_2f73432195c6499a, []int{11} } func (m *WatchRequest) XXX_Unmarshal(b []byte) error { @@ -647,7 +649,7 @@ func (m *Event) Reset() { *m = Event{} } func (m *Event) String() string { return proto.CompactTextString(m) } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { - return fileDescriptor_41af05d40a615591, []int{12} + return fileDescriptor_2f73432195c6499a, []int{12} } func (m *Event) XXX_Unmarshal(b []byte) error { @@ -716,50 +718,285 @@ func init() { proto.RegisterType((*Event)(nil), "go.micro.registry.Event") } -func init() { proto.RegisterFile("registry.proto", fileDescriptor_41af05d40a615591) } +func init() { + proto.RegisterFile("micro/go-micro/registry/service/proto/registry.proto", fileDescriptor_2f73432195c6499a) +} -var fileDescriptor_41af05d40a615591 = []byte{ - // 667 bytes of a gzipped FileDescriptorProto +var fileDescriptor_2f73432195c6499a = []byte{ + // 681 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xdd, 0x6e, 0xd3, 0x4c, 0x10, 0x8d, 0xed, 0xfc, 0x4e, 0xda, 0x7e, 0xfd, 0x46, 0x08, 0x8c, 0x5b, 0x20, 0xb2, 0x04, 0x0a, - 0x48, 0x84, 0x2a, 0x54, 0x88, 0x9f, 0x2b, 0x44, 0x43, 0x25, 0xd4, 0x82, 0x58, 0xfe, 0xae, 0x4d, - 0x3c, 0x2a, 0x16, 0x89, 0x6d, 0x76, 0xb7, 0x91, 0xf2, 0x0e, 0x48, 0x3c, 0x01, 0x6f, 0xc3, 0x53, - 0xf0, 0x34, 0x68, 0xd7, 0xeb, 0x24, 0x55, 0xd7, 0x01, 0xa9, 0x70, 0x37, 0xe3, 0x3d, 0x33, 0x3b, - 0x73, 0xce, 0x59, 0x19, 0xb6, 0x38, 0x9d, 0x24, 0x42, 0xf2, 0xf9, 0x20, 0xe7, 0x99, 0xcc, 0xf0, - 0xff, 0x93, 0x6c, 0x30, 0x4d, 0xc6, 0x3c, 0x1b, 0x94, 0x07, 0xe1, 0x4f, 0x17, 0x5a, 0x6f, 0x88, - 0xcf, 0x92, 0x31, 0x21, 0x42, 0x3d, 0x8d, 0xa6, 0xe4, 0x3b, 0x3d, 0xa7, 0xdf, 0x61, 0x3a, 0x46, - 0x1f, 0x5a, 0x33, 0xe2, 0x22, 0xc9, 0x52, 0xdf, 0xd5, 0x9f, 0xcb, 0x14, 0x0f, 0xa0, 0x3d, 0x25, - 0x19, 0xc5, 0x91, 0x8c, 0x7c, 0xaf, 0xe7, 0xf5, 0xbb, 0xc3, 0xfe, 0xe0, 0x5c, 0xff, 0x81, 0xe9, - 0x3d, 0x38, 0x36, 0xd0, 0x51, 0x2a, 0xf9, 0x9c, 0x2d, 0x2a, 0xf1, 0x11, 0x74, 0x28, 0x8d, 0xf3, - 0x2c, 0x49, 0xa5, 0xf0, 0xeb, 0xba, 0xcd, 0x8e, 0xa5, 0xcd, 0xc8, 0x60, 0xd8, 0x12, 0x8d, 0x77, - 0xa1, 0x91, 0x66, 0x31, 0x09, 0xbf, 0xa1, 0xcb, 0xae, 0x58, 0xca, 0x5e, 0x66, 0x31, 0xb1, 0x02, - 0x85, 0xfb, 0xd0, 0xca, 0x72, 0x99, 0x64, 0xa9, 0xf0, 0x9b, 0x3d, 0xa7, 0xdf, 0x1d, 0x06, 0x96, - 0x82, 0x57, 0x05, 0x82, 0x95, 0xd0, 0xe0, 0x09, 0x6c, 0x9e, 0x19, 0x1d, 0xb7, 0xc1, 0xfb, 0x4c, - 0x73, 0xc3, 0x91, 0x0a, 0xf1, 0x12, 0x34, 0x66, 0xd1, 0xe4, 0x94, 0x0c, 0x41, 0x45, 0xf2, 0xd8, - 0x7d, 0xe8, 0x84, 0x3f, 0x1c, 0xa8, 0xab, 0x11, 0x70, 0x0b, 0xdc, 0x24, 0x36, 0x35, 0x6e, 0x12, - 0x2b, 0x56, 0xa3, 0x38, 0xe6, 0x24, 0x44, 0xc9, 0xaa, 0x49, 0x95, 0x06, 0x79, 0xc6, 0xa5, 0xef, - 0xf5, 0x9c, 0xbe, 0xc7, 0x74, 0x8c, 0x4f, 0x57, 0x98, 0x2e, 0x28, 0xba, 0x59, 0xb1, 0x6b, 0x15, - 0xcd, 0x17, 0x5b, 0xe3, 0xab, 0x0b, 0xed, 0x52, 0x00, 0xab, 0x49, 0x86, 0xd0, 0xe2, 0xf4, 0xe5, - 0x94, 0x84, 0xd4, 0xc5, 0xdd, 0xa1, 0x6f, 0x99, 0xef, 0xbd, 0xea, 0xc7, 0x4a, 0x20, 0xee, 0x43, - 0x9b, 0x93, 0xc8, 0xb3, 0x54, 0x90, 0x5e, 0x76, 0x5d, 0xd1, 0x02, 0x89, 0xa3, 0x73, 0x54, 0xdc, - 0x5e, 0xe3, 0x96, 0x7f, 0x43, 0x47, 0x04, 0x0d, 0x3d, 0x96, 0x95, 0x0a, 0x84, 0xba, 0x9c, 0xe7, - 0x65, 0x95, 0x8e, 0x71, 0x0f, 0x9a, 0xba, 0x5a, 0x98, 0x77, 0x52, 0xbd, 0xa8, 0xc1, 0x85, 0x3b, - 0xd0, 0x32, 0x4e, 0x54, 0x93, 0x49, 0x39, 0xd1, 0x77, 0x78, 0x4c, 0x85, 0xa1, 0x84, 0x26, 0x23, - 0x71, 0x3a, 0x91, 0x78, 0x19, 0x9a, 0xd1, 0x58, 0xc1, 0xcc, 0x08, 0x26, 0x53, 0x56, 0x17, 0xc5, - 0xbb, 0x33, 0x7a, 0x04, 0xd5, 0x2f, 0x93, 0x95, 0x50, 0xdc, 0x85, 0x8e, 0x4c, 0xa6, 0x24, 0x64, - 0x34, 0xcd, 0x8d, 0xff, 0x96, 0x1f, 0xc2, 0xff, 0x60, 0x73, 0x34, 0xcd, 0xe5, 0x9c, 0x19, 0x29, - 0xc2, 0x5b, 0x00, 0x87, 0x24, 0x99, 0x91, 0xd3, 0x5f, 0x5e, 0x59, 0xcc, 0x52, 0xa6, 0xe1, 0x08, - 0xba, 0x1a, 0x67, 0x14, 0x7c, 0x00, 0x6d, 0x73, 0x22, 0x7c, 0x47, 0xd3, 0xb1, 0x6e, 0xb8, 0x05, - 0x36, 0xdc, 0x84, 0xee, 0x51, 0x22, 0xca, 0xfb, 0xc2, 0xe7, 0xb0, 0x51, 0xa4, 0x17, 0x6c, 0xdb, - 0x87, 0x8d, 0x0f, 0x91, 0x1c, 0x7f, 0xfa, 0xfd, 0x1e, 0xdf, 0x1d, 0x68, 0x8c, 0x66, 0x94, 0xca, - 0x73, 0xaf, 0x79, 0x6f, 0x45, 0xf3, 0xad, 0xe1, 0xae, 0xcd, 0x90, 0xaa, 0xee, 0xed, 0x3c, 0x27, - 0xe3, 0x88, 0xb5, 0x54, 0xaf, 0xca, 0x57, 0xff, 0x63, 0xf9, 0xee, 0xdc, 0x83, 0xce, 0xe2, 0x1a, - 0x04, 0x68, 0x3e, 0xe3, 0x14, 0x49, 0xda, 0xae, 0xa9, 0xf8, 0x80, 0x26, 0x24, 0x69, 0xdb, 0x51, - 0xf1, 0xbb, 0x3c, 0x56, 0xdf, 0xdd, 0xe1, 0x37, 0x0f, 0xda, 0xcc, 0xb4, 0xc3, 0x63, 0xad, 0x66, - 0xf9, 0x27, 0xb8, 0x66, 0xb9, 0x70, 0x29, 0x76, 0x70, 0xbd, 0xea, 0xd8, 0x58, 0xa3, 0x86, 0x2f, - 0xca, 0xd6, 0xc4, 0x71, 0xcd, 0xf4, 0x41, 0xcf, 0x46, 0xd6, 0x19, 0x9b, 0xd5, 0xf0, 0x08, 0xe0, - 0x80, 0xf8, 0xdf, 0xea, 0xf6, 0xba, 0x30, 0x8e, 0x29, 0x11, 0x68, 0xdb, 0x65, 0xc5, 0x68, 0xc1, - 0x8d, 0xca, 0xf3, 0x45, 0xcb, 0x43, 0x68, 0x68, 0x0f, 0xa1, 0x0d, 0xbb, 0xea, 0xae, 0xe0, 0xaa, - 0x05, 0x50, 0xbc, 0xe5, 0xb0, 0xb6, 0xe7, 0x7c, 0x6c, 0xea, 0xdf, 0xf4, 0xfd, 0x5f, 0x01, 0x00, - 0x00, 0xff, 0xff, 0xfb, 0x3e, 0x7d, 0xa4, 0xb8, 0x07, 0x00, 0x00, + 0x48, 0x4d, 0xaa, 0x50, 0x21, 0x7e, 0xae, 0x10, 0x0d, 0x95, 0x50, 0x0b, 0x62, 0xf9, 0xbb, 0x36, + 0xf1, 0xa8, 0x58, 0x24, 0xb6, 0xd9, 0xdd, 0x46, 0xca, 0x3b, 0x20, 0xf1, 0x04, 0xbc, 0x0d, 0x4f, + 0xc1, 0xd3, 0xa0, 0x5d, 0xaf, 0x93, 0x54, 0xdd, 0x04, 0xa4, 0xc2, 0xdd, 0xcc, 0xee, 0x39, 0xb3, + 0xb3, 0x67, 0xce, 0xda, 0x70, 0x30, 0x49, 0x46, 0x3c, 0xeb, 0x9f, 0x66, 0x7b, 0x45, 0xc0, 0xe9, + 0x34, 0x11, 0x92, 0xcf, 0xfa, 0x82, 0xf8, 0x34, 0x19, 0x51, 0x3f, 0xe7, 0x99, 0x5c, 0x2c, 0xf7, + 0x74, 0x8a, 0xff, 0x9f, 0x66, 0x3d, 0x8d, 0xef, 0x95, 0x1b, 0xe1, 0x4f, 0x17, 0x1a, 0x6f, 0x0a, + 0x0e, 0x22, 0x54, 0xd3, 0x68, 0x42, 0xbe, 0xd3, 0x71, 0xba, 0x2d, 0xa6, 0x63, 0xf4, 0xa1, 0x31, + 0x25, 0x2e, 0x92, 0x2c, 0xf5, 0x5d, 0xbd, 0x5c, 0xa6, 0x78, 0x08, 0xcd, 0x09, 0xc9, 0x28, 0x8e, + 0x64, 0xe4, 0x7b, 0x1d, 0xaf, 0xdb, 0x1e, 0x74, 0x7b, 0x17, 0xea, 0xf7, 0x4c, 0xed, 0xde, 0x89, + 0x81, 0x0e, 0x53, 0xc9, 0x67, 0x6c, 0xce, 0xc4, 0x47, 0xd0, 0xa2, 0x34, 0xce, 0xb3, 0x24, 0x95, + 0xc2, 0xaf, 0xea, 0x32, 0x3b, 0x96, 0x32, 0x43, 0x83, 0x61, 0x0b, 0x34, 0xee, 0x41, 0x2d, 0xcd, + 0x62, 0x12, 0x7e, 0x4d, 0xd3, 0xae, 0x59, 0x68, 0x2f, 0xb3, 0x98, 0x58, 0x81, 0xc2, 0x03, 0x68, + 0x64, 0xb9, 0x4c, 0xb2, 0x54, 0xf8, 0xf5, 0x8e, 0xd3, 0x6d, 0x0f, 0x02, 0x0b, 0xe1, 0x55, 0x81, + 0x60, 0x25, 0x34, 0x78, 0x02, 0x9b, 0xe7, 0x5a, 0xc7, 0x6d, 0xf0, 0x3e, 0xd3, 0xcc, 0x68, 0xa4, + 0x42, 0xbc, 0x02, 0xb5, 0x69, 0x34, 0x3e, 0x23, 0x23, 0x50, 0x91, 0x3c, 0x76, 0x1f, 0x3a, 0xe1, + 0x0f, 0x07, 0xaa, 0xaa, 0x05, 0xdc, 0x02, 0x37, 0x89, 0x0d, 0xc7, 0x4d, 0x62, 0xa5, 0x6a, 0x14, + 0xc7, 0x9c, 0x84, 0x28, 0x55, 0x35, 0xa9, 0x9a, 0x41, 0x9e, 0x71, 0xe9, 0x7b, 0x1d, 0xa7, 0xeb, + 0x31, 0x1d, 0xe3, 0xd3, 0x25, 0xa5, 0x0b, 0x89, 0x6e, 0xaf, 0xb8, 0xeb, 0x2a, 0x99, 0x2f, 0x77, + 0x8d, 0xaf, 0x2e, 0x34, 0xcb, 0x01, 0x58, 0x4d, 0x32, 0x80, 0x06, 0xa7, 0x2f, 0x67, 0x24, 0xa4, + 0x26, 0xb7, 0x07, 0xbe, 0xa5, 0xbf, 0xf7, 0xaa, 0x1e, 0x2b, 0x81, 0x78, 0x00, 0x4d, 0x4e, 0x22, + 0xcf, 0x52, 0x41, 0xfa, 0xb2, 0xeb, 0x48, 0x73, 0x24, 0x0e, 0x2f, 0x48, 0x71, 0x77, 0x8d, 0x5b, + 0xfe, 0x8d, 0x1c, 0x11, 0xd4, 0x74, 0x5b, 0x56, 0x29, 0x10, 0xaa, 0x72, 0x96, 0x97, 0x2c, 0x1d, + 0xe3, 0x3e, 0xd4, 0x35, 0x5b, 0x98, 0x77, 0xb2, 0xfa, 0xa2, 0x06, 0x17, 0xee, 0x40, 0xc3, 0x38, + 0x51, 0x75, 0x26, 0xe5, 0x58, 0x9f, 0xe1, 0x31, 0x15, 0x86, 0x12, 0xea, 0x8c, 0xc4, 0xd9, 0x58, + 0xe2, 0x55, 0xa8, 0x47, 0x23, 0x05, 0x33, 0x2d, 0x98, 0x4c, 0x59, 0xdd, 0x7c, 0x07, 0xcc, 0x3c, + 0x82, 0xd5, 0x2f, 0x93, 0x95, 0x50, 0xdc, 0x85, 0x96, 0x4c, 0x26, 0x24, 0x64, 0x34, 0xc9, 0x8d, + 0xff, 0x16, 0x0b, 0xe1, 0x7f, 0xb0, 0x39, 0x9c, 0xe4, 0x72, 0xc6, 0xcc, 0x28, 0xc2, 0x3b, 0x00, + 0x47, 0x24, 0x99, 0x19, 0xa7, 0xbf, 0x38, 0xb2, 0xe8, 0xa5, 0x4c, 0xc3, 0x21, 0xb4, 0x35, 0xce, + 0x4c, 0xf0, 0x01, 0x34, 0xcd, 0x8e, 0xf0, 0x1d, 0x2d, 0xc7, 0xba, 0xe6, 0xe6, 0xd8, 0x70, 0x13, + 0xda, 0xc7, 0x89, 0x28, 0xcf, 0x0b, 0x9f, 0xc3, 0x46, 0x91, 0x5e, 0xb2, 0x6c, 0x17, 0x36, 0x3e, + 0x44, 0x72, 0xf4, 0xe9, 0xf7, 0xf7, 0xf8, 0xee, 0x40, 0x6d, 0x38, 0xa5, 0x54, 0x5e, 0x78, 0xcd, + 0xfb, 0x4b, 0x33, 0xdf, 0x1a, 0xec, 0xda, 0x0c, 0xa9, 0x78, 0x6f, 0x67, 0x39, 0x19, 0x47, 0xac, + 0x95, 0x7a, 0x79, 0x7c, 0xd5, 0x3f, 0x1e, 0xdf, 0xbd, 0x3e, 0xb4, 0xe6, 0xc7, 0x20, 0x40, 0xfd, + 0x19, 0xa7, 0x48, 0xd2, 0x76, 0x45, 0xc5, 0x87, 0x34, 0x26, 0x49, 0xdb, 0x8e, 0x8a, 0xdf, 0xe5, + 0xb1, 0x5a, 0x77, 0x07, 0xdf, 0x3c, 0x68, 0x32, 0x53, 0x0e, 0x4f, 0xf4, 0x34, 0xcb, 0x3f, 0xc1, + 0x0d, 0xcb, 0x81, 0x8b, 0x61, 0x07, 0x37, 0x57, 0x6d, 0x1b, 0x6b, 0x54, 0xf0, 0x45, 0x59, 0x9a, + 0x38, 0xae, 0xe9, 0x3e, 0xe8, 0xd8, 0xc4, 0x3a, 0x67, 0xb3, 0x0a, 0x1e, 0x03, 0x1c, 0x12, 0xff, + 0x5b, 0xd5, 0x5e, 0x17, 0xc6, 0x31, 0x14, 0x81, 0xb6, 0xbb, 0x2c, 0x19, 0x2d, 0xb8, 0xb5, 0x72, + 0x7f, 0x5e, 0xf2, 0x08, 0x6a, 0xda, 0x43, 0x68, 0xc3, 0x2e, 0xbb, 0x2b, 0xb8, 0x6e, 0x01, 0x14, + 0x6f, 0x39, 0xac, 0xec, 0x3b, 0x1f, 0xeb, 0xfa, 0x37, 0x7d, 0xff, 0x57, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x69, 0x33, 0x08, 0xdb, 0xde, 0x07, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// RegistryClient is the client API for Registry service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type RegistryClient interface { + GetService(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) + Register(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) + Deregister(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) + ListServices(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) + Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (Registry_WatchClient, error) +} + +type registryClient struct { + cc *grpc.ClientConn +} + +func NewRegistryClient(cc *grpc.ClientConn) RegistryClient { + return ®istryClient{cc} +} + +func (c *registryClient) GetService(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) { + out := new(GetResponse) + err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/GetService", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *registryClient) Register(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) { + out := new(EmptyResponse) + err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/Register", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *registryClient) Deregister(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) { + out := new(EmptyResponse) + err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/Deregister", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *registryClient) ListServices(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { + out := new(ListResponse) + err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/ListServices", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *registryClient) Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (Registry_WatchClient, error) { + stream, err := c.cc.NewStream(ctx, &_Registry_serviceDesc.Streams[0], "/go.micro.registry.Registry/Watch", opts...) + if err != nil { + return nil, err + } + x := ®istryWatchClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Registry_WatchClient interface { + Recv() (*Result, error) + grpc.ClientStream +} + +type registryWatchClient struct { + grpc.ClientStream +} + +func (x *registryWatchClient) Recv() (*Result, error) { + m := new(Result) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// RegistryServer is the server API for Registry service. +type RegistryServer interface { + GetService(context.Context, *GetRequest) (*GetResponse, error) + Register(context.Context, *Service) (*EmptyResponse, error) + Deregister(context.Context, *Service) (*EmptyResponse, error) + ListServices(context.Context, *ListRequest) (*ListResponse, error) + Watch(*WatchRequest, Registry_WatchServer) error +} + +func RegisterRegistryServer(s *grpc.Server, srv RegistryServer) { + s.RegisterService(&_Registry_serviceDesc, srv) +} + +func _Registry_GetService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistryServer).GetService(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.registry.Registry/GetService", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistryServer).GetService(ctx, req.(*GetRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Registry_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Service) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistryServer).Register(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.registry.Registry/Register", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistryServer).Register(ctx, req.(*Service)) + } + return interceptor(ctx, in, info, handler) +} + +func _Registry_Deregister_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Service) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistryServer).Deregister(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.registry.Registry/Deregister", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistryServer).Deregister(ctx, req.(*Service)) + } + return interceptor(ctx, in, info, handler) +} + +func _Registry_ListServices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistryServer).ListServices(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.registry.Registry/ListServices", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistryServer).ListServices(ctx, req.(*ListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Registry_Watch_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(WatchRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(RegistryServer).Watch(m, ®istryWatchServer{stream}) +} + +type Registry_WatchServer interface { + Send(*Result) error + grpc.ServerStream +} + +type registryWatchServer struct { + grpc.ServerStream +} + +func (x *registryWatchServer) Send(m *Result) error { + return x.ServerStream.SendMsg(m) +} + +var _Registry_serviceDesc = grpc.ServiceDesc{ + ServiceName: "go.micro.registry.Registry", + HandlerType: (*RegistryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetService", + Handler: _Registry_GetService_Handler, + }, + { + MethodName: "Register", + Handler: _Registry_Register_Handler, + }, + { + MethodName: "Deregister", + Handler: _Registry_Deregister_Handler, + }, + { + MethodName: "ListServices", + Handler: _Registry_ListServices_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Watch", + Handler: _Registry_Watch_Handler, + ServerStreams: true, + }, + }, + Metadata: "micro/go-micro/registry/service/proto/registry.proto", } diff --git a/registry/proto/registry.proto b/registry/service/proto/registry.proto similarity index 100% rename from registry/proto/registry.proto rename to registry/service/proto/registry.proto diff --git a/registry/service/service.go b/registry/service/service.go index 5bc3cffb..fefc9e77 100644 --- a/registry/service/service.go +++ b/registry/service/service.go @@ -7,7 +7,7 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/registry" - pb "github.com/micro/go-micro/registry/proto" + pb "github.com/micro/go-micro/registry/service/proto" ) var ( diff --git a/registry/service/util.go b/registry/service/util.go index bbde4095..5b6a1de5 100644 --- a/registry/service/util.go +++ b/registry/service/util.go @@ -2,7 +2,7 @@ package service import ( "github.com/micro/go-micro/registry" - pb "github.com/micro/go-micro/registry/proto" + pb "github.com/micro/go-micro/registry/service/proto" ) func values(v []*registry.Value) []*pb.Value { diff --git a/registry/service/watcher.go b/registry/service/watcher.go index 08f2144d..c17085a0 100644 --- a/registry/service/watcher.go +++ b/registry/service/watcher.go @@ -2,7 +2,7 @@ package service import ( "github.com/micro/go-micro/registry" - pb "github.com/micro/go-micro/registry/proto" + pb "github.com/micro/go-micro/registry/service/proto" ) type serviceWatcher struct { From b59c5a4488226254f3596587b9e5597596c97c06 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Oct 2019 12:37:13 +0100 Subject: [PATCH 077/344] move network handler to service/handler --- network/service/handler/handler.go | 205 +++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 network/service/handler/handler.go diff --git a/network/service/handler/handler.go b/network/service/handler/handler.go new file mode 100644 index 00000000..a4858308 --- /dev/null +++ b/network/service/handler/handler.go @@ -0,0 +1,205 @@ +// Package handler implements network RPC handler +package handler + +import ( + "context" + + "github.com/micro/go-micro/errors" + "github.com/micro/go-micro/network" + pbNet "github.com/micro/go-micro/network/proto" + "github.com/micro/go-micro/router" + pbRtr "github.com/micro/go-micro/router/proto" +) + +// Network implements network handler +type Network struct { + Network network.Network +} + +func flatten(n network.Node, visited map[string]bool) []network.Node { + // if node is nil runaway + if n == nil { + return nil + } + + // set visisted + if visited == nil { + visited = make(map[string]bool) + } + + // create new list of nodes + var nodes []network.Node + + // check if already visited + if visited[n.Id()] == false { + // append the current node + nodes = append(nodes, n) + } + + // set to visited + visited[n.Id()] = true + + // visit the list of peers + for _, node := range n.Peers() { + nodes = append(nodes, flatten(node, visited)...) + } + + return nodes +} + +func (n *Network) Connect(ctx context.Context, req *pbNet.ConnectRequest, resp *pbNet.ConnectResponse) error { + if len(req.Nodes) == 0 { + return nil + } + + // get list of existing nodes + nodes := n.Network.Options().Peers + + // generate a node map + nodeMap := make(map[string]bool) + + for _, node := range nodes { + nodeMap[node] = true + } + + for _, node := range req.Nodes { + // TODO: we may have been provided a network only + // so process anad resolve node.Network + if len(node.Address) == 0 { + continue + } + + // already exists + if _, ok := nodeMap[node.Address]; ok { + continue + } + + nodeMap[node.Address] = true + nodes = append(nodes, node.Address) + } + + // reinitialise the peers + n.Network.Init( + network.Peers(nodes...), + ) + + return nil +} + +// Nodes returns the list of nodes +func (n *Network) Nodes(ctx context.Context, req *pbNet.NodesRequest, resp *pbNet.NodesResponse) error { + depth := uint(req.Depth) + if depth <= 0 || depth > network.MaxDepth { + depth = network.MaxDepth + } + + // root node + nodes := map[string]network.Node{} + + // get peers encoded into protobuf + peers := flatten(n.Network, nil) + + // walk all the peers + for _, peer := range peers { + if peer == nil { + continue + } + if _, ok := nodes[peer.Id()]; ok { + continue + } + + // add to visited list + nodes[n.Network.Id()] = peer + + resp.Nodes = append(resp.Nodes, &pbNet.Node{ + Id: peer.Id(), + Address: peer.Address(), + }) + } + + return nil +} + +// Graph returns the network graph from this root node +func (n *Network) Graph(ctx context.Context, req *pbNet.GraphRequest, resp *pbNet.GraphResponse) error { + depth := uint(req.Depth) + if depth <= 0 || depth > network.MaxDepth { + depth = network.MaxDepth + } + + // get peers encoded into protobuf + peers := network.PeersToProto(n.Network, depth) + + // set the root node + resp.Root = peers + + return nil +} + +// Routes returns a list of routing table routes +func (n *Network) Routes(ctx context.Context, req *pbNet.RoutesRequest, resp *pbNet.RoutesResponse) error { + // build query + + var qOpts []router.QueryOption + + if q := req.Query; q != nil { + if len(q.Service) > 0 { + qOpts = append(qOpts, router.QueryService(q.Service)) + } + if len(q.Address) > 0 { + qOpts = append(qOpts, router.QueryAddress(q.Address)) + } + if len(q.Gateway) > 0 { + qOpts = append(qOpts, router.QueryGateway(q.Gateway)) + } + if len(q.Router) > 0 { + qOpts = append(qOpts, router.QueryRouter(q.Router)) + } + if len(q.Network) > 0 { + qOpts = append(qOpts, router.QueryNetwork(q.Network)) + } + } + + routes, err := n.Network.Options().Router.Table().Query(qOpts...) + if err != nil { + return errors.InternalServerError("go.micro.network", "failed to list routes: %s", err) + } + + var respRoutes []*pbRtr.Route + for _, route := range routes { + respRoute := &pbRtr.Route{ + Service: route.Service, + Address: route.Address, + Gateway: route.Gateway, + Network: route.Network, + Router: route.Router, + Link: route.Link, + Metric: int64(route.Metric), + } + respRoutes = append(respRoutes, respRoute) + } + + resp.Routes = respRoutes + + return nil +} + +// Services returns a list of services based on the routing table +func (n *Network) Services(ctx context.Context, req *pbNet.ServicesRequest, resp *pbNet.ServicesResponse) error { + routes, err := n.Network.Options().Router.Table().List() + if err != nil { + return errors.InternalServerError("go.micro.network", "failed to list services: %s", err) + } + + services := make(map[string]bool) + + for _, route := range routes { + if _, ok := services[route.Service]; ok { + continue + } + services[route.Service] = true + resp.Services = append(resp.Services, route.Service) + } + + return nil +} From 5029d80e686d8a46ca1381cebf65cd9a07ae061c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Oct 2019 12:37:39 +0100 Subject: [PATCH 078/344] add Network.Connect handler and network/metadata fields to node --- network/proto/network.micro.go | 19 +++ network/proto/network.pb.go | 227 ++++++++++++++++++++++++++------- network/proto/network.proto | 12 ++ 3 files changed, 210 insertions(+), 48 deletions(-) diff --git a/network/proto/network.micro.go b/network/proto/network.micro.go index 7dee3697..28e473cb 100644 --- a/network/proto/network.micro.go +++ b/network/proto/network.micro.go @@ -35,6 +35,8 @@ var _ server.Option // Client API for Network service type NetworkService interface { + // Connect to the network + Connect(ctx context.Context, in *ConnectRequest, opts ...client.CallOption) (*ConnectResponse, error) // Returns the entire network graph Graph(ctx context.Context, in *GraphRequest, opts ...client.CallOption) (*GraphResponse, error) // Returns a list of known nodes in the network @@ -63,6 +65,16 @@ func NewNetworkService(name string, c client.Client) NetworkService { } } +func (c *networkService) Connect(ctx context.Context, in *ConnectRequest, opts ...client.CallOption) (*ConnectResponse, error) { + req := c.c.NewRequest(c.name, "Network.Connect", in) + out := new(ConnectResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *networkService) Graph(ctx context.Context, in *GraphRequest, opts ...client.CallOption) (*GraphResponse, error) { req := c.c.NewRequest(c.name, "Network.Graph", in) out := new(GraphResponse) @@ -106,6 +118,8 @@ func (c *networkService) Services(ctx context.Context, in *ServicesRequest, opts // Server API for Network service type NetworkHandler interface { + // Connect to the network + Connect(context.Context, *ConnectRequest, *ConnectResponse) error // Returns the entire network graph Graph(context.Context, *GraphRequest, *GraphResponse) error // Returns a list of known nodes in the network @@ -118,6 +132,7 @@ type NetworkHandler interface { func RegisterNetworkHandler(s server.Server, hdlr NetworkHandler, opts ...server.HandlerOption) error { type network interface { + Connect(ctx context.Context, in *ConnectRequest, out *ConnectResponse) error Graph(ctx context.Context, in *GraphRequest, out *GraphResponse) error Nodes(ctx context.Context, in *NodesRequest, out *NodesResponse) error Routes(ctx context.Context, in *RoutesRequest, out *RoutesResponse) error @@ -134,6 +149,10 @@ type networkHandler struct { NetworkHandler } +func (h *networkHandler) Connect(ctx context.Context, in *ConnectRequest, out *ConnectResponse) error { + return h.NetworkHandler.Connect(ctx, in, out) +} + func (h *networkHandler) Graph(ctx context.Context, in *GraphRequest, out *GraphResponse) error { return h.NetworkHandler.Graph(ctx, in, out) } diff --git a/network/proto/network.pb.go b/network/proto/network.pb.go index 694c9ecd..4e81fa65 100644 --- a/network/proto/network.pb.go +++ b/network/proto/network.pb.go @@ -95,6 +95,76 @@ func (m *Query) GetNetwork() string { return "" } +type ConnectRequest struct { + Nodes []*Node `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ConnectRequest) Reset() { *m = ConnectRequest{} } +func (m *ConnectRequest) String() string { return proto.CompactTextString(m) } +func (*ConnectRequest) ProtoMessage() {} +func (*ConnectRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_0b7953b26a7c4730, []int{1} +} + +func (m *ConnectRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ConnectRequest.Unmarshal(m, b) +} +func (m *ConnectRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ConnectRequest.Marshal(b, m, deterministic) +} +func (m *ConnectRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConnectRequest.Merge(m, src) +} +func (m *ConnectRequest) XXX_Size() int { + return xxx_messageInfo_ConnectRequest.Size(m) +} +func (m *ConnectRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ConnectRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ConnectRequest proto.InternalMessageInfo + +func (m *ConnectRequest) GetNodes() []*Node { + if m != nil { + return m.Nodes + } + return nil +} + +type ConnectResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ConnectResponse) Reset() { *m = ConnectResponse{} } +func (m *ConnectResponse) String() string { return proto.CompactTextString(m) } +func (*ConnectResponse) ProtoMessage() {} +func (*ConnectResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_0b7953b26a7c4730, []int{2} +} + +func (m *ConnectResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ConnectResponse.Unmarshal(m, b) +} +func (m *ConnectResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ConnectResponse.Marshal(b, m, deterministic) +} +func (m *ConnectResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConnectResponse.Merge(m, src) +} +func (m *ConnectResponse) XXX_Size() int { + return xxx_messageInfo_ConnectResponse.Size(m) +} +func (m *ConnectResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ConnectResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ConnectResponse proto.InternalMessageInfo + // PeerRequest requests list of peers type NodesRequest struct { // node topology depth @@ -108,7 +178,7 @@ func (m *NodesRequest) Reset() { *m = NodesRequest{} } func (m *NodesRequest) String() string { return proto.CompactTextString(m) } func (*NodesRequest) ProtoMessage() {} func (*NodesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{1} + return fileDescriptor_0b7953b26a7c4730, []int{3} } func (m *NodesRequest) XXX_Unmarshal(b []byte) error { @@ -149,7 +219,7 @@ func (m *NodesResponse) Reset() { *m = NodesResponse{} } func (m *NodesResponse) String() string { return proto.CompactTextString(m) } func (*NodesResponse) ProtoMessage() {} func (*NodesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{2} + return fileDescriptor_0b7953b26a7c4730, []int{4} } func (m *NodesResponse) XXX_Unmarshal(b []byte) error { @@ -189,7 +259,7 @@ func (m *GraphRequest) Reset() { *m = GraphRequest{} } func (m *GraphRequest) String() string { return proto.CompactTextString(m) } func (*GraphRequest) ProtoMessage() {} func (*GraphRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{3} + return fileDescriptor_0b7953b26a7c4730, []int{5} } func (m *GraphRequest) XXX_Unmarshal(b []byte) error { @@ -228,7 +298,7 @@ func (m *GraphResponse) Reset() { *m = GraphResponse{} } func (m *GraphResponse) String() string { return proto.CompactTextString(m) } func (*GraphResponse) ProtoMessage() {} func (*GraphResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{4} + return fileDescriptor_0b7953b26a7c4730, []int{6} } func (m *GraphResponse) XXX_Unmarshal(b []byte) error { @@ -268,7 +338,7 @@ func (m *RoutesRequest) Reset() { *m = RoutesRequest{} } func (m *RoutesRequest) String() string { return proto.CompactTextString(m) } func (*RoutesRequest) ProtoMessage() {} func (*RoutesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{5} + return fileDescriptor_0b7953b26a7c4730, []int{7} } func (m *RoutesRequest) XXX_Unmarshal(b []byte) error { @@ -307,7 +377,7 @@ func (m *RoutesResponse) Reset() { *m = RoutesResponse{} } func (m *RoutesResponse) String() string { return proto.CompactTextString(m) } func (*RoutesResponse) ProtoMessage() {} func (*RoutesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{6} + return fileDescriptor_0b7953b26a7c4730, []int{8} } func (m *RoutesResponse) XXX_Unmarshal(b []byte) error { @@ -345,7 +415,7 @@ func (m *ServicesRequest) Reset() { *m = ServicesRequest{} } func (m *ServicesRequest) String() string { return proto.CompactTextString(m) } func (*ServicesRequest) ProtoMessage() {} func (*ServicesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{7} + return fileDescriptor_0b7953b26a7c4730, []int{9} } func (m *ServicesRequest) XXX_Unmarshal(b []byte) error { @@ -377,7 +447,7 @@ func (m *ServicesResponse) Reset() { *m = ServicesResponse{} } func (m *ServicesResponse) String() string { return proto.CompactTextString(m) } func (*ServicesResponse) ProtoMessage() {} func (*ServicesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{8} + return fileDescriptor_0b7953b26a7c4730, []int{10} } func (m *ServicesResponse) XXX_Unmarshal(b []byte) error { @@ -410,17 +480,21 @@ type Node struct { // node id Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // node address - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + // the network + Network string `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"` + // associated metadata + Metadata map[string]string `protobuf:"bytes,4,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Node) Reset() { *m = Node{} } func (m *Node) String() string { return proto.CompactTextString(m) } func (*Node) ProtoMessage() {} func (*Node) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{9} + return fileDescriptor_0b7953b26a7c4730, []int{11} } func (m *Node) XXX_Unmarshal(b []byte) error { @@ -455,6 +529,20 @@ func (m *Node) GetAddress() string { return "" } +func (m *Node) GetNetwork() string { + if m != nil { + return m.Network + } + return "" +} + +func (m *Node) GetMetadata() map[string]string { + if m != nil { + return m.Metadata + } + return nil +} + // Connect is sent when the node connects to the network type Connect struct { // network mode @@ -468,7 +556,7 @@ func (m *Connect) Reset() { *m = Connect{} } func (m *Connect) String() string { return proto.CompactTextString(m) } func (*Connect) ProtoMessage() {} func (*Connect) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{10} + return fileDescriptor_0b7953b26a7c4730, []int{12} } func (m *Connect) XXX_Unmarshal(b []byte) error { @@ -509,7 +597,7 @@ func (m *Close) Reset() { *m = Close{} } func (m *Close) String() string { return proto.CompactTextString(m) } func (*Close) ProtoMessage() {} func (*Close) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{11} + return fileDescriptor_0b7953b26a7c4730, []int{13} } func (m *Close) XXX_Unmarshal(b []byte) error { @@ -552,7 +640,7 @@ func (m *Peer) Reset() { *m = Peer{} } func (m *Peer) String() string { return proto.CompactTextString(m) } func (*Peer) ProtoMessage() {} func (*Peer) Descriptor() ([]byte, []int) { - return fileDescriptor_0b7953b26a7c4730, []int{12} + return fileDescriptor_0b7953b26a7c4730, []int{14} } func (m *Peer) XXX_Unmarshal(b []byte) error { @@ -589,6 +677,8 @@ func (m *Peer) GetPeers() []*Peer { func init() { proto.RegisterType((*Query)(nil), "go.micro.network.Query") + proto.RegisterType((*ConnectRequest)(nil), "go.micro.network.ConnectRequest") + proto.RegisterType((*ConnectResponse)(nil), "go.micro.network.ConnectResponse") proto.RegisterType((*NodesRequest)(nil), "go.micro.network.NodesRequest") proto.RegisterType((*NodesResponse)(nil), "go.micro.network.NodesResponse") proto.RegisterType((*GraphRequest)(nil), "go.micro.network.GraphRequest") @@ -598,6 +688,7 @@ func init() { proto.RegisterType((*ServicesRequest)(nil), "go.micro.network.ServicesRequest") proto.RegisterType((*ServicesResponse)(nil), "go.micro.network.ServicesResponse") proto.RegisterType((*Node)(nil), "go.micro.network.Node") + proto.RegisterMapType((map[string]string)(nil), "go.micro.network.Node.MetadataEntry") proto.RegisterType((*Connect)(nil), "go.micro.network.Connect") proto.RegisterType((*Close)(nil), "go.micro.network.Close") proto.RegisterType((*Peer)(nil), "go.micro.network.Peer") @@ -608,38 +699,43 @@ func init() { } var fileDescriptor_0b7953b26a7c4730 = []byte{ - // 482 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4d, 0x6f, 0xd3, 0x40, - 0x10, 0x6d, 0x3e, 0x9c, 0xb4, 0x03, 0x29, 0x65, 0x85, 0x8a, 0xe5, 0x03, 0x84, 0x15, 0x87, 0x0a, - 0x51, 0x07, 0x35, 0xea, 0x09, 0x81, 0x90, 0x7a, 0x40, 0x42, 0xa2, 0x82, 0xed, 0x1f, 0x20, 0x8d, - 0x47, 0x89, 0x05, 0xf5, 0xba, 0xbb, 0x1b, 0xaa, 0xfe, 0x02, 0x7e, 0x19, 0xff, 0x0b, 0xed, 0xce, - 0xd8, 0xb4, 0x89, 0x1d, 0xc1, 0xcd, 0x6f, 0xe7, 0xcd, 0x9b, 0xdd, 0x37, 0x4f, 0x86, 0xd3, 0x45, - 0xee, 0x96, 0xab, 0xcb, 0x74, 0xae, 0xaf, 0x26, 0x57, 0xf9, 0xdc, 0xe8, 0xc9, 0x42, 0x1f, 0xd3, - 0x47, 0x81, 0xee, 0x46, 0x9b, 0xef, 0x93, 0xd2, 0x68, 0x57, 0xa3, 0x34, 0x20, 0x71, 0xb0, 0xd0, - 0x69, 0x60, 0xa5, 0x7c, 0x9e, 0x4c, 0xdb, 0x85, 0x8c, 0x5e, 0x39, 0x34, 0xac, 0x43, 0x80, 0x64, - 0xe4, 0xaf, 0x0e, 0x44, 0x5f, 0x57, 0x68, 0x6e, 0x45, 0x0c, 0x43, 0x8b, 0xe6, 0x67, 0x3e, 0xc7, - 0xb8, 0x33, 0xee, 0x1c, 0xed, 0xa9, 0x0a, 0xfa, 0xca, 0x2c, 0xcb, 0x0c, 0x5a, 0x1b, 0x77, 0xa9, - 0xc2, 0xd0, 0x57, 0x16, 0x33, 0x87, 0x37, 0xb3, 0xdb, 0xb8, 0x47, 0x15, 0x86, 0xe2, 0x10, 0x06, - 0x34, 0x27, 0xee, 0x87, 0x02, 0x23, 0xdf, 0xc1, 0xf7, 0x8d, 0x23, 0xea, 0x60, 0x28, 0x5f, 0xc2, - 0xc3, 0x73, 0x9d, 0xa1, 0x55, 0x78, 0xbd, 0x42, 0xeb, 0xc4, 0x13, 0x88, 0x32, 0x2c, 0xdd, 0x32, - 0xdc, 0x66, 0xa4, 0x08, 0xc8, 0x77, 0x30, 0x62, 0x96, 0x2d, 0x75, 0x61, 0x51, 0xbc, 0x86, 0xa8, - 0xf0, 0x07, 0x71, 0x67, 0xdc, 0x3b, 0x7a, 0x70, 0x72, 0x98, 0xae, 0xfb, 0x92, 0x7a, 0xbe, 0x22, - 0x92, 0x1f, 0xf2, 0xd1, 0xcc, 0xca, 0xe5, 0xf6, 0x21, 0x6f, 0x61, 0xc4, 0x2c, 0x1e, 0xf2, 0x0a, - 0xfa, 0x46, 0x6b, 0x17, 0x58, 0x8d, 0x33, 0xbe, 0x20, 0x1a, 0x15, 0x38, 0xf2, 0x3d, 0x8c, 0x94, - 0x7f, 0x6b, 0xfd, 0x90, 0x63, 0x88, 0xae, 0xbd, 0xc3, 0xdc, 0xfd, 0x74, 0xb3, 0x3b, 0x2c, 0x40, - 0x11, 0x4b, 0x7e, 0x80, 0xfd, 0xaa, 0x9f, 0xa7, 0xa7, 0xec, 0x65, 0xc3, 0x1b, 0x79, 0x97, 0xa1, - 0x81, 0x3d, 0xb6, 0xf2, 0x31, 0x3c, 0xba, 0xa0, 0xd5, 0x55, 0x77, 0x90, 0x29, 0x1c, 0xfc, 0x3d, - 0x62, 0xd9, 0x04, 0x76, 0x79, 0xc3, 0x24, 0xbc, 0xa7, 0x6a, 0x2c, 0xdf, 0x40, 0xdf, 0xdb, 0x26, - 0xf6, 0xa1, 0x9b, 0x67, 0x9c, 0x87, 0x6e, 0x9e, 0xb5, 0x47, 0x41, 0x9e, 0xc2, 0xf0, 0x4c, 0x17, - 0x05, 0xce, 0x9d, 0x77, 0xcb, 0xbb, 0xdd, 0xee, 0x56, 0xd8, 0x48, 0xe0, 0xc8, 0x29, 0x44, 0x67, - 0x3f, 0x34, 0x59, 0xfc, 0xcf, 0x4d, 0xdf, 0xa0, 0xef, 0x0d, 0xff, 0x9f, 0x1e, 0x9f, 0x93, 0x12, - 0xd1, 0xf8, 0x7b, 0xf7, 0xb6, 0xec, 0x90, 0x48, 0x27, 0xbf, 0xbb, 0x30, 0x3c, 0xa7, 0x73, 0xf1, - 0x09, 0xa2, 0x90, 0x06, 0xf1, 0x6c, 0xb3, 0xe7, 0x6e, 0x98, 0x92, 0xe7, 0xad, 0x75, 0x72, 0x5c, - 0xee, 0x78, 0xad, 0x10, 0xdf, 0x26, 0xad, 0xbb, 0xe9, 0x6f, 0xd2, 0xba, 0x97, 0x7b, 0xb9, 0x23, - 0x3e, 0xc3, 0x80, 0x82, 0x22, 0x1a, 0xc8, 0xf7, 0x22, 0x98, 0x8c, 0xdb, 0x09, 0xb5, 0xdc, 0x05, - 0xec, 0x56, 0x11, 0x11, 0x2f, 0x36, 0xf9, 0x6b, 0x89, 0x4a, 0xe4, 0x36, 0x4a, 0x25, 0x7a, 0x39, - 0x08, 0x7f, 0x99, 0xe9, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x84, 0x80, 0x26, 0xe5, 0x04, - 0x00, 0x00, + // 573 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x61, 0x6a, 0xdb, 0x4c, + 0x10, 0x8d, 0x2c, 0xcb, 0x76, 0xe6, 0x8b, 0xfd, 0xb9, 0x4b, 0x49, 0x85, 0x7e, 0xb4, 0xee, 0xe2, + 0x1f, 0xa1, 0x34, 0x32, 0xc4, 0x04, 0x4a, 0x43, 0x43, 0x20, 0x94, 0x42, 0x21, 0x21, 0x55, 0x2e, + 0x50, 0xc5, 0x1a, 0x6c, 0x93, 0x58, 0xeb, 0xac, 0xd6, 0x09, 0x3e, 0x41, 0x8f, 0xd0, 0x33, 0xf5, + 0x56, 0x65, 0x77, 0x47, 0x8a, 0x1d, 0xcb, 0xa2, 0xf9, 0xe7, 0xd1, 0xbc, 0xf7, 0x66, 0x67, 0xe6, + 0x8d, 0xe1, 0x78, 0x3c, 0x55, 0x93, 0xc5, 0x4d, 0x38, 0x12, 0xb3, 0xc1, 0x6c, 0x3a, 0x92, 0x62, + 0x30, 0x16, 0x87, 0xf6, 0x47, 0x8a, 0xea, 0x51, 0xc8, 0xdb, 0xc1, 0x5c, 0x0a, 0x55, 0x44, 0xa1, + 0x89, 0x58, 0x77, 0x2c, 0x42, 0x83, 0x0a, 0xe9, 0x7b, 0x30, 0xdc, 0x2e, 0x24, 0xc5, 0x42, 0xa1, + 0x24, 0x1d, 0x1b, 0x58, 0x19, 0xfe, 0xcb, 0x01, 0xef, 0xc7, 0x02, 0xe5, 0x92, 0xf9, 0xd0, 0xcc, + 0x50, 0x3e, 0x4c, 0x47, 0xe8, 0x3b, 0x3d, 0xe7, 0x60, 0x37, 0xca, 0x43, 0x9d, 0x89, 0x93, 0x44, + 0x62, 0x96, 0xf9, 0x35, 0x9b, 0xa1, 0x50, 0x67, 0xc6, 0xb1, 0xc2, 0xc7, 0x78, 0xe9, 0xbb, 0x36, + 0x43, 0x21, 0xdb, 0x87, 0x86, 0xad, 0xe3, 0xd7, 0x4d, 0x82, 0x22, 0xcd, 0xa0, 0xf7, 0xfa, 0x9e, + 0x65, 0x50, 0xc8, 0x4f, 0xa1, 0x73, 0x2e, 0xd2, 0x14, 0x47, 0x2a, 0xc2, 0xfb, 0x05, 0x66, 0x8a, + 0x7d, 0x04, 0x2f, 0x15, 0x09, 0x66, 0xbe, 0xd3, 0x73, 0x0f, 0xfe, 0x3b, 0xda, 0x0f, 0x9f, 0xb7, + 0x1c, 0x5e, 0x8a, 0x04, 0x23, 0x0b, 0xe2, 0xaf, 0xe0, 0xff, 0x82, 0x9f, 0xcd, 0x45, 0x9a, 0x21, + 0xef, 0xc3, 0x9e, 0x46, 0x64, 0xb9, 0xe0, 0x6b, 0xf0, 0x12, 0x9c, 0xab, 0x89, 0x69, 0xb0, 0x1d, + 0xd9, 0x80, 0x7f, 0x81, 0x36, 0xa1, 0x2c, 0xed, 0x85, 0x75, 0xfb, 0xb0, 0xf7, 0x4d, 0xc6, 0xf3, + 0x49, 0x75, 0x91, 0x13, 0x68, 0x13, 0x8a, 0x8a, 0x7c, 0x80, 0xba, 0x14, 0x42, 0x19, 0x54, 0x69, + 0x8d, 0x2b, 0x44, 0x19, 0x19, 0x0c, 0x3f, 0x85, 0x76, 0xa4, 0xc7, 0x57, 0x34, 0x72, 0x08, 0xde, + 0xbd, 0x5e, 0x1a, 0xb1, 0xdf, 0x6c, 0xb2, 0xcd, 0x4e, 0x23, 0x8b, 0xe2, 0x67, 0xd0, 0xc9, 0xf9, + 0x54, 0x3d, 0xa4, 0xf5, 0x94, 0xf4, 0x48, 0xf6, 0x30, 0x04, 0x5a, 0x9b, 0x19, 0xee, 0xb5, 0x75, + 0x43, 0xfe, 0x06, 0x1e, 0x42, 0xf7, 0xe9, 0x13, 0xc9, 0x06, 0xd0, 0x22, 0xd3, 0x58, 0xe1, 0xdd, + 0xa8, 0x88, 0xf9, 0x1f, 0x07, 0xea, 0x7a, 0x6e, 0xac, 0x03, 0xb5, 0x69, 0x42, 0x1e, 0xab, 0x4d, + 0x93, 0x6a, 0x7b, 0xe5, 0x66, 0x71, 0xd7, 0xcc, 0xc2, 0xce, 0xa0, 0x35, 0x43, 0x15, 0x27, 0xb1, + 0x8a, 0xfd, 0xba, 0xe9, 0xa0, 0x5f, 0xbe, 0xa5, 0xf0, 0x82, 0x60, 0x5f, 0x53, 0x25, 0x97, 0x51, + 0xc1, 0x0a, 0x4e, 0xa0, 0xbd, 0x96, 0x62, 0x5d, 0x70, 0x6f, 0x71, 0x49, 0xef, 0xd2, 0x3f, 0xf5, + 0x26, 0x1f, 0xe2, 0xbb, 0x05, 0xd2, 0xb3, 0x6c, 0xf0, 0xb9, 0xf6, 0xc9, 0xe1, 0xc7, 0xd0, 0x24, + 0xaf, 0xe9, 0x3d, 0x6a, 0x1f, 0x6c, 0xdf, 0xa3, 0xf1, 0x8a, 0xc1, 0xf0, 0x21, 0x78, 0xe7, 0x77, + 0xc2, 0x2e, 0xff, 0x9f, 0x49, 0x3f, 0xa1, 0xae, 0xad, 0xf0, 0x12, 0x8e, 0x76, 0xf0, 0x1c, 0x51, + 0xea, 0x81, 0xba, 0x15, 0xee, 0xb2, 0xa0, 0xa3, 0xdf, 0x2e, 0x34, 0x2f, 0x69, 0xb0, 0x57, 0x4f, + 0x9d, 0xf5, 0x36, 0x59, 0xeb, 0x07, 0x1a, 0xbc, 0xaf, 0x40, 0xd0, 0x09, 0xee, 0xb0, 0xef, 0xe0, + 0x19, 0xe7, 0xb3, 0xb7, 0x9b, 0xe8, 0xd5, 0xc3, 0x09, 0xde, 0x6d, 0xcd, 0xaf, 0x6a, 0x99, 0x53, + 0x2d, 0xd3, 0x5a, 0xbd, 0xf4, 0x32, 0xad, 0xb5, 0x1b, 0xe7, 0x3b, 0xec, 0x02, 0x1a, 0xf6, 0x28, + 0x58, 0x09, 0x78, 0xed, 0xdc, 0x82, 0xde, 0x76, 0x40, 0x21, 0x77, 0x0d, 0xad, 0xfc, 0x1c, 0x58, + 0xc9, 0x5c, 0x9e, 0x5d, 0x4f, 0xc0, 0xab, 0x20, 0xb9, 0xe8, 0x4d, 0xc3, 0xfc, 0x49, 0x0f, 0xff, + 0x06, 0x00, 0x00, 0xff, 0xff, 0x79, 0x8a, 0x5f, 0xf0, 0x24, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -654,6 +750,8 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type NetworkClient interface { + // Connect to the network + Connect(ctx context.Context, in *ConnectRequest, opts ...grpc.CallOption) (*ConnectResponse, error) // Returns the entire network graph Graph(ctx context.Context, in *GraphRequest, opts ...grpc.CallOption) (*GraphResponse, error) // Returns a list of known nodes in the network @@ -672,6 +770,15 @@ func NewNetworkClient(cc *grpc.ClientConn) NetworkClient { return &networkClient{cc} } +func (c *networkClient) Connect(ctx context.Context, in *ConnectRequest, opts ...grpc.CallOption) (*ConnectResponse, error) { + out := new(ConnectResponse) + err := c.cc.Invoke(ctx, "/go.micro.network.Network/Connect", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *networkClient) Graph(ctx context.Context, in *GraphRequest, opts ...grpc.CallOption) (*GraphResponse, error) { out := new(GraphResponse) err := c.cc.Invoke(ctx, "/go.micro.network.Network/Graph", in, out, opts...) @@ -710,6 +817,8 @@ func (c *networkClient) Services(ctx context.Context, in *ServicesRequest, opts // NetworkServer is the server API for Network service. type NetworkServer interface { + // Connect to the network + Connect(context.Context, *ConnectRequest) (*ConnectResponse, error) // Returns the entire network graph Graph(context.Context, *GraphRequest) (*GraphResponse, error) // Returns a list of known nodes in the network @@ -724,6 +833,24 @@ func RegisterNetworkServer(s *grpc.Server, srv NetworkServer) { s.RegisterService(&_Network_serviceDesc, srv) } +func _Network_Connect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ConnectRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NetworkServer).Connect(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.network.Network/Connect", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NetworkServer).Connect(ctx, req.(*ConnectRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Network_Graph_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GraphRequest) if err := dec(in); err != nil { @@ -800,6 +927,10 @@ var _Network_serviceDesc = grpc.ServiceDesc{ ServiceName: "go.micro.network.Network", HandlerType: (*NetworkServer)(nil), Methods: []grpc.MethodDesc{ + { + MethodName: "Connect", + Handler: _Network_Connect_Handler, + }, { MethodName: "Graph", Handler: _Network_Graph_Handler, diff --git a/network/proto/network.proto b/network/proto/network.proto index 8097f8c0..4689325b 100644 --- a/network/proto/network.proto +++ b/network/proto/network.proto @@ -6,6 +6,8 @@ import "github.com/micro/go-micro/router/proto/router.proto"; // Network service is usesd to gain visibility into networks service Network { + // Connect to the network + rpc Connect(ConnectRequest) returns (ConnectResponse) {}; // Returns the entire network graph rpc Graph(GraphRequest) returns (GraphResponse) {}; // Returns a list of known nodes in the network @@ -25,6 +27,12 @@ message Query { string network = 5; } +message ConnectRequest { + repeated Node nodes = 1; +} + +message ConnectResponse {} + // PeerRequest requests list of peers message NodesRequest { // node topology depth @@ -67,6 +75,10 @@ message Node { string id = 1; // node address string address = 2; + // the network + string network = 3; + // associated metadata + map metadata = 4; } // Connect is sent when the node connects to the network From 174f1b857cc6f701b19f0ad728db3512708704c5 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Oct 2019 12:37:56 +0100 Subject: [PATCH 079/344] Network handler moves to service/handler --- network/handler/handler.go | 166 ------------------------------------- 1 file changed, 166 deletions(-) delete mode 100644 network/handler/handler.go diff --git a/network/handler/handler.go b/network/handler/handler.go deleted file mode 100644 index 62162e64..00000000 --- a/network/handler/handler.go +++ /dev/null @@ -1,166 +0,0 @@ -// Package handler implements network RPC handler -package handler - -import ( - "context" - - "github.com/micro/go-micro/errors" - "github.com/micro/go-micro/network" - pbNet "github.com/micro/go-micro/network/proto" - "github.com/micro/go-micro/router" - pbRtr "github.com/micro/go-micro/router/proto" -) - -// Network implements network handler -type Network struct { - Network network.Network -} - -func flatten(n network.Node, visited map[string]bool) []network.Node { - // if node is nil runaway - if n == nil { - return nil - } - - // set visisted - if visited == nil { - visited = make(map[string]bool) - } - - // create new list of nodes - var nodes []network.Node - - // check if already visited - if visited[n.Id()] == false { - // append the current node - nodes = append(nodes, n) - } - - // set to visited - visited[n.Id()] = true - - // visit the list of peers - for _, node := range n.Peers() { - nodes = append(nodes, flatten(node, visited)...) - } - - return nodes -} - -// Nodes returns the list of nodes -func (n *Network) Nodes(ctx context.Context, req *pbNet.NodesRequest, resp *pbNet.NodesResponse) error { - depth := uint(req.Depth) - if depth <= 0 || depth > network.MaxDepth { - depth = network.MaxDepth - } - - // root node - nodes := map[string]network.Node{} - - // get peers encoded into protobuf - peers := flatten(n.Network, nil) - - // walk all the peers - for _, peer := range peers { - if peer == nil { - continue - } - if _, ok := nodes[peer.Id()]; ok { - continue - } - - // add to visited list - nodes[n.Network.Id()] = peer - - resp.Nodes = append(resp.Nodes, &pbNet.Node{ - Id: peer.Id(), - Address: peer.Address(), - }) - } - - return nil -} - -// Graph returns the network graph from this root node -func (n *Network) Graph(ctx context.Context, req *pbNet.GraphRequest, resp *pbNet.GraphResponse) error { - depth := uint(req.Depth) - if depth <= 0 || depth > network.MaxDepth { - depth = network.MaxDepth - } - - // get peers encoded into protobuf - peers := network.PeersToProto(n.Network, depth) - - // set the root node - resp.Root = peers - - return nil -} - -// Routes returns a list of routing table routes -func (n *Network) Routes(ctx context.Context, req *pbNet.RoutesRequest, resp *pbNet.RoutesResponse) error { - // build query - - var qOpts []router.QueryOption - - if q := req.Query; q != nil { - if len(q.Service) > 0 { - qOpts = append(qOpts, router.QueryService(q.Service)) - } - if len(q.Address) > 0 { - qOpts = append(qOpts, router.QueryAddress(q.Address)) - } - if len(q.Gateway) > 0 { - qOpts = append(qOpts, router.QueryGateway(q.Gateway)) - } - if len(q.Router) > 0 { - qOpts = append(qOpts, router.QueryRouter(q.Router)) - } - if len(q.Network) > 0 { - qOpts = append(qOpts, router.QueryNetwork(q.Network)) - } - } - - routes, err := n.Network.Options().Router.Table().Query(qOpts...) - if err != nil { - return errors.InternalServerError("go.micro.network", "failed to list routes: %s", err) - } - - var respRoutes []*pbRtr.Route - for _, route := range routes { - respRoute := &pbRtr.Route{ - Service: route.Service, - Address: route.Address, - Gateway: route.Gateway, - Network: route.Network, - Router: route.Router, - Link: route.Link, - Metric: int64(route.Metric), - } - respRoutes = append(respRoutes, respRoute) - } - - resp.Routes = respRoutes - - return nil -} - -// Services returns a list of services based on the routing table -func (n *Network) Services(ctx context.Context, req *pbNet.ServicesRequest, resp *pbNet.ServicesResponse) error { - routes, err := n.Network.Options().Router.Table().List() - if err != nil { - return errors.InternalServerError("go.micro.network", "failed to list services: %s", err) - } - - services := make(map[string]bool) - - for _, route := range routes { - if _, ok := services[route.Service]; ok { - continue - } - services[route.Service] = true - resp.Services = append(resp.Services, route.Service) - } - - return nil -} From 01492997ea65653d4934e6d3fa0b35c95d8ca95e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Oct 2019 12:38:13 +0100 Subject: [PATCH 080/344] add Network.Init method --- network/default.go | 12 ++++++++++++ network/network.go | 2 ++ 2 files changed, 14 insertions(+) diff --git a/network/default.go b/network/default.go index 8000255d..b1dfd8d9 100644 --- a/network/default.go +++ b/network/default.go @@ -144,6 +144,18 @@ func newNetwork(opts ...Option) Network { return network } +func (n *network) Init(opts ...Option) error { + n.Lock() + defer n.Unlock() + + // TODO: maybe only allow reinit of certain opts + for _, o := range opts { + o(&n.options) + } + + return nil +} + // Options returns network options func (n *network) Options() Options { n.RLock() diff --git a/network/network.go b/network/network.go index ef303992..e927241b 100644 --- a/network/network.go +++ b/network/network.go @@ -38,6 +38,8 @@ type Node interface { type Network interface { // Node is network node Node + // Initialise options + Init(...Option) error // Options returns the network options Options() Options // Name of the network From d6c6e7815e0405f65e239962d8c06f14d97b937a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Oct 2019 12:40:53 +0100 Subject: [PATCH 081/344] Spaces not tabs --- network/proto/network.proto | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/network/proto/network.proto b/network/proto/network.proto index 4689325b..d58ed5b8 100644 --- a/network/proto/network.proto +++ b/network/proto/network.proto @@ -75,10 +75,10 @@ message Node { string id = 1; // node address string address = 2; - // the network - string network = 3; - // associated metadata - map metadata = 4; + // the network + string network = 3; + // associated metadata + map metadata = 4; } // Connect is sent when the node connects to the network From f77df51f60bc132c40e36cfaab96590476764351 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Oct 2019 18:36:22 +0100 Subject: [PATCH 082/344] Support reconnects --- network/default.go | 53 +++++++++++++++++------------- network/resolver/dns/dns.go | 4 +++ network/service/handler/handler.go | 6 ++++ tunnel/default.go | 44 ++++++++++++++++--------- 4 files changed, 68 insertions(+), 39 deletions(-) diff --git a/network/default.go b/network/default.go index b1dfd8d9..6952aaa2 100644 --- a/network/default.go +++ b/network/default.go @@ -175,9 +175,6 @@ func (n *network) Name() string { func (n *network) resolveNodes() ([]string, error) { // resolve the network address to network nodes records, err := n.options.Resolver.Resolve(n.options.Name) - if err != nil { - return nil, err - } nodeMap := make(map[string]bool) @@ -209,6 +206,7 @@ func (n *network) resolveNodes() ([]string, error) { // resolve anything that looks like a host name records, err := dns.Resolve(node) if err != nil { + log.Debugf("Failed to resolve %v %v", node, err) continue } @@ -220,7 +218,7 @@ func (n *network) resolveNodes() ([]string, error) { } } - return nodes, nil + return nodes, err } // resolve continuously resolves network nodes and initializes network tunnel with resolved addresses @@ -347,7 +345,7 @@ func (n *network) processNetChan(client transport.Client, listener tunnel.Listen if pbNetPeer.Node.Id == n.options.Id { continue } - log.Debugf("Network received peer message from: %s", pbNetPeer.Node.Id) + log.Debugf("Network received peer message from: %s %s", pbNetPeer.Node.Id, pbNetPeer.Node.Address) peer := &node{ id: pbNetPeer.Node.Id, address: pbNetPeer.Node.Address, @@ -771,14 +769,25 @@ func (n *network) advertise(client transport.Client, advertChan <-chan *router.A } } +func (n *network) sendConnect() { + // send connect message to NetworkChannel + // NOTE: in theory we could do this as soon as + // Dial to NetworkChannel succeeds, but instead + // we initialize all other node resources first + msg := &pbNet.Connect{ + Node: &pbNet.Node{ + Id: n.node.id, + Address: n.node.address, + }, + } + if err := n.sendMsg("connect", msg, NetworkChannel); err != nil { + log.Debugf("Network failed to send connect message: %s", err) + } +} + // Connect connects the network func (n *network) Connect() error { n.Lock() - // return if already connected - if n.connected { - n.Unlock() - return nil - } // try to resolve network nodes nodes, err := n.resolveNodes() @@ -797,6 +806,15 @@ func (n *network) Connect() error { return err } + // return if already connected + if n.connected { + // unlock first + n.Unlock() + // send the connect message + n.sendConnect() + return nil + } + // set our internal node address // if advertise address is not set if len(n.options.Advertise) == 0 { @@ -858,19 +876,8 @@ func (n *network) Connect() error { } n.Unlock() - // send connect message to NetworkChannel - // NOTE: in theory we could do this as soon as - // Dial to NetworkChannel succeeds, but instead - // we initialize all other node resources first - msg := &pbNet.Connect{ - Node: &pbNet.Node{ - Id: n.node.id, - Address: n.node.address, - }, - } - if err := n.sendMsg("connect", msg, NetworkChannel); err != nil { - log.Debugf("Network failed to send connect message: %s", err) - } + // send the connect message + n.sendConnect() // go resolving network nodes go n.resolve() diff --git a/network/resolver/dns/dns.go b/network/resolver/dns/dns.go index fe022d93..4cd99bf8 100644 --- a/network/resolver/dns/dns.go +++ b/network/resolver/dns/dns.go @@ -18,6 +18,10 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { port = "8085" } + if len(host) == 0 { + host = "localhost" + } + addrs, err := net.LookupHost(host) if err != nil { return nil, err diff --git a/network/service/handler/handler.go b/network/service/handler/handler.go index a4858308..54f449f9 100644 --- a/network/service/handler/handler.go +++ b/network/service/handler/handler.go @@ -9,6 +9,7 @@ import ( pbNet "github.com/micro/go-micro/network/proto" "github.com/micro/go-micro/router" pbRtr "github.com/micro/go-micro/router/proto" + "github.com/micro/go-micro/util/log" ) // Network implements network handler @@ -78,11 +79,16 @@ func (n *Network) Connect(ctx context.Context, req *pbNet.ConnectRequest, resp * nodes = append(nodes, node.Address) } + log.Infof("Network.Connect setting peers: %v", nodes) + // reinitialise the peers n.Network.Init( network.Peers(nodes...), ) + // call the connect method + n.Network.Connect() + return nil } diff --git a/tunnel/default.go b/tunnel/default.go index c65829b1..16ca339e 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -777,6 +777,30 @@ func (t *tun) setupLink(node string) (*link, error) { return link, nil } +func (t *tun) setupLinks() { + for _, node := range t.options.Nodes { + // skip zero length nodes + if len(node) == 0 { + continue + } + + // link already exists + if _, ok := t.links[node]; ok { + continue + } + + // connect to node and return link + link, err := t.setupLink(node) + if err != nil { + log.Debugf("Tunnel failed to establish node link to %s: %v", node, err) + continue + } + + // save the link + t.links[node] = link + } +} + // connect the tunnel to all the nodes and listen for incoming tunnel connections func (t *tun) connect() error { l, err := t.options.Transport.Listen(t.options.Address) @@ -816,22 +840,8 @@ func (t *tun) connect() error { } }() - for _, node := range t.options.Nodes { - // skip zero length nodes - if len(node) == 0 { - continue - } - - // connect to node and return link - link, err := t.setupLink(node) - if err != nil { - log.Debugf("Tunnel failed to establish node link to %s: %v", node, err) - continue - } - - // save the link - t.links[node] = link - } + // setup links + t.setupLinks() // process outbound messages to be sent // process sends to all links @@ -850,6 +860,8 @@ func (t *tun) Connect() error { // already connected if t.connected { + // setup links + t.setupLinks() return nil } From a1b47866821db0b4a394f49a8692935f4b346f83 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Mon, 14 Oct 2019 12:04:49 +0100 Subject: [PATCH 083/344] TLS -> ToS --- api/server/acme/acme.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/server/acme/acme.go b/api/server/acme/acme.go index 9d61816a..cecf49e0 100644 --- a/api/server/acme/acme.go +++ b/api/server/acme/acme.go @@ -45,8 +45,8 @@ type Options struct { Cache interface{} } -// AcceptTLS indicates whether you accept your CA's terms of service -func AcceptTLS(b bool) Option { +// AcceptToS indicates whether you accept your CA's terms of service +func AcceptToS(b bool) Option { return func(o *Options) { o.AcceptToS = b } @@ -78,7 +78,7 @@ func OnDemand(b bool) Option { // Default uses the Let's Encrypt Production CA, with DNS Challenge disabled. func Default() []Option { return []Option{ - AcceptTLS(true), + AcceptToS(true), CA(LetsEncryptProductionCA), OnDemand(true), } From a1342c23fbd100db482b8592e1b97cf2286454d8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Oct 2019 15:17:25 +0100 Subject: [PATCH 084/344] add mutex lock implementation --- sync/lock/lock.go | 5 ++ sync/lock/mutex/mutex.go | 142 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 sync/lock/mutex/mutex.go diff --git a/sync/lock/lock.go b/sync/lock/lock.go index 8be6629f..c21a9125 100644 --- a/sync/lock/lock.go +++ b/sync/lock/lock.go @@ -2,9 +2,14 @@ package lock import ( + "errors" "time" ) +var ( + ErrLockTimeout = errors.New("lock timeout") +) + // Lock is a distributed locking interface type Lock interface { // Acquire a lock with given id diff --git a/sync/lock/mutex/mutex.go b/sync/lock/mutex/mutex.go new file mode 100644 index 00000000..81059ab3 --- /dev/null +++ b/sync/lock/mutex/mutex.go @@ -0,0 +1,142 @@ +// Package mutex provides a sync.Mutex implementation of the lock for local use +package mutex + +import ( + "sync" + "time" + + lock "github.com/micro/go-micro/sync/lock" +) + +type mutexLock struct { + sync.RWMutex + locks map[string]*mlock +} + +type mlock struct { + id string + time time.Time + ttl time.Duration + release chan bool +} + +func (m *mutexLock) Acquire(id string, opts ...lock.AcquireOption) error { + // lock our access + m.Lock() + + var options lock.AcquireOptions + for _, o := range opts { + o(&options) + } + + lk, ok := m.locks[id] + if !ok { + m.locks[id] = &mlock{ + id: id, + time: time.Now(), + ttl: options.TTL, + release: make(chan bool), + } + // unlock + m.Unlock() + return nil + } + + m.Unlock() + + // set wait time + var wait <-chan time.Time + var ttl <-chan time.Time + + // decide if we should wait + if options.Wait > time.Duration(0) { + wait = time.After(options.Wait) + } + + // check the ttl of the lock + if lk.ttl > time.Duration(0) { + // time lived for the lock + live := time.Since(lk.time) + + // set a timer for the leftover ttl + if live > lk.ttl { + // release the lock if it expired + m.Release(id) + } else { + ttl = time.After(live) + } + } + +lockLoop: + for { + // wait for the lock to be released + select { + case <-lk.release: + m.Lock() + + // someone locked before us + lk, ok = m.locks[id] + if ok { + m.Unlock() + continue + } + + // got chance to lock + m.locks[id] = &mlock{ + id: id, + time: time.Now(), + ttl: options.TTL, + release: make(chan bool), + } + + m.Unlock() + + break lockLoop + case <-ttl: + // ttl exceeded + m.Release(id) + // TODO: check the ttl again above + ttl = nil + // try acquire + continue + case <-wait: + return lock.ErrLockTimeout + } + } + + return nil +} + +func (m *mutexLock) Release(id string) error { + m.Lock() + defer m.Unlock() + + lk, ok := m.locks[id] + // no lock exists + if !ok { + return nil + } + + // delete the lock + delete(m.locks, id) + + select { + case <-lk.release: + return nil + default: + close(lk.release) + } + + return nil +} + +func NewLock(opts ...lock.Option) lock.Lock { + var options lock.Options + for _, o := range opts { + o(&options) + } + + return &mutexLock{ + locks: make(map[string]*mlock), + } +} From 745299bce5c3e7df22894fdcecc8882a6296e1fa Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Oct 2019 21:39:25 +0100 Subject: [PATCH 085/344] add http lock implementation --- sync/lock/http/http.go | 135 ++++++++++++++++++++++++++++++++ sync/lock/http/server/server.go | 45 +++++++++++ 2 files changed, 180 insertions(+) create mode 100644 sync/lock/http/http.go create mode 100644 sync/lock/http/server/server.go diff --git a/sync/lock/http/http.go b/sync/lock/http/http.go new file mode 100644 index 00000000..892be138 --- /dev/null +++ b/sync/lock/http/http.go @@ -0,0 +1,135 @@ +// Package http adds a http lock implementation +package http + +import ( + "errors" + "fmt" + "hash/crc32" + "io/ioutil" + "net/http" + "net/url" + "path/filepath" + "strings" + + "github.com/micro/go-micro/sync/lock" +) + +var ( + DefaultPath = "/sync/lock" + DefaultAddress = "localhost:8080" +) + +type httpLock struct { + opts lock.Options +} + +func (h *httpLock) url(id string) (string, error) { + sum := crc32.ChecksumIEEE([]byte(id)) + node := h.opts.Nodes[sum%uint32(len(h.opts.Nodes))] + + // parse the host:port or whatever + uri, err := url.Parse(node) + if err != nil { + return "", err + } + + if len(uri.Scheme) == 0 { + uri.Scheme = "http" + } + + // set path + // build path + path := filepath.Join(DefaultPath, h.opts.Prefix, id) + uri.Path = path + + // return url + return uri.String(), nil +} + +func (h *httpLock) Acquire(id string, opts ...lock.AcquireOption) error { + var options lock.AcquireOptions + for _, o := range opts { + o(&options) + } + + uri, err := h.url(id) + if err != nil { + return err + } + + ttl := fmt.Sprintf("%d", int64(options.TTL.Seconds())) + wait := fmt.Sprintf("%d", int64(options.Wait.Seconds())) + + rsp, err := http.PostForm(uri, url.Values{ + "id": {id}, + "ttl": {ttl}, + "wait": {wait}, + }) + if err != nil { + return err + } + defer rsp.Body.Close() + + b, err := ioutil.ReadAll(rsp.Body) + if err != nil { + return err + } + + // success + if rsp.StatusCode == 200 { + return nil + } + + // return error + return errors.New(string(b)) +} + +func (h *httpLock) Release(id string) error { + uri, err := h.url(id) + if err != nil { + return err + } + + vals := url.Values{ + "id": {id}, + } + + req, err := http.NewRequest("DELETE", uri, strings.NewReader(vals.Encode())) + if err != nil { + return err + } + + rsp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer rsp.Body.Close() + + b, err := ioutil.ReadAll(rsp.Body) + if err != nil { + return err + } + + // success + if rsp.StatusCode == 200 { + return nil + } + + // return error + return errors.New(string(b)) +} + +func NewLock(opts ...lock.Option) lock.Lock { + var options lock.Options + for _, o := range opts { + o(&options) + } + + if len(options.Nodes) == 0 { + options.Nodes = []string{DefaultAddress} + } + + return &httpLock{ + opts: options, + } +} diff --git a/sync/lock/http/server/server.go b/sync/lock/http/server/server.go new file mode 100644 index 00000000..49298547 --- /dev/null +++ b/sync/lock/http/server/server.go @@ -0,0 +1,45 @@ +// Package server implements the sync http server +package server + +import ( + "net/http" + + "github.com/micro/go-micro/sync/lock" + lkhttp "github.com/micro/go-micro/sync/lock/http" +) + +func Handler(lk lock.Lock) http.Handler { + mux := http.NewServeMux() + + mux.HandleFunc(lkhttp.DefaultPath, func(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + + id := r.Form.Get("id") + if len(id) == 0 { + return + } + + switch r.Method { + case "POST": + err := lk.Acquire(id) + if err != nil { + http.Error(w, err.Error(), 500) + } + case "DELETE": + err := lk.Release(id) + if err != nil { + http.Error(w, err.Error(), 500) + } + } + }) + + return mux +} + +func Server(lk lock.Lock) *http.Server { + server := &http.Server{ + Addr: lkhttp.DefaultAddress, + Handler: Handler(lk), + } + return server +} From 854b01c20c9886e1ba58a30bfbb9ef37948d95a7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Oct 2019 21:52:18 +0100 Subject: [PATCH 086/344] Add acquire/release to http path --- sync/lock/http/http.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sync/lock/http/http.go b/sync/lock/http/http.go index 892be138..497774d5 100644 --- a/sync/lock/http/http.go +++ b/sync/lock/http/http.go @@ -23,7 +23,7 @@ type httpLock struct { opts lock.Options } -func (h *httpLock) url(id string) (string, error) { +func (h *httpLock) url(do, id string) (string, error) { sum := crc32.ChecksumIEEE([]byte(id)) node := h.opts.Nodes[sum%uint32(len(h.opts.Nodes))] @@ -39,7 +39,7 @@ func (h *httpLock) url(id string) (string, error) { // set path // build path - path := filepath.Join(DefaultPath, h.opts.Prefix, id) + path := filepath.Join(DefaultPath, do, h.opts.Prefix, id) uri.Path = path // return url @@ -52,7 +52,7 @@ func (h *httpLock) Acquire(id string, opts ...lock.AcquireOption) error { o(&options) } - uri, err := h.url(id) + uri, err := h.url("acquire", id) if err != nil { return err } @@ -85,7 +85,7 @@ func (h *httpLock) Acquire(id string, opts ...lock.AcquireOption) error { } func (h *httpLock) Release(id string) error { - uri, err := h.url(id) + uri, err := h.url("release", id) if err != nil { return err } From b1fed017528b2366b880e4203f4266e103256583 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Oct 2019 22:26:23 +0100 Subject: [PATCH 087/344] add network name to node --- network/node.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/network/node.go b/network/node.go index d015b9d9..8b4d3f57 100644 --- a/network/node.go +++ b/network/node.go @@ -322,6 +322,11 @@ func peerProtoTopology(peer Node, depth uint) *pb.Peer { Address: peer.Address(), } + // set the network name if network is not nil + if peer.Network() != nil { + node.Network = peer.Network().Name() + } + pbPeers := &pb.Peer{ Node: node, Peers: make([]*pb.Peer, 0), @@ -351,6 +356,12 @@ func PeersToProto(node Node, depth uint) *pb.Peer { Id: node.Id(), Address: node.Address(), } + + // set the network name if network is not nil + if node.Network() != nil { + pbNode.Network = node.Network().Name() + } + // we will build proto topology into this pbPeers := &pb.Peer{ Node: pbNode, From 247249050b2e4be1d2edf3e0a7eddc169502058c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Oct 2019 22:38:22 +0100 Subject: [PATCH 088/344] move mutex to memory --- sync/lock/{mutex/mutex.go => memory/memory.go} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename sync/lock/{mutex/mutex.go => memory/memory.go} (88%) diff --git a/sync/lock/mutex/mutex.go b/sync/lock/memory/memory.go similarity index 88% rename from sync/lock/mutex/mutex.go rename to sync/lock/memory/memory.go index 81059ab3..0812cee6 100644 --- a/sync/lock/mutex/mutex.go +++ b/sync/lock/memory/memory.go @@ -1,5 +1,5 @@ -// Package mutex provides a sync.Mutex implementation of the lock for local use -package mutex +// Package memoy provides a sync.Mutex implementation of the lock for local use +package memory import ( "sync" @@ -8,7 +8,7 @@ import ( lock "github.com/micro/go-micro/sync/lock" ) -type mutexLock struct { +type memoryLock struct { sync.RWMutex locks map[string]*mlock } @@ -20,7 +20,7 @@ type mlock struct { release chan bool } -func (m *mutexLock) Acquire(id string, opts ...lock.AcquireOption) error { +func (m *memoryLock) Acquire(id string, opts ...lock.AcquireOption) error { // lock our access m.Lock() @@ -107,7 +107,7 @@ lockLoop: return nil } -func (m *mutexLock) Release(id string) error { +func (m *memoryLock) Release(id string) error { m.Lock() defer m.Unlock() @@ -136,7 +136,7 @@ func NewLock(opts ...lock.Option) lock.Lock { o(&options) } - return &mutexLock{ + return &memoryLock{ locks: make(map[string]*mlock), } } From 44b794722e0e51adfba6a5d45568d6be2007d602 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Oct 2019 22:39:26 +0100 Subject: [PATCH 089/344] rcache becomes cache --- registry/cache/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/cache/cache.go b/registry/cache/cache.go index 8acd79a3..a6068ae8 100644 --- a/registry/cache/cache.go +++ b/registry/cache/cache.go @@ -423,7 +423,7 @@ func (c *cache) Stop() { } func (c *cache) String() string { - return "rcache" + return "cache" } // New returns a new cache From 9bd0a8f3b51e7bff88a0988b1d4f563bbee6b9a5 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Tue, 15 Oct 2019 12:35:20 +0100 Subject: [PATCH 090/344] Update go.mod for cloudflare --- go.mod | 17 ++++++++++- go.sum | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c8d22e00..caf4e6c8 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,12 @@ require ( github.com/BurntSushi/toml v0.3.1 github.com/beevik/ntp v0.2.0 github.com/bitly/go-simplejson v0.5.0 + github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/bwmarrin/discordgo v0.19.0 + github.com/cloudflare/cloudflare-go v0.10.4 + github.com/coreos/bbolt v1.3.3 // indirect github.com/coreos/etcd v3.3.17+incompatible + github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c @@ -18,13 +22,18 @@ require ( github.com/go-log/log v0.1.0 github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect + github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect + github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc // indirect github.com/golang/protobuf v1.3.2 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/websocket v1.4.1 + github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/hashicorp/consul/api v1.2.0 github.com/hashicorp/hcl v1.0.0 github.com/imdario/mergo v0.3.8 + github.com/jonboulle/clockwork v0.1.0 // indirect github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 github.com/leodido/go-urn v1.1.0 // indirect @@ -33,16 +42,22 @@ require ( github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 github.com/mitchellh/hashstructure v1.0.0 + github.com/nats-io/nats-server/v2 v2.1.0 // indirect github.com/nats-io/nats.go v1.8.1 github.com/nlopes/slack v0.6.0 github.com/pkg/errors v0.8.1 + github.com/soheilhy/cmux v0.1.4 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect + github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect + go.etcd.io/bbolt v1.3.3 // indirect go.uber.org/multierr v1.2.0 // indirect - go.uber.org/zap v1.10.0 // indirect golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/net v0.0.0-20191011234655-491137f69257 google.golang.org/grpc v1.24.0 + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v9 v9.30.0 gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/telegram-bot-api.v4 v4.6.4 + sigs.k8s.io/yaml v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index df9d9044..dfcc6613 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= github.com/Azure/azure-sdk-for-go v32.4.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/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw= @@ -18,23 +19,28 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= 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/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= 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-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= @@ -42,10 +48,13 @@ github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +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/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY= github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= @@ -56,10 +65,16 @@ github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wX github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.10.2 h1:VBodKICVPnwmDxstcW3biKcDSpFIfS/RELUXsZSBYK4= github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= +github.com/cloudflare/cloudflare-go v0.10.4 h1:7C1D9mtcNFZLCqmhkHK2BlwKKm9fi4cBqY6qpYtQv5E= +github.com/cloudflare/cloudflare-go v0.10.4/go.mod h1:4HgmUutVbZTRnHg91bS8lvlA0Wx+TgqttLDcwey2S6E= 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/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.17+incompatible h1:f/Z3EoDSx1yjaIjLQGo1diYUlQYSBrrAQ5vP8NjwXwo= github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= @@ -68,8 +83,10 @@ github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMEl github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= +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/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= @@ -90,6 +107,7 @@ github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3 github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c h1:pBgVXWDXju1m8W4lnEeIqTHPOzhTUO81a7yknM/xQR4= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY= @@ -99,8 +117,8 @@ github.com/fsouza/go-dockerclient v1.4.4 h1:Sd5nD4wdAgiPxvrbYUzT2ZZNmPk3z+GGnZ+f github.com/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA= 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.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-acme/lego v2.7.2+incompatible h1:ThhpPBgf6oa9X/vRd0kEmWOsX7+vmYdckmGZSb+FEp0= github.com/go-acme/lego/v3 v3.1.0 h1:yanYFoYW8azFkCvJfIk7edWWfjkYkhDxe45ZsxoW4Xk= github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= @@ -116,14 +134,20 @@ github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3yg github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 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/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-20191002201903-404acd9df4cc h1:55rEp52jU6bkyslZ1+C/7NGfpQsEc6pxGLAGDOctqbw= +github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= @@ -131,9 +155,11 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -154,24 +180,34 @@ github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= +github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= +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.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= -github.com/hashicorp/consul v1.6.1 h1:ISPgwOO8/vPYrCXQNyx63eJAYjPGRnmFsXK7aj2XICs= github.com/hashicorp/consul/api v1.2.0 h1:oPsuzLp2uk7I7rojPKuncWbZ+m5TMoD4Ivs+2Rkeh4Y= github.com/hashicorp/consul/api v1.2.0/go.mod h1:1SIkFYi2ZTXUE5Kgt179+4hH33djo11+0Eo2XgTAtkw= +github.com/hashicorp/consul/sdk v0.2.0 h1:GWFYFmry/k4b1hEoy7kSkmU8e30GAyI4VZHk0fRxeL4= github.com/hashicorp/consul/sdk v0.2.0/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-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/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: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-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.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -182,9 +218,11 @@ 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/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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM= @@ -195,6 +233,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -212,11 +252,14 @@ github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= 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= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +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/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= @@ -234,6 +277,7 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +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/certmagic v0.7.5 h1:1ZGHwUI4+zg1S17tPUj5Xxb9Q1ghTjLcUZE5G4yV5SM= github.com/mholt/certmagic v0.7.5/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= @@ -249,6 +293,7 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT 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 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-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= @@ -266,10 +311,16 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= +github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats-server/v2 v2.1.0 h1:Yi0+ZhRPtPAGeIxFn5erIeJIV9wXA+JznfSxK621Fbk= +github.com/nats-io/nats-server/v2 v2.1.0/go.mod h1:r5y0WgCag0dTj/qiHkHrXAcKQ/f5GMOZaEGdoxxnJ4I= github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= +github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= @@ -280,7 +331,9 @@ github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2 github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 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.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= @@ -288,30 +341,37 @@ 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/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= +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/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 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.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -320,6 +380,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ= 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/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= @@ -331,6 +392,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -338,10 +401,13 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ 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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= +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/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -351,11 +417,18 @@ github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0B github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +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.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4= go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= @@ -401,6 +474,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191011234655-491137f69257 h1:ry8e2D+cwaV6hk7lb3aRTjjZo24shrbK0e11QEOkTIg= golang.org/x/net v0.0.0-20191011234655-491137f69257/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -410,6 +484,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -464,6 +539,8 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 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/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -473,8 +550,12 @@ google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= @@ -487,11 +568,13 @@ 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/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/telegram-bot-api.v4 v4.6.4 h1:hpHWhzn4jTCsAJZZ2loNKfy2QWyPDRJVl3aTFXeMW8g= gopkg.in/telegram-bot-api.v4 v4.6.4/go.mod h1:5DpGO5dbumb40px+dXcwCpcjmeHNYLpk0bp3XRNvWDM= +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/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= @@ -499,9 +582,12 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl 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= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/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-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From a46133f05995be61bc1b932f2fd67ce5f836b49d Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Tue, 15 Oct 2019 12:35:45 +0100 Subject: [PATCH 091/344] cloudflare workers KV Store implementation --- store/cloudflare/cloudflare.go | 119 ++++++++++++++++++++++++++++ store/cloudflare/cloudflare_test.go | 66 +++++++++++++++ 2 files changed, 185 insertions(+) create mode 100644 store/cloudflare/cloudflare.go create mode 100644 store/cloudflare/cloudflare_test.go diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go new file mode 100644 index 00000000..a35302dd --- /dev/null +++ b/store/cloudflare/cloudflare.go @@ -0,0 +1,119 @@ +// Package cloudflare is a store implementation backed by cloudflare workers kv +// Note that the cloudflare workers KV API is eventually consistent. +package cloudflare + +import ( + "context" + "log" + "time" + + "github.com/cloudflare/cloudflare-go" + "github.com/micro/go-micro/config/options" + "github.com/micro/go-micro/store" +) + +var namespaceUUID string + +type workersKV struct { + options.Options + api *cloudflare.API +} + +// New returns a cloudflare Store implementation. +// Options expects CF_API_TOKEN to a cloudflare API token scoped to Workers KV, +// CF_ACCOUNT_ID to contain a string with your cloudflare account ID and +// KV_NAMESPACE_ID to contain the namespace UUID for your KV storage. +func New(opts ...options.Option) (store.Store, error) { + // Validate Options + options := options.NewOptions(opts...) + apiToken, ok := options.Values().Get("CF_API_TOKEN") + if !ok { + log.Fatal("Store: No CF_API_TOKEN passed as an option") + } + apiTokenString, ok := apiToken.(string) + if !ok { + log.Fatal("Store: Option CF_API_TOKEN contains a non-string") + } + accountID, ok := options.Values().Get("CF_ACCOUNT_ID") + if !ok { + log.Fatal("Store: No CF_ACCOUNT_ID passed as an option") + } + accountIDString, ok := accountID.(string) + if !ok { + log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string") + } + uuid, ok := options.Values().Get("KV_NAMESPACE_ID") + if !ok { + log.Fatal("Store: No KV_NAMESPACE_ID passed as an option") + } + namespaceUUID, ok = uuid.(string) + if !ok { + log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string") + } + + // Create API client + api, err := cloudflare.NewWithAPIToken(apiTokenString, cloudflare.UsingAccount(accountIDString)) + if err != nil { + return nil, err + } + return &workersKV{ + Options: options, + api: api, + }, nil +} + +// In the cloudflare workers KV implemention, Sync() doesn't guarantee +// anything as the workers API is eventually consistent. +func (w *workersKV) Sync() ([]*store.Record, error) { + response, err := w.api.ListWorkersKVs(context.Background(), namespaceUUID) + if err != nil { + return nil, err + } + var keys []string + for _, r := range response.Result { + keys = append(keys, r.Name) + } + return w.Read(keys...) +} + +func (w *workersKV) Read(keys ...string) ([]*store.Record, error) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + var records []*store.Record + for _, k := range keys { + v, err := w.api.ReadWorkersKV(ctx, namespaceUUID, k) + if err != nil { + return records, err + } + records = append(records, &store.Record{ + Key: k, + Value: v, + }) + } + return records, nil +} + +func (w *workersKV) Write(records ...*store.Record) error { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + for _, r := range records { + if _, err := w.api.WriteWorkersKV(ctx, namespaceUUID, r.Key, r.Value); err != nil { + return err + } + } + return nil +} + +func (w *workersKV) Delete(keys ...string) error { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + for _, k := range keys { + if _, err := w.api.DeleteWorkersKV(ctx, namespaceUUID, k); err != nil { + return err + } + } + return nil +} diff --git a/store/cloudflare/cloudflare_test.go b/store/cloudflare/cloudflare_test.go new file mode 100644 index 00000000..faf4465f --- /dev/null +++ b/store/cloudflare/cloudflare_test.go @@ -0,0 +1,66 @@ +package cloudflare + +import ( + "math/rand" + "os" + "strconv" + "testing" + "time" + + "github.com/micro/go-micro/config/options" + "github.com/micro/go-micro/store" +) + +func TestCloudflare(t *testing.T) { + apiToken, accountID := os.Getenv("CF_API_TOKEN"), os.Getenv("CF_ACCOUNT_ID") + kvID := os.Getenv("KV_NAMESPACE_ID") + if len(apiToken) == 0 || len(accountID) == 0 || len(kvID) == 0 { + t.Skip("No Cloudflare API keys available, skipping test") + } + rand.Seed(time.Now().UnixNano()) + randomK := strconv.Itoa(rand.Int()) + randomV := strconv.Itoa(rand.Int()) + + wkv, err := New( + options.WithValue("CF_API_TOKEN", apiToken), + options.WithValue("CF_ACCOUNT_ID", accountID), + options.WithValue("KV_NAMESPACE_ID", kvID), + ) + + if err != nil { + t.Fatal(err.Error()) + } + + _, err = wkv.Sync() + if err != nil { + t.Fatalf("Sync: %s\n", err.Error()) + } + + err = wkv.Write(&store.Record{ + Key: randomK, + Value: []byte(randomV), + }) + if err != nil { + t.Errorf("Write: %s", err.Error()) + } + + // This might be needed for cloudflare eventual consistency + time.Sleep(1 * time.Minute) + + r, err := wkv.Read(randomK) + if err != nil { + t.Errorf("Read: %s\n", err.Error()) + } + if len(r) != 1 { + t.Errorf("Expected to read 1 key, got %d keys\n", len(r)) + } + if string(r[0].Value) != randomV { + t.Errorf("Read: expected %s, got %s\n", randomK, string(r[0].Value)) + } + + err = wkv.Delete(randomK) + if err != nil { + t.Errorf("Delete: %s\n", err.Error()) + } + +} From fed5af68e69da70e4a63b5519dea71a1d2ea1934 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 15 Oct 2019 15:03:47 +0100 Subject: [PATCH 092/344] Handle Accept errors gracefully. Originally when Accept fails we log the error and let the program flow continue. This can lead to us spawning handling connection go routines on nil connections which in turn leads to Go panics. --- network/default.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/network/default.go b/network/default.go index 6952aaa2..a6c759c7 100644 --- a/network/default.go +++ b/network/default.go @@ -269,14 +269,21 @@ func (n *network) acceptNetConn(l tunnel.Listener, recv chan *transport.Message) for { // accept a connection conn, err := l.Accept() - if err != nil { - log.Debugf("Network tunnel [%s] accept error: %v", NetworkChannel, err) - } select { case <-n.closed: + // only try to close the connection if it has been successfully opened + if err != nil { + if closeErr := conn.Close(); closeErr != nil { + log.Debugf("Network tunnel [%s] failed to close connection: %v", NetworkChannel, closeErr) + } + } return default: + if err != nil { + log.Debugf("Network tunnel [%s] accept error: %v", NetworkChannel, err) + continue + } // go handle NetworkChannel connection go n.handleNetConn(conn, recv) } @@ -558,14 +565,21 @@ func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *transport.Message for { // accept a connection conn, err := l.Accept() - if err != nil { - log.Debugf("Network tunnel [%s] accept error: %v", ControlChannel, err) - } select { case <-n.closed: + // only try to close the connection if it has been successfully opened + if err != nil { + if closeErr := conn.Close(); closeErr != nil { + log.Debugf("Network tunnel [%s] failed to close connection: %v", ControlChannel, closeErr) + } + } return default: + if err != nil { + log.Debugf("Network tunnel [%s] accept error: %v", ControlChannel, err) + continue + } // go handle ControlChannel connection go n.handleCtrlConn(conn, recv) } From 7b1f5584abfe3cd36534fbbf1a133a39be80575f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 15 Oct 2019 15:40:04 +0100 Subject: [PATCH 093/344] Tunnel mode --- tunnel/broker/broker.go | 2 +- tunnel/default.go | 25 +++++++++++++++--------- tunnel/listener.go | 4 ++-- tunnel/options.go | 20 ++++++++++++++++--- tunnel/session.go | 43 +++++++++++++++++++++-------------------- tunnel/tunnel.go | 10 +++++++++- 6 files changed, 67 insertions(+), 37 deletions(-) diff --git a/tunnel/broker/broker.go b/tunnel/broker/broker.go index 6778dfaa..75779698 100644 --- a/tunnel/broker/broker.go +++ b/tunnel/broker/broker.go @@ -71,7 +71,7 @@ func (t *tunBroker) Publish(topic string, m *broker.Message, opts ...broker.Publ } func (t *tunBroker) Subscribe(topic string, h broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) { - l, err := t.tunnel.Listen(topic) + l, err := t.tunnel.Listen(topic, tunnel.ListenMulticast()) if err != nil { return nil, err } diff --git a/tunnel/default.go b/tunnel/default.go index 16ca339e..fe63fe26 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -326,7 +326,7 @@ func (t *tun) process() { } // check the multicast mappings - if msg.multicast { + if msg.mode > Unicast { link.RLock() _, ok := link.channels[msg.channel] link.RUnlock() @@ -366,7 +366,7 @@ func (t *tun) process() { sent = true // keep sending broadcast messages - if msg.broadcast || msg.multicast { + if msg.mode > Unicast { continue } @@ -523,7 +523,7 @@ func (t *tun) listen(link *link) { case "accept": s, exists := t.getSession(channel, sessionId) // we don't need this - if exists && s.multicast { + if exists && s.mode > Unicast { s.accepted = true continue } @@ -963,7 +963,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { } // set the multicast option - c.multicast = options.Multicast + c.mode = options.Mode // set the dial timeout c.timeout = options.Timeout @@ -1009,7 +1009,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { // discovered so set the link if not multicast // TODO: pick the link efficiently based // on link status and saturation. - if c.discovered && !c.multicast { + if c.discovered && c.mode == Unicast { // set the link i := rand.Intn(len(links)) c.link = links[i] @@ -1019,7 +1019,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { if !c.discovered { // create a new discovery message for this channel msg := c.newMessage("discover") - msg.broadcast = true + msg.mode = Broadcast msg.outbound = true msg.link = "" @@ -1041,7 +1041,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { dialTimeout := after() // set a shorter delay for multicast - if c.multicast { + if c.mode > Unicast { // shorten this dialTimeout = time.Millisecond * 500 } @@ -1057,7 +1057,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { } // if its multicast just go ahead because this is best effort - if c.multicast { + if c.mode > Unicast { c.discovered = true c.accepted = true return c, nil @@ -1086,9 +1086,14 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { } // Accept a connection on the address -func (t *tun) Listen(channel string) (Listener, error) { +func (t *tun) Listen(channel string, opts ...ListenOption) (Listener, error) { log.Debugf("Tunnel listening on %s", channel) + var options ListenOptions + for _, o := range opts { + o(&options) + } + // create a new session by hashing the address c, ok := t.newSession(channel, "listener") if !ok { @@ -1103,6 +1108,8 @@ func (t *tun) Listen(channel string) (Listener, error) { c.remote = "remote" // set local c.local = channel + // set mode + c.mode = options.Mode tl := &tunListener{ channel: channel, diff --git a/tunnel/listener.go b/tunnel/listener.go index f154b2a6..c893297d 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -82,8 +82,8 @@ func (t *tunListener) process() { loopback: m.loopback, // the link the message was received on link: m.link, - // set multicast - multicast: m.multicast, + // set the connection mode + mode: m.mode, // close chan closed: make(chan bool), // recv called by the acceptor diff --git a/tunnel/options.go b/tunnel/options.go index 903f7fb7..54e740e2 100644 --- a/tunnel/options.go +++ b/tunnel/options.go @@ -36,12 +36,19 @@ type DialOption func(*DialOptions) type DialOptions struct { // Link specifies the link to use Link string - // specify a multicast connection - Multicast bool + // specify mode of the session + Mode Mode // the dial timeout Timeout time.Duration } +type ListenOption func(*ListenOptions) + +type ListenOptions struct { + // specify mode of the session + Mode Mode +} + // The tunnel id func Id(id string) Option { return func(o *Options) { @@ -87,12 +94,19 @@ func DefaultOptions() Options { } } +// Listen options +func ListenMulticast() ListenOption { + return func(o *ListenOptions) { + o.Mode = Multicast + } +} + // Dial options // Dial multicast sets the multicast option to send only to those mapped func DialMulticast() DialOption { return func(o *DialOptions) { - o.Multicast = true + o.Mode = Multicast } } diff --git a/tunnel/session.go b/tunnel/session.go index 6757f150..0cd3bcce 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -37,10 +37,8 @@ type session struct { outbound bool // lookback marks the session as a loopback on the inbound loopback bool - // if the session is multicast - multicast bool - // if the session is broadcast - broadcast bool + // mode of the connection + mode Mode // the timeout timeout time.Duration // the link on which this message was received @@ -63,10 +61,8 @@ type message struct { outbound bool // loopback marks the message intended for loopback loopback bool - // whether to send as multicast - multicast bool - // broadcast sets the broadcast type - broadcast bool + // mode of the connection + mode Mode // the link to send the message on link string // transport data @@ -98,15 +94,15 @@ func (s *session) Channel() string { // newMessage creates a new message based on the session func (s *session) newMessage(typ string) *message { return &message{ - typ: typ, - tunnel: s.tunnel, - channel: s.channel, - session: s.session, - outbound: s.outbound, - loopback: s.loopback, - multicast: s.multicast, - link: s.link, - errChan: s.errChan, + typ: typ, + tunnel: s.tunnel, + channel: s.channel, + session: s.session, + outbound: s.outbound, + loopback: s.loopback, + mode: s.mode, + link: s.link, + errChan: s.errChan, } } @@ -128,8 +124,8 @@ func (s *session) Open() error { return io.EOF } - // we don't wait on multicast - if s.multicast { + // don't wait on multicast/broadcast + if s.mode > Unicast { s.accepted = true return nil } @@ -166,6 +162,11 @@ func (s *session) Accept() error { // no op here } + // don't wait on multicast/broadcast + if s.mode > Unicast { + return nil + } + // wait for send response select { case err := <-s.errChan: @@ -185,7 +186,7 @@ func (s *session) Announce() error { // we don't need an error back msg.errChan = nil // announce to all - msg.broadcast = true + msg.mode = Broadcast // we don't need the link msg.link = "" @@ -222,7 +223,7 @@ func (s *session) Send(m *transport.Message) error { msg.data = data // if multicast don't set the link - if s.multicast { + if s.mode > Unicast { msg.link = "" } diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 312a6681..8b9b347a 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -8,6 +8,12 @@ import ( "github.com/micro/go-micro/transport" ) +const ( + Unicast Mode = iota + Multicast + Broadcast +) + var ( // DefaultDialTimeout is the dial timeout if none is specified DefaultDialTimeout = time.Second * 5 @@ -19,6 +25,8 @@ var ( ErrLinkNotFound = errors.New("link not found") ) +type Mode uint8 + // Tunnel creates a gre tunnel on top of the go-micro/transport. // It establishes multiple streams using the Micro-Tunnel-Channel header // and Micro-Tunnel-Session header. The tunnel id is a hash of @@ -36,7 +44,7 @@ type Tunnel interface { // Connect to a channel Dial(channel string, opts ...DialOption) (Session, error) // Accept connections on a channel - Listen(channel string) (Listener, error) + Listen(channel string, opts ...ListenOption) (Listener, error) // Name of the tunnel implementation String() string } From ca180893827f51408e5bb35aecf8be7413c69d2f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 15 Oct 2019 15:55:08 +0100 Subject: [PATCH 094/344] Fix bugs related to needing to send Broadcast --- tunnel/default.go | 2 +- tunnel/session.go | 6 +++--- tunnel/tunnel.go | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index fe63fe26..38f0f100 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -326,7 +326,7 @@ func (t *tun) process() { } // check the multicast mappings - if msg.mode > Unicast { + if msg.mode == Multicast { link.RLock() _, ok := link.channels[msg.channel] link.RUnlock() diff --git a/tunnel/session.go b/tunnel/session.go index 0cd3bcce..a185c3ce 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -125,7 +125,7 @@ func (s *session) Open() error { } // don't wait on multicast/broadcast - if s.mode > Unicast { + if s.mode == Multicast { s.accepted = true return nil } @@ -163,7 +163,7 @@ func (s *session) Accept() error { } // don't wait on multicast/broadcast - if s.mode > Unicast { + if s.mode == Multicast { return nil } @@ -223,7 +223,7 @@ func (s *session) Send(m *transport.Message) error { msg.data = data // if multicast don't set the link - if s.mode > Unicast { + if s.mode == Multicast { msg.link = "" } diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 8b9b347a..f46c90b8 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -9,8 +9,11 @@ import ( ) const ( + // send over one link Unicast Mode = iota + // send to all channel listeners Multicast + // send to all listeners Broadcast ) @@ -25,6 +28,7 @@ var ( ErrLinkNotFound = errors.New("link not found") ) +// Mode of the session type Mode uint8 // Tunnel creates a gre tunnel on top of the go-micro/transport. From ca934951ad3bcda774b7bda2adf10a5799671dbd Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 15 Oct 2019 15:57:13 +0100 Subject: [PATCH 095/344] Use multicast on network/control channels --- network/default.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/network/default.go b/network/default.go index 6952aaa2..e12ab8c9 100644 --- a/network/default.go +++ b/network/default.go @@ -831,7 +831,7 @@ func (n *network) Connect() error { n.tunClient[ControlChannel] = ctrlClient // listen on ControlChannel - ctrlListener, err := n.tunnel.Listen(ControlChannel) + ctrlListener, err := n.tunnel.Listen(ControlChannel, tunnel.ListenMulticast()) if err != nil { n.Unlock() return err @@ -847,7 +847,7 @@ func (n *network) Connect() error { n.tunClient[NetworkChannel] = netClient // listen on NetworkChannel - netListener, err := n.tunnel.Listen(NetworkChannel) + netListener, err := n.tunnel.Listen(NetworkChannel, tunnel.ListenMulticast()) if err != nil { n.Unlock() return err From 4936a2e1a5181d9836c9d6f44649e2fa5eb812b3 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 15 Oct 2019 15:58:33 +0100 Subject: [PATCH 096/344] Exponential backoff for failed accept connections --- network/default.go | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/network/default.go b/network/default.go index a6c759c7..535b9a83 100644 --- a/network/default.go +++ b/network/default.go @@ -19,6 +19,7 @@ import ( "github.com/micro/go-micro/transport" "github.com/micro/go-micro/tunnel" tun "github.com/micro/go-micro/tunnel/transport" + "github.com/micro/go-micro/util/backoff" "github.com/micro/go-micro/util/log" ) @@ -266,24 +267,28 @@ func (n *network) handleNetConn(sess tunnel.Session, msg chan *transport.Message // acceptNetConn accepts connections from NetworkChannel func (n *network) acceptNetConn(l tunnel.Listener, recv chan *transport.Message) { + var i int for { // accept a connection conn, err := l.Accept() + if err != nil { + sleep := backoff.Do(i) + log.Debugf("Network tunnel [%s] accept error: %v, backing off for %v", ControlChannel, err, sleep) + time.Sleep(sleep) + if i > 5 { + i = 0 + } + i++ + continue + } select { case <-n.closed: - // only try to close the connection if it has been successfully opened - if err != nil { - if closeErr := conn.Close(); closeErr != nil { - log.Debugf("Network tunnel [%s] failed to close connection: %v", NetworkChannel, closeErr) - } + if err := conn.Close(); err != nil { + log.Debugf("Network tunnel [%s] failed to close connection: %v", NetworkChannel, err) } return default: - if err != nil { - log.Debugf("Network tunnel [%s] accept error: %v", NetworkChannel, err) - continue - } // go handle NetworkChannel connection go n.handleNetConn(conn, recv) } @@ -562,24 +567,29 @@ func (n *network) handleCtrlConn(sess tunnel.Session, msg chan *transport.Messag // acceptCtrlConn accepts connections from ControlChannel func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *transport.Message) { + var i int for { // accept a connection conn, err := l.Accept() + if err != nil { + sleep := backoff.Do(i) + log.Debugf("Network tunnel [%s] accept error: %v, backing off for %v", ControlChannel, err, sleep) + time.Sleep(sleep) + if i > 5 { + // reset the counter + i = 0 + } + i++ + continue + } select { case <-n.closed: - // only try to close the connection if it has been successfully opened - if err != nil { - if closeErr := conn.Close(); closeErr != nil { - log.Debugf("Network tunnel [%s] failed to close connection: %v", ControlChannel, closeErr) - } + if err := conn.Close(); err != nil { + log.Debugf("Network tunnel [%s] failed to close connection: %v", ControlChannel, err) } return default: - if err != nil { - log.Debugf("Network tunnel [%s] accept error: %v", ControlChannel, err) - continue - } // go handle ControlChannel connection go n.handleCtrlConn(conn, recv) } From be5093798b8f1043e7268fe80185eb7c654c5d49 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 15 Oct 2019 16:08:38 +0100 Subject: [PATCH 097/344] Use DialMode/ListenMode --- network/default.go | 8 ++++---- tunnel/broker/broker.go | 4 ++-- tunnel/options.go | 8 ++++---- tunnel/tunnel.go | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/network/default.go b/network/default.go index e12ab8c9..1494d348 100644 --- a/network/default.go +++ b/network/default.go @@ -822,7 +822,7 @@ func (n *network) Connect() error { } // dial into ControlChannel to send route adverts - ctrlClient, err := n.tunnel.Dial(ControlChannel, tunnel.DialMulticast()) + ctrlClient, err := n.tunnel.Dial(ControlChannel, tunnel.DialMode(tunnel.Multicast)) if err != nil { n.Unlock() return err @@ -831,14 +831,14 @@ func (n *network) Connect() error { n.tunClient[ControlChannel] = ctrlClient // listen on ControlChannel - ctrlListener, err := n.tunnel.Listen(ControlChannel, tunnel.ListenMulticast()) + ctrlListener, err := n.tunnel.Listen(ControlChannel, tunnel.ListenMode(tunnel.Multicast)) if err != nil { n.Unlock() return err } // dial into NetworkChannel to send network messages - netClient, err := n.tunnel.Dial(NetworkChannel, tunnel.DialMulticast()) + netClient, err := n.tunnel.Dial(NetworkChannel, tunnel.DialMode(tunnel.Multicast)) if err != nil { n.Unlock() return err @@ -847,7 +847,7 @@ func (n *network) Connect() error { n.tunClient[NetworkChannel] = netClient // listen on NetworkChannel - netListener, err := n.tunnel.Listen(NetworkChannel, tunnel.ListenMulticast()) + netListener, err := n.tunnel.Listen(NetworkChannel, tunnel.ListenMode(tunnel.Multicast)) if err != nil { n.Unlock() return err diff --git a/tunnel/broker/broker.go b/tunnel/broker/broker.go index 75779698..d11e160c 100644 --- a/tunnel/broker/broker.go +++ b/tunnel/broker/broker.go @@ -58,7 +58,7 @@ func (t *tunBroker) Disconnect() error { func (t *tunBroker) Publish(topic string, m *broker.Message, opts ...broker.PublishOption) error { // TODO: this is probably inefficient, we might want to just maintain an open connection // it may be easier to add broadcast to the tunnel - c, err := t.tunnel.Dial(topic, tunnel.DialMulticast()) + c, err := t.tunnel.Dial(topic, tunnel.DialMode(tunnel.Multicast)) if err != nil { return err } @@ -71,7 +71,7 @@ func (t *tunBroker) Publish(topic string, m *broker.Message, opts ...broker.Publ } func (t *tunBroker) Subscribe(topic string, h broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) { - l, err := t.tunnel.Listen(topic, tunnel.ListenMulticast()) + l, err := t.tunnel.Listen(topic, tunnel.ListenMode(tunnel.Multicast)) if err != nil { return nil, err } diff --git a/tunnel/options.go b/tunnel/options.go index 54e740e2..7d6360ab 100644 --- a/tunnel/options.go +++ b/tunnel/options.go @@ -95,18 +95,18 @@ func DefaultOptions() Options { } // Listen options -func ListenMulticast() ListenOption { +func ListenMode(m Mode) ListenOption { return func(o *ListenOptions) { - o.Mode = Multicast + o.Mode = m } } // Dial options // Dial multicast sets the multicast option to send only to those mapped -func DialMulticast() DialOption { +func DialMode(m Mode) DialOption { return func(o *DialOptions) { - o.Mode = Multicast + o.Mode = m } } diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index f46c90b8..a2671f62 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -13,7 +13,7 @@ const ( Unicast Mode = iota // send to all channel listeners Multicast - // send to all listeners + // send to all links Broadcast ) From a6e95d389fc2b5971e88e09b8426b5dbc7bc8e50 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Tue, 15 Oct 2019 19:32:20 +0100 Subject: [PATCH 098/344] Implementation of certmagic storage using micro's store and sync packages --- .travis.yml | 2 +- api/server/acme/acme.go | 61 --------- api/server/acme/certmagic/certmagic.go | 7 + api/server/acme/certmagic/certmagic_test.go | 50 +++++--- api/server/acme/certmagic/storage.go | 134 ++++++++++++++++++++ api/server/acme/options.go | 73 +++++++++++ 6 files changed, 248 insertions(+), 79 deletions(-) create mode 100644 api/server/acme/certmagic/storage.go create mode 100644 api/server/acme/options.go diff --git a/.travis.yml b/.travis.yml index cb760ae9..e2a018e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: go go: - 1.13.x env: - - GO111MODULE=on + - GO111MODULE=on IN_TRAVIS_CI=yes notifications: slack: secure: aEvhLbhujaGaKSrOokiG3//PaVHTIrc3fBpoRbCRqfZpyq6WREoapJJhF+tIpWWOwaC9GmChbD6aHo/jMUgwKXVyPSaNjiEL87YzUUpL8B2zslNp1rgfTg/LrzthOx3Q1TYwpaAl3to0fuHUVFX4yMeC2vuThq7WSXgMMxFCtbc= diff --git a/api/server/acme/acme.go b/api/server/acme/acme.go index cecf49e0..f9df8962 100644 --- a/api/server/acme/acme.go +++ b/api/server/acme/acme.go @@ -4,8 +4,6 @@ package acme import ( "errors" "net" - - "github.com/go-acme/lego/v3/challenge" ) var ( @@ -24,62 +22,3 @@ const ( LetsEncryptStagingCA = "https://acme-staging-v02.api.letsencrypt.org/directory" LetsEncryptProductionCA = "https://acme-v02.api.letsencrypt.org/directory" ) - -// Option (or Options) are passed to New() to configure providers -type Option func(o *Options) - -// Options represents various options you can present to ACME providers -type Options struct { - // AcceptTLS must be set to true to indicate that you have read your - // provider's terms of service. - AcceptToS bool - // CA is the CA to use - CA string - // ChallengeProvider is a go-acme/lego challenge provider. Set this if you - // want to use DNS Challenges. Otherwise, tls-alpn-01 will be used - ChallengeProvider challenge.Provider - // Issue certificates for domains on demand. Otherwise, certs will be - // retrieved / issued on start-up. - OnDemand bool - // TODO - Cache interface{} -} - -// AcceptToS indicates whether you accept your CA's terms of service -func AcceptToS(b bool) Option { - return func(o *Options) { - o.AcceptToS = b - } -} - -// CA sets the CA of an acme.Options -func CA(CA string) Option { - return func(o *Options) { - o.CA = CA - } -} - -// ChallengeProvider sets the Challenge provider of an acme.Options -// if set, it enables the DNS challenge, otherwise tls-alpn-01 will be used. -func ChallengeProvider(p challenge.Provider) Option { - return func(o *Options) { - o.ChallengeProvider = p - } -} - -// OnDemand enables on-demand certificate issuance. Not recommended for use -// with the DNS challenge, as the first connection may be very slow. -func OnDemand(b bool) Option { - return func(o *Options) { - o.OnDemand = b - } -} - -// Default uses the Let's Encrypt Production CA, with DNS Challenge disabled. -func Default() []Option { - return []Option{ - AcceptToS(true), - CA(LetsEncryptProductionCA), - OnDemand(true), - } -} diff --git a/api/server/acme/certmagic/certmagic.go b/api/server/acme/certmagic/certmagic.go index 68e36f64..6d12e9d6 100644 --- a/api/server/acme/certmagic/certmagic.go +++ b/api/server/acme/certmagic/certmagic.go @@ -2,6 +2,7 @@ package certmagic import ( + "log" "net" "github.com/mholt/certmagic" @@ -36,6 +37,12 @@ func New(options ...acme.Option) acme.Provider { op(o) } } + if o.Cache != nil { + if _, ok := o.Cache.(certmagic.Storage); !ok { + log.Fatal("ACME: cache provided doesn't implement certmagic's Storage interface") + } + } + return &certmagicProvider{ opts: o, } diff --git a/api/server/acme/certmagic/certmagic_test.go b/api/server/acme/certmagic/certmagic_test.go index dc727101..52ede19c 100644 --- a/api/server/acme/certmagic/certmagic_test.go +++ b/api/server/acme/certmagic/certmagic_test.go @@ -1,19 +1,24 @@ package certmagic import ( + "os" "testing" "github.com/go-acme/lego/v3/providers/dns/cloudflare" - // "github.com/micro/go-micro/api/server/acme" + "github.com/mholt/certmagic" + "github.com/micro/go-micro/api/server/acme" + "github.com/micro/go-micro/sync/lock/memory" ) func TestCertMagic(t *testing.T) { - // TODO: Travis doesn't let us bind :443 - // l, err := New().NewListener() - // if err != nil { - // t.Error(err.Error()) - // } - // l.Close() + if len(os.Getenv("IN_TRAVIS_CI")) != 0 { + t.Skip("Travis doesn't let us bind :443") + } + l, err := New().NewListener() + if err != nil { + t.Error(err.Error()) + } + l.Close() c := cloudflare.NewDefaultConfig() c.AuthEmail = "" @@ -21,19 +26,30 @@ func TestCertMagic(t *testing.T) { c.AuthToken = "test" c.ZoneToken = "test" - _, err := cloudflare.NewDNSProviderConfig(c) + p, err := cloudflare.NewDNSProviderConfig(c) if err != nil { t.Error(err.Error()) } - // TODO: Travis doesn't let us bind :443 - // l, err = New(acme.AcceptTLS(true), - // acme.CA(acme.LetsEncryptStagingCA), - // acme.ChallengeProvider(p), - // ).NewListener() + l, err = New(acme.AcceptToS(true), + acme.CA(acme.LetsEncryptStagingCA), + acme.ChallengeProvider(p), + ).NewListener() - // if err != nil { - // t.Error(err.Error()) - // } - // l.Close() + if err != nil { + t.Error(err.Error()) + } + l.Close() +} + +func TestStorageImplementation(t *testing.T) { + var s certmagic.Storage + s = &storage{ + lock: memory.NewLock(), + } + if err := s.Lock("test"); err != nil { + t.Error(err) + } + s.Unlock("test") + New(acme.Cache(s)) } diff --git a/api/server/acme/certmagic/storage.go b/api/server/acme/certmagic/storage.go new file mode 100644 index 00000000..b1bb92b4 --- /dev/null +++ b/api/server/acme/certmagic/storage.go @@ -0,0 +1,134 @@ +package certmagic + +import ( + "bytes" + "encoding/gob" + "fmt" + "path" + "strings" + "time" + + "github.com/mholt/certmagic" + "github.com/micro/go-micro/store" + "github.com/micro/go-micro/sync/lock" +) + +// file represents a "file" that will be stored in store.Store - the contents and last modified time +type file struct { + // last modified time + lastModified time.Time + // contents + contents []byte +} + +// storage is an implementation of certmagic.Storage using micro's sync.Map and store.Store interfaces. +// As certmagic storage expects a filesystem (with stat() abilities) we have to implement +// the bare minimum of metadata. +type storage struct { + lock lock.Lock + store store.Store +} + +func (s *storage) Lock(key string) error { + return s.lock.Acquire(key, lock.TTL(10*time.Minute)) +} + +func (s *storage) Unlock(key string) error { + return s.lock.Release(key) +} + +func (s *storage) Store(key string, value []byte) error { + f := file{ + lastModified: time.Now(), + contents: value, + } + buf := &bytes.Buffer{} + e := gob.NewEncoder(buf) + if err := e.Encode(f); err != nil { + return err + } + r := &store.Record{ + Key: key, + Value: buf.Bytes(), + } + return s.store.Write(r) +} + +func (s *storage) Load(key string) ([]byte, error) { + records, err := s.store.Read(key) + if err != nil { + return nil, err + } + if len(records) != 1 { + return nil, fmt.Errorf("ACME Storage: multiple records matched key %s", key) + } + b := bytes.NewBuffer(records[0].Value) + d := gob.NewDecoder(b) + var f file + err = d.Decode(&f) + if err != nil { + return nil, err + } + return f.contents, nil +} + +func (s *storage) Delete(key string) error { + return s.store.Delete(key) +} + +func (s *storage) Exists(key string) bool { + _, err := s.store.Read() + if err != nil { + return false + } + return true +} + +func (s *storage) List(prefix string, recursive bool) ([]string, error) { + records, err := s.store.Sync() + if err != nil { + return nil, err + } + var results []string + for _, r := range records { + if strings.HasPrefix(r.Key, prefix) { + results = append(results, r.Key) + } + } + if recursive { + return results, nil + } + keysMap := make(map[string]bool) + for _, key := range results { + dir := strings.Split(strings.TrimPrefix(key, prefix+"/"), "/") + keysMap[dir[0]] = true + } + results = make([]string, 0) + for k := range keysMap { + results = append(results, path.Join(prefix, k)) + } + return results, nil +} + +func (s *storage) Stat(key string) (certmagic.KeyInfo, error) { + records, err := s.store.Read(key) + if err != nil { + return certmagic.KeyInfo{}, err + } + if len(records) != 1 { + return certmagic.KeyInfo{}, fmt.Errorf("ACME Storage: multiple records matched key %s", key) + } + b := bytes.NewBuffer(records[0].Value) + d := gob.NewDecoder(b) + var f file + err = d.Decode(&f) + if err != nil { + return certmagic.KeyInfo{}, err + } + return certmagic.KeyInfo{ + Key: key, + Modified: f.lastModified, + Size: int64(len(f.contents)), + IsTerminal: false, + }, nil +} diff --git a/api/server/acme/options.go b/api/server/acme/options.go new file mode 100644 index 00000000..cd7f55fd --- /dev/null +++ b/api/server/acme/options.go @@ -0,0 +1,73 @@ +package acme + +import "github.com/go-acme/lego/v3/challenge" + +// Option (or Options) are passed to New() to configure providers +type Option func(o *Options) + +// Options represents various options you can present to ACME providers +type Options struct { + // AcceptTLS must be set to true to indicate that you have read your + // provider's terms of service. + AcceptToS bool + // CA is the CA to use + CA string + // ChallengeProvider is a go-acme/lego challenge provider. Set this if you + // want to use DNS Challenges. Otherwise, tls-alpn-01 will be used + ChallengeProvider challenge.Provider + // Issue certificates for domains on demand. Otherwise, certs will be + // retrieved / issued on start-up. + OnDemand bool + // Cache is a storage interface. Most ACME libraries have an cache, but + // there's no defined interface, so if you consume this option + // sanity check it before using. + Cache interface{} +} + +// AcceptToS indicates whether you accept your CA's terms of service +func AcceptToS(b bool) Option { + return func(o *Options) { + o.AcceptToS = b + } +} + +// CA sets the CA of an acme.Options +func CA(CA string) Option { + return func(o *Options) { + o.CA = CA + } +} + +// ChallengeProvider sets the Challenge provider of an acme.Options +// if set, it enables the DNS challenge, otherwise tls-alpn-01 will be used. +func ChallengeProvider(p challenge.Provider) Option { + return func(o *Options) { + o.ChallengeProvider = p + } +} + +// OnDemand enables on-demand certificate issuance. Not recommended for use +// with the DNS challenge, as the first connection may be very slow. +func OnDemand(b bool) Option { + return func(o *Options) { + o.OnDemand = b + } +} + +// Cache provides a cache / storage interface to the underlying ACME library +// as there is no standard, this needs to be validated by the underlying +// implentation. +func Cache(c interface{}) Option { + return func(o *Options) { + o.Cache = c + } +} + +// Default uses the Let's Encrypt Production CA, with DNS Challenge disabled. +func Default() []Option { + return []Option{ + AcceptToS(true), + CA(LetsEncryptProductionCA), + OnDemand(true), + } +} From 7d2afa34a018989621ca44de62882b838f46bc86 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Wed, 16 Oct 2019 12:58:14 +0100 Subject: [PATCH 099/344] Implementation and tests for certmagic.Storage interface --- api/server/acme/certmagic/certmagic_test.go | 140 +++++++++++++++++++- api/server/acme/certmagic/storage.go | 26 ++-- 2 files changed, 149 insertions(+), 17 deletions(-) diff --git a/api/server/acme/certmagic/certmagic_test.go b/api/server/acme/certmagic/certmagic_test.go index 52ede19c..367f6360 100644 --- a/api/server/acme/certmagic/certmagic_test.go +++ b/api/server/acme/certmagic/certmagic_test.go @@ -2,11 +2,16 @@ package certmagic import ( "os" + "reflect" + "sort" "testing" + "time" "github.com/go-acme/lego/v3/providers/dns/cloudflare" "github.com/mholt/certmagic" "github.com/micro/go-micro/api/server/acme" + "github.com/micro/go-micro/config/options" + cloudflarestorage "github.com/micro/go-micro/store/cloudflare" "github.com/micro/go-micro/sync/lock/memory" ) @@ -43,13 +48,140 @@ func TestCertMagic(t *testing.T) { } func TestStorageImplementation(t *testing.T) { - var s certmagic.Storage - s = &storage{ - lock: memory.NewLock(), + apiToken, accountID := os.Getenv("CF_API_TOKEN"), os.Getenv("CF_ACCOUNT_ID") + kvID := os.Getenv("KV_NAMESPACE_ID") + if len(apiToken) == 0 || len(accountID) == 0 || len(kvID) == 0 { + t.Skip("No Cloudflare API keys available, skipping test") } + + var s certmagic.Storage + st, err := cloudflarestorage.New( + options.WithValue("CF_API_TOKEN", apiToken), + options.WithValue("CF_ACCOUNT_ID", accountID), + options.WithValue("KV_NAMESPACE_ID", kvID), + ) + if err != nil { + t.Fatalf("Couldn't initialise cloudflare storage: %s\n", err.Error()) + } + s = &storage{ + lock: memory.NewLock(), + store: st, + } + + // Test Lock if err := s.Lock("test"); err != nil { t.Error(err) } - s.Unlock("test") + + // Test Unlock + if err := s.Unlock("test"); err != nil { + t.Error(err) + } + + // Test data + testdata := []struct { + key string + value []byte + }{ + {key: "/foo/a", value: []byte("lorem")}, + {key: "/foo/b", value: []byte("ipsum")}, + {key: "/foo/c", value: []byte("dolor")}, + {key: "/foo/d", value: []byte("sit")}, + {key: "/bar/a", value: []byte("amet")}, + {key: "/bar/b", value: []byte("consectetur")}, + {key: "/bar/c", value: []byte("adipiscing")}, + {key: "/bar/d", value: []byte("elit")}, + {key: "/foo/bar/a", value: []byte("sed")}, + {key: "/foo/bar/b", value: []byte("do")}, + {key: "/foo/bar/c", value: []byte("eiusmod")}, + {key: "/foo/bar/d", value: []byte("tempor")}, + {key: "/foo/bar/baz/a", value: []byte("incididunt")}, + {key: "/foo/bar/baz/b", value: []byte("ut")}, + {key: "/foo/bar/baz/c", value: []byte("labore")}, + {key: "/foo/bar/baz/d", value: []byte("et")}, + // a duplicate just in case there's any edge cases + {key: "/foo/a", value: []byte("lorem")}, + } + + // Test Store + for _, d := range testdata { + if err := s.Store(d.key, d.value); err != nil { + t.Error(err.Error()) + } + } + + // Test Load + for _, d := range testdata { + if value, err := s.Load(d.key); err != nil { + t.Error(err.Error()) + } else { + if !reflect.DeepEqual(value, d.value) { + t.Errorf("Load %s: expected %v, got %v", d.key, d.value, value) + } + } + } + + // Test Exists + for _, d := range testdata { + if !s.Exists(d.key) { + t.Errorf("%s should exist, but doesn't\n", d.key) + } + } + + // Test List + if list, err := s.List("/", true); err != nil { + t.Error(err.Error()) + } else { + var expected []string + for i, d := range testdata { + if i != len(testdata)-1 { + // Don't store the intentionally duplicated key + expected = append(expected, d.key) + } + } + sort.Strings(expected) + sort.Strings(list) + if !reflect.DeepEqual(expected, list) { + t.Errorf("List: Expected %v, got %v\n", expected, list) + } + } + if list, err := s.List("/foo", false); err != nil { + t.Error(err.Error()) + } else { + sort.Strings(list) + expected := []string{"/foo/a", "/foo/b", "/foo/bar", "/foo/c", "/foo/d"} + if !reflect.DeepEqual(expected, list) { + t.Errorf("List: expected %s, got %s\n", expected, list) + } + } + + // Test Stat + for _, d := range testdata { + info, err := s.Stat(d.key) + if err != nil { + t.Error(err.Error()) + } else { + if info.Key != d.key { + t.Errorf("Stat().Key: expected %s, got %s\n", d.key, info.Key) + } + if info.Size != int64(len(d.value)) { + t.Errorf("Stat().Size: expected %d, got %d\n", len(d.value), info.Size) + } + if time.Since(info.Modified) > time.Minute { + t.Errorf("Stat().Modified: expected time since last modified to be < 1 minute, got %v\n", time.Since(info.Modified)) + } + } + + } + + // Test Delete + for _, d := range testdata { + if err := s.Delete(d.key); err != nil { + t.Error(err.Error()) + } + } + + // New interface doesn't return an error, so call it in case any log.Fatal + // happens New(acme.Cache(s)) } diff --git a/api/server/acme/certmagic/storage.go b/api/server/acme/certmagic/storage.go index b1bb92b4..d0dd3ab9 100644 --- a/api/server/acme/certmagic/storage.go +++ b/api/server/acme/certmagic/storage.go @@ -13,12 +13,12 @@ import ( "github.com/micro/go-micro/sync/lock" ) -// file represents a "file" that will be stored in store.Store - the contents and last modified time -type file struct { +// File represents a "File" that will be stored in store.Store - the contents and last modified time +type File struct { // last modified time - lastModified time.Time - // contents - contents []byte + LastModified time.Time + // Contents + Contents []byte } // storage is an implementation of certmagic.Storage using micro's sync.Map and store.Store interfaces. @@ -38,9 +38,9 @@ func (s *storage) Unlock(key string) error { } func (s *storage) Store(key string, value []byte) error { - f := file{ - lastModified: time.Now(), - contents: value, + f := File{ + LastModified: time.Now(), + Contents: value, } buf := &bytes.Buffer{} e := gob.NewEncoder(buf) @@ -64,12 +64,12 @@ func (s *storage) Load(key string) ([]byte, error) { } b := bytes.NewBuffer(records[0].Value) d := gob.NewDecoder(b) - var f file + var f File err = d.Decode(&f) if err != nil { return nil, err } - return f.contents, nil + return f.Contents, nil } func (s *storage) Delete(key string) error { @@ -120,15 +120,15 @@ func (s *storage) Stat(key string) (certmagic.KeyInfo, error) { } b := bytes.NewBuffer(records[0].Value) d := gob.NewDecoder(b) - var f file + var f File err = d.Decode(&f) if err != nil { return certmagic.KeyInfo{}, err } return certmagic.KeyInfo{ Key: key, - Modified: f.lastModified, - Size: int64(len(f.contents)), + Modified: f.LastModified, + Size: int64(len(f.Contents)), IsTerminal: false, }, nil } From 2ae583ce944d0fee1f5fd5cc7900d4dd2c149fd7 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 16 Oct 2019 20:44:22 +0100 Subject: [PATCH 100/344] Cleanup of tunnel dial code. Clean up network channel processors --- network/default.go | 12 +++++------ tunnel/default.go | 51 ++++++++++++++++++++++++++-------------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/network/default.go b/network/default.go index d0a8a683..36f80da3 100644 --- a/network/default.go +++ b/network/default.go @@ -296,7 +296,7 @@ func (n *network) acceptNetConn(l tunnel.Listener, recv chan *transport.Message) } // processNetChan processes messages received on NetworkChannel -func (n *network) processNetChan(client transport.Client, listener tunnel.Listener) { +func (n *network) processNetChan(listener tunnel.Listener) { // receive network message queue recv := make(chan *transport.Message, 128) @@ -629,7 +629,7 @@ func (n *network) setRouteMetric(route *router.Route) { } // processCtrlChan processes messages received on ControlChannel -func (n *network) processCtrlChan(client transport.Client, listener tunnel.Listener) { +func (n *network) processCtrlChan(listener tunnel.Listener) { // receive control message queue recv := make(chan *transport.Message, 128) @@ -739,7 +739,7 @@ func (n *network) processCtrlChan(client transport.Client, listener tunnel.Liste } // advertise advertises routes to the network -func (n *network) advertise(client transport.Client, advertChan <-chan *router.Advert) { +func (n *network) advertise(advertChan <-chan *router.Advert) { hasher := fnv.New64() for { select { @@ -910,11 +910,11 @@ func (n *network) Connect() error { // prune stale nodes go n.prune() // listen to network messages - go n.processNetChan(netClient, netListener) + go n.processNetChan(netListener) // advertise service routes - go n.advertise(ctrlClient, advertChan) + go n.advertise(advertChan) // accept and process routes - go n.processCtrlChan(ctrlClient, ctrlListener) + go n.processCtrlChan(ctrlListener) n.Lock() n.connected = true diff --git a/tunnel/default.go b/tunnel/default.go index 38f0f100..73052581 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -982,28 +982,32 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { var links []string // non multicast so we need to find the link - t.RLock() - for _, link := range t.links { - // use the link specified it its available - if id := options.Link; len(id) > 0 && link.id != id { - continue + if id := options.Link; id != "" { + t.RLock() + for _, link := range t.links { + // use the link specified it its available + if link.id != id { + continue + } + + link.RLock() + _, ok := link.channels[channel] + link.RUnlock() + + // we have at least one channel mapping + if ok { + c.discovered = true + links = append(links, link.id) + } + } + t.RUnlock() + // link not found + if len(links) == 0 { + // delete session and return error + t.delSession(c.channel, c.session) + return nil, ErrLinkNotFound } - link.RLock() - _, ok := link.channels[channel] - link.RUnlock() - - // we have at least one channel mapping - if ok { - c.discovered = true - links = append(links, link.id) - } - } - t.RUnlock() - - // link not found - if len(links) == 0 && len(options.Link) > 0 { - return nil, ErrLinkNotFound } // discovered so set the link if not multicast @@ -1028,9 +1032,11 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { select { case <-time.After(after()): + t.delSession(c.channel, c.session) return nil, ErrDialTimeout case err := <-c.errChan: if err != nil { + t.delSession(c.channel, c.session) return nil, err } } @@ -1041,7 +1047,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { dialTimeout := after() // set a shorter delay for multicast - if c.mode > Unicast { + if c.mode != Unicast { // shorten this dialTimeout = time.Millisecond * 500 } @@ -1057,7 +1063,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { } // if its multicast just go ahead because this is best effort - if c.mode > Unicast { + if c.mode != Unicast { c.discovered = true c.accepted = true return c, nil @@ -1065,6 +1071,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { // otherwise return an error if err != nil { + t.delSession(c.channel, c.session) return nil, err } From 4885bba2acee5da6b4b7b53d87a79d79cdca55c1 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Thu, 17 Oct 2019 16:31:02 +0100 Subject: [PATCH 101/344] E2E tests for certmagic ACME provider * Actually set the CA * Fix the certmangic.storage interface to return the correct error type * Write an e2e test for certmagic against the let's encrypt staging CA --- api/server/acme/certmagic/certmagic.go | 13 ++++++ api/server/acme/certmagic/certmagic_test.go | 44 +++++++++++++++++++++ api/server/acme/certmagic/storage.go | 14 ++++++- go.mod | 1 + 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/api/server/acme/certmagic/certmagic.go b/api/server/acme/certmagic/certmagic.go index 6d12e9d6..cde5783d 100644 --- a/api/server/acme/certmagic/certmagic.go +++ b/api/server/acme/certmagic/certmagic.go @@ -3,7 +3,9 @@ package certmagic import ( "log" + "math/rand" "net" + "time" "github.com/mholt/certmagic" @@ -15,6 +17,7 @@ type certmagicProvider struct { } func (c *certmagicProvider) NewListener(ACMEHosts ...string) (net.Listener, error) { + certmagic.Default.CA = c.opts.CA if c.opts.ChallengeProvider != nil { // Enabling DNS Challenge disables the other challenges certmagic.Default.DNSProvider = c.opts.ChallengeProvider @@ -22,6 +25,16 @@ func (c *certmagicProvider) NewListener(ACMEHosts ...string) (net.Listener, erro if c.opts.OnDemand { certmagic.Default.OnDemand = new(certmagic.OnDemandConfig) } + if c.opts.Cache != nil { + // already validated by new() + certmagic.Default.Storage = c.opts.Cache.(certmagic.Storage) + } + // If multiple instances of the provider are running, inject some + // randomness so they don't collide + rand.Seed(time.Now().UnixNano()) + randomDuration := (7 * 24 * time.Hour) + (time.Duration(rand.Intn(504)) * time.Hour) + certmagic.Default.RenewDurationBefore = randomDuration + return certmagic.Listen(ACMEHosts) } diff --git a/api/server/acme/certmagic/certmagic_test.go b/api/server/acme/certmagic/certmagic_test.go index 367f6360..8474b0bd 100644 --- a/api/server/acme/certmagic/certmagic_test.go +++ b/api/server/acme/certmagic/certmagic_test.go @@ -1,6 +1,7 @@ package certmagic import ( + "net/http" "os" "reflect" "sort" @@ -185,3 +186,46 @@ func TestStorageImplementation(t *testing.T) { // happens New(acme.Cache(s)) } + +// Full test with a real zone, with against LE staging +func TestE2e(t *testing.T) { + apiToken, accountID := os.Getenv("CF_API_TOKEN"), os.Getenv("CF_ACCOUNT_ID") + kvID := os.Getenv("KV_NAMESPACE_ID") + if len(apiToken) == 0 || len(accountID) == 0 || len(kvID) == 0 { + t.Skip("No Cloudflare API keys available, skipping test") + } + + testLock := memory.NewLock() + testStore, err := cloudflarestorage.New( + options.WithValue("CF_API_TOKEN", apiToken), + options.WithValue("CF_ACCOUNT_ID", accountID), + options.WithValue("KV_NAMESPACE_ID", kvID), + ) + if err != nil { + t.Fatal(err.Error()) + } + testStorage := NewStorage(testLock, testStore) + + conf := cloudflare.NewDefaultConfig() + conf.AuthToken = apiToken + conf.ZoneToken = apiToken + testChallengeProvider, err := cloudflare.NewDNSProviderConfig(conf) + if err != nil { + t.Fatal(err.Error()) + } + + testProvider := New( + acme.AcceptToS(true), + acme.Cache(testStorage), + acme.CA(acme.LetsEncryptStagingCA), + acme.ChallengeProvider(testChallengeProvider), + acme.OnDemand(false), + ) + + listener, err := testProvider.NewListener("*.micro.mu", "micro.mu") + if err != nil { + t.Fatal(err.Error()) + } + go http.Serve(listener, http.NotFoundHandler()) + time.Sleep(10 * time.Minute) +} diff --git a/api/server/acme/certmagic/storage.go b/api/server/acme/certmagic/storage.go index d0dd3ab9..b91b5db6 100644 --- a/api/server/acme/certmagic/storage.go +++ b/api/server/acme/certmagic/storage.go @@ -3,6 +3,7 @@ package certmagic import ( "bytes" "encoding/gob" + "errors" "fmt" "path" "strings" @@ -55,6 +56,9 @@ func (s *storage) Store(key string, value []byte) error { } func (s *storage) Load(key string) ([]byte, error) { + if !s.Exists(key) { + return nil, certmagic.ErrNotExist(errors.New(key + " doesn't exist")) + } records, err := s.store.Read(key) if err != nil { return nil, err @@ -77,7 +81,7 @@ func (s *storage) Delete(key string) error { } func (s *storage) Exists(key string) bool { - _, err := s.store.Read() + _, err := s.store.Read(key) if err != nil { return false } @@ -132,3 +136,11 @@ func (s *storage) Stat(key string) (certmagic.KeyInfo, error) { IsTerminal: false, }, nil } + +// NewStorage returns a certmagic.Storage backed by a go-micro/lock and go-micro/store +func NewStorage(lock lock.Lock, store store.Store) certmagic.Storage { + return &storage{ + lock: lock, + store: store, + } +} diff --git a/go.mod b/go.mod index caf4e6c8..dec35c22 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/jonboulle/clockwork v0.1.0 // indirect github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 + github.com/kr/pretty v0.1.0 github.com/leodido/go-urn v1.1.0 // indirect github.com/lucas-clemente/quic-go v0.12.1 github.com/mholt/certmagic v0.7.5 From 05774f2c76b3f053f0286fd61fdc9c86f59d1cd6 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Thu, 17 Oct 2019 16:35:09 +0100 Subject: [PATCH 102/344] Don't touch go.mod --- go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/go.mod b/go.mod index dec35c22..caf4e6c8 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,6 @@ require ( github.com/jonboulle/clockwork v0.1.0 // indirect github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 - github.com/kr/pretty v0.1.0 github.com/leodido/go-urn v1.1.0 // indirect github.com/lucas-clemente/quic-go v0.12.1 github.com/mholt/certmagic v0.7.5 From 3aedea4c56a6ea15927bdb580f4b6fced767181a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 17 Oct 2019 18:37:37 +0100 Subject: [PATCH 103/344] strip topic from http broker subscribe service name --- broker/http_broker.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index 4a22fe12..c2ae4dda 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -527,7 +527,7 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) // now attempt to get the service h.RLock() - s, err := h.r.GetService("topic:" + topic) + s, err := h.r.GetService(topic) if err != nil { h.RUnlock() // ignore error @@ -565,13 +565,29 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) continue } + var nodes []*registry.Node + + for _, node := range service.Nodes { + // only use nodes tagged with broker http + if node.Metadata["broker"] != "http" { + continue + } + + // look for nodes for the topic + if node.Metadata["topic"] != topic { + continue + } + + nodes = append(nodes, node) + } + switch service.Version { // broadcast version means broadcast to all nodes case broadcastVersion: var success bool // publish to all nodes - for _, node := range service.Nodes { + for _, node := range nodes { // publish async if err := pub(node, topic, b); err == nil { success = true @@ -584,7 +600,7 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) } default: // select node to publish to - node := service.Nodes[rand.Int()%len(service.Nodes)] + node := nodes[rand.Int()%len(nodes)] // publish async to one node if err := pub(node, topic, b); err != nil { @@ -647,6 +663,8 @@ func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO Address: mnet.HostPort(addr, port), Metadata: map[string]string{ "secure": fmt.Sprintf("%t", secure), + "broker": "http", + "topic": topic, }, } @@ -657,7 +675,7 @@ func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO } service := ®istry.Service{ - Name: "topic:" + topic, + Name: topic, Version: version, Nodes: []*registry.Node{node}, } From 5c38f38dd9a4f1006c60daaa3f31eebb5f118833 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 18 Oct 2019 10:29:14 +0100 Subject: [PATCH 104/344] No need to lock here since Topology read locks and makes copies --- network/node.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/network/node.go b/network/node.go index 8b4d3f57..194dd6d2 100644 --- a/network/node.go +++ b/network/node.go @@ -170,9 +170,6 @@ func (n *node) Nodes() []Node { // GetPeerNode returns a node from node MaxDepth topology // It returns nil if the peer was not found func (n *node) GetPeerNode(id string) *node { - n.RLock() - defer n.RUnlock() - // get node topology up to MaxDepth top := n.Topology(MaxDepth) From 3d5d9be02a494dcb1e7081571c7d920b3342aa0b Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 18 Oct 2019 11:23:28 +0100 Subject: [PATCH 105/344] Avoid recursive calls to RLock() Topology calls itsel recursively invoking RLock. This, according to go documentation is wrong. This commit moves the body of Topology function to a non-thread safe unexported function to keep locsk at check! --- network/node.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/network/node.go b/network/node.go index 194dd6d2..e8632ccc 100644 --- a/network/node.go +++ b/network/node.go @@ -237,12 +237,9 @@ func (n *node) PruneStalePeerNodes(pruneTime time.Duration) map[string]*node { return pruned } -// Topology returns a copy of the node topology down to given depth -// NOTE: the returned node is a node graph - not a single node -func (n *node) Topology(depth uint) *node { - n.RLock() - defer n.RUnlock() - +// getTopology traverses node graph and builds node topology +// NOTE: this function is not thread safe +func (n *node) getTopology(depth uint) *node { // make a copy of yourself node := &node{ id: n.id, @@ -262,7 +259,7 @@ func (n *node) Topology(depth uint) *node { // iterate through our peers and update the node peers for _, peer := range n.peers { - nodePeer := peer.Topology(depth) + nodePeer := peer.getTopology(depth) if _, ok := node.peers[nodePeer.id]; !ok { node.peers[nodePeer.id] = nodePeer } @@ -271,6 +268,15 @@ func (n *node) Topology(depth uint) *node { return node } +// Topology returns a copy of the node topology down to given depth +// NOTE: the returned node is a node graph - not a single node +func (n *node) Topology(depth uint) *node { + n.RLock() + defer n.RUnlock() + + return n.getTopology(depth) +} + // Peers returns node peers up to MaxDepth func (n *node) Peers() []Node { n.RLock() @@ -278,7 +284,7 @@ func (n *node) Peers() []Node { var peers []Node for _, nodePeer := range n.peers { - peer := nodePeer.Topology(MaxDepth) + peer := nodePeer.getTopology(MaxDepth) peers = append(peers, peer) } From a89d1edc419f54e568633d903a4ad7642daf6bf2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 19 Oct 2019 08:11:05 +0100 Subject: [PATCH 106/344] fix divide by zero bug --- broker/http_broker.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index c2ae4dda..3e9fbc54 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -560,11 +560,6 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) srv := func(s []*registry.Service, b []byte) { for _, service := range s { - // only process if we have nodes - if len(service.Nodes) == 0 { - continue - } - var nodes []*registry.Node for _, node := range service.Nodes { @@ -581,6 +576,11 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) nodes = append(nodes, node) } + // only process if we have nodes + if len(nodes) == 0 { + continue + } + switch service.Version { // broadcast version means broadcast to all nodes case broadcastVersion: From f792fac1cc6c8fe7db5be85cc44533e3ba872eaa Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 22 Oct 2019 11:53:49 +0100 Subject: [PATCH 107/344] Round robin routes we've sorted by metric --- proxy/mucp/mucp.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index ce02c6b6..b336e5f3 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -11,6 +11,7 @@ import ( "time" "github.com/micro/go-micro/client" + "github.com/micro/go-micro/client/selector" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/codec/bytes" "github.com/micro/go-micro/config/options" @@ -252,11 +253,18 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server routes = addr } + var opts []client.CallOption + + // set strategy to round robin + opts = append(opts, client.WithSelectOption(selector.WithStrategy(selector.RoundRobin))) + // if the address is already set just serve it // TODO: figure it out if we should know to pick a link if len(addresses) > 0 { + opts = append(opts, client.WithAddress(addresses...)) + // serve the normal way - return p.serveRequest(ctx, p.Client, service, endpoint, req, rsp, client.WithAddress(addresses...)) + return p.serveRequest(ctx, p.Client, service, endpoint, req, rsp, opts...) } // there's no links e.g we're local routing then just serve it with addresses @@ -288,9 +296,10 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server // set the address to call addresses := toNodes([]router.Route{route}) + opts = append(opts, client.WithAddress(addresses...)) // do the request with the link - gerr = p.serveRequest(ctx, link, service, endpoint, req, rsp, client.WithAddress(addresses...)) + gerr = p.serveRequest(ctx, link, service, endpoint, req, rsp, opts...) // return on no error since we succeeded if gerr == nil { return nil From 4fddd69229e30f5c693606a2e31bfbf61e0bfbb0 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 22 Oct 2019 16:50:00 +0100 Subject: [PATCH 108/344] Add placeholders for link metrics --- tunnel/link.go | 15 +++++++++++++++ tunnel/tunnel.go | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/tunnel/link.go b/tunnel/link.go index 181121e7..580c6abd 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -85,6 +85,21 @@ func (l *link) expiry() { } } +// Delay is the current load on the link +func (l *link) Delay() int64 { + return 0 +} + +// Transfer rate capability as bits per second (higher is better) +func (l *link) Rate() float64 { + return float64(10e8) +} + +// Length returns the roundtrip time as nanoseconds (lower is better) +func (l *link) Length() int64 { + return time.Second.Nanoseconds() +} + func (l *link) Id() string { l.RLock() defer l.RUnlock() diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index a2671f62..cc03f07f 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -59,6 +59,12 @@ type Link interface { Id() string // Status of the link e.g connected/closed Status() string + // Delay is the current load on the link + Delay() int64 + // Transfer rate capability as bits per second (higher is better) + Rate() float64 + // Length returns the roundtrip time as nanoseconds (lower is better) + Length() int64 // honours transport socket transport.Socket } From ab9fa20a50d145ee763084cadf5bc9c188771328 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 22 Oct 2019 16:53:47 +0100 Subject: [PATCH 109/344] Update comments --- tunnel/link.go | 2 +- tunnel/tunnel.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tunnel/link.go b/tunnel/link.go index 580c6abd..22362198 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -90,7 +90,7 @@ func (l *link) Delay() int64 { return 0 } -// Transfer rate capability as bits per second (higher is better) +// Current transfer rate as bits per second (lower is better) func (l *link) Rate() float64 { return float64(10e8) } diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index cc03f07f..9a52ffaf 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -59,9 +59,9 @@ type Link interface { Id() string // Status of the link e.g connected/closed Status() string - // Delay is the current load on the link + // Delay is the current load on the link (lower is better) Delay() int64 - // Transfer rate capability as bits per second (higher is better) + // Current transfer rate as bits per second (lower is better) Rate() float64 // Length returns the roundtrip time as nanoseconds (lower is better) Length() int64 From 85e273afa541937975e66c7e34546dc1f6e9cc7a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 22 Oct 2019 17:02:22 +0100 Subject: [PATCH 110/344] reorder methods --- tunnel/tunnel.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 9a52ffaf..73c937f3 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -57,14 +57,14 @@ type Tunnel interface { type Link interface { // The id of the link Id() string - // Status of the link e.g connected/closed - Status() string // Delay is the current load on the link (lower is better) Delay() int64 - // Current transfer rate as bits per second (lower is better) - Rate() float64 // Length returns the roundtrip time as nanoseconds (lower is better) Length() int64 + // Current transfer rate as bits per second (lower is better) + Rate() float64 + // Status of the link e.g connected/closed + Status() string // honours transport socket transport.Socket } From 407694232ab53489cd6a4c9b3149dc10fa2ca66b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 22 Oct 2019 18:43:09 +0100 Subject: [PATCH 111/344] Measure roundtrip times on link --- tunnel/default.go | 38 +++++++++++++++++++++++++++++++++++++- tunnel/link.go | 26 ++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index 73052581..5ba6b868 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -966,7 +966,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { c.mode = options.Mode // set the dial timeout c.timeout = options.Timeout - + // get the current time now := time.Now() after := func() time.Duration { @@ -980,6 +980,8 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { } var links []string + // did we measure the rtt + var measured bool // non multicast so we need to find the link if id := options.Link; id != "" { @@ -1021,6 +1023,9 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { // shit fuck if !c.discovered { + // piggy back roundtrip + nowRTT := time.Now() + // create a new discovery message for this channel msg := c.newMessage("discover") msg.mode = Broadcast @@ -1075,12 +1080,31 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { return nil, err } + // set roundtrip + d := time.Since(nowRTT) + + // set the link time + t.RLock() + link, ok := t.links[msg.link] + t.RUnlock() + + if ok { + // set the rountrip time + link.setRTT(d) + } + + // set measured to true + measured = true + // set discovered to true c.discovered = true } // a unicast session so we call "open" and wait for an "accept" + // reset now in case we use it + now = time.Now() + // try to open the session err := c.Open() if err != nil { @@ -1089,6 +1113,18 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { return nil, err } + // if we haven't measured the roundtrip do it now + if !measured && c.mode == Unicast { + // set the link time + t.RLock() + link, ok := t.links[c.link] + t.RUnlock() + if ok { + // set the rountrip time + link.setRTT(time.Since(now)) + } + } + return c, nil } diff --git a/tunnel/link.go b/tunnel/link.go index 22362198..91636075 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -32,6 +32,9 @@ type link struct { // channels keeps a mapping of channels and last seen channels map[string]time.Time + // the weighed moving average roundtrip + rtt int64 + // keep an error count on the link errCount int } @@ -48,6 +51,21 @@ func newLink(s transport.Socket) *link { return l } +func (l *link) setRTT(d time.Duration) { + l.Lock() + defer l.Unlock() + + if l.rtt < 0 { + l.rtt = d.Nanoseconds() + return + } + + // https://fishi.devtail.io/weblog/2015/04/12/measuring-bandwidth-and-round-trip-time-tcp-connection-inside-application-layer/ + rtt := 0.8*float64(l.rtt) + 0.2*float64(d.Nanoseconds()) + // set new rtt + l.rtt = int64(rtt) +} + // watches the channel expiry func (l *link) expiry() { t := time.NewTicker(time.Minute) @@ -95,9 +113,13 @@ func (l *link) Rate() float64 { return float64(10e8) } -// Length returns the roundtrip time as nanoseconds (lower is better) +// Length returns the roundtrip time as nanoseconds (lower is better). +// Returns 0 where no measurement has been taken. func (l *link) Length() int64 { - return time.Second.Nanoseconds() + l.RLock() + defer l.RUnlock() + + return l.rtt } func (l *link) Id() string { From d64f8c665ea617a003d56c9cc50e66cb1cf03c25 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 22 Oct 2019 19:38:29 +0100 Subject: [PATCH 112/344] add rate measure --- tunnel/default.go | 7 +++--- tunnel/link.go | 43 ++++++++++++++++++++++++++++++++++--- tunnel/tunnel_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 7 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index 5ba6b868..6cc48d3c 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -1085,17 +1085,16 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { // set the link time t.RLock() - link, ok := t.links[msg.link] + link, ok := t.links[c.link] t.RUnlock() if ok { // set the rountrip time link.setRTT(d) + // set measured to true + measured = true } - // set measured to true - measured = true - // set discovered to true c.discovered = true } diff --git a/tunnel/link.go b/tunnel/link.go index 91636075..d5c044b9 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -32,9 +32,12 @@ type link struct { // channels keeps a mapping of channels and last seen channels map[string]time.Time - // the weighed moving average roundtrip + // the weighted moving average roundtrip rtt int64 + // weighted moving average of bits flowing + rate float64 + // keep an error count on the link errCount int } @@ -55,7 +58,7 @@ func (l *link) setRTT(d time.Duration) { l.Lock() defer l.Unlock() - if l.rtt < 0 { + if l.rtt <= 0 { l.rtt = d.Nanoseconds() return } @@ -110,7 +113,9 @@ func (l *link) Delay() int64 { // Current transfer rate as bits per second (lower is better) func (l *link) Rate() float64 { - return float64(10e8) + l.RLock() + defer l.RUnlock() + return l.rate } // Length returns the roundtrip time as nanoseconds (lower is better). @@ -141,11 +146,43 @@ func (l *link) Close() error { } func (l *link) Send(m *transport.Message) error { + dataSent := len(m.Body) + + // set header length + for k, v := range m.Header { + dataSent += (len(k) + len(v)) + } + + // get time now + now := time.Now() + + // send the message err := l.Socket.Send(m) l.Lock() defer l.Unlock() + // calculate based on data + if dataSent > 0 { + // measure time taken + delta := time.Since(now) + + // bit sent + bits := dataSent * 1024 + + // rate of send in bits per nanosecond + rate := float64(bits) / float64(delta.Nanoseconds()) + + // + if l.rate == 0 { + // rate per second + l.rate = rate * 1e9 + } else { + // set new rate per second + l.rate = 0.8*l.rate + 0.2*(rate*1e9) + } + } + // if theres no error reset the counter if err == nil { l.errCount = 0 diff --git a/tunnel/tunnel_test.go b/tunnel/tunnel_test.go index fc76421b..a06a1b01 100644 --- a/tunnel/tunnel_test.go +++ b/tunnel/tunnel_test.go @@ -292,3 +292,53 @@ func TestReconnectTunnel(t *testing.T) { // wait until done wg.Wait() } + +func TestTunnelRTTRate(t *testing.T) { + // create a new tunnel client + tunA := NewTunnel( + Address("127.0.0.1:9096"), + Nodes("127.0.0.1:9097"), + ) + + // create a new tunnel server + tunB := NewTunnel( + Address("127.0.0.1:9097"), + ) + + // start tunB + err := tunB.Connect() + if err != nil { + t.Fatal(err) + } + defer tunB.Close() + + // start tunA + err = tunA.Connect() + if err != nil { + t.Fatal(err) + } + defer tunA.Close() + + wait := make(chan bool) + + var wg sync.WaitGroup + + wg.Add(1) + // start the listener + go testAccept(t, tunB, wait, &wg) + + wg.Add(1) + // start the client + go testSend(t, tunA, wait, &wg) + + // wait until done + wg.Wait() + + for _, link := range tunA.Links() { + t.Logf("Link %s length %v rate %v", link.Id(), link.Length(), link.Rate()) + } + + for _, link := range tunB.Links() { + t.Logf("Link %s length %v rate %v", link.Id(), link.Length(), link.Rate()) + } +} From 5ac58651542503847cae9aba50a97925b1fa5847 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 10:55:53 +0100 Subject: [PATCH 113/344] add comment --- tunnel/link.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tunnel/link.go b/tunnel/link.go index d5c044b9..909ad489 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -173,7 +173,7 @@ func (l *link) Send(m *transport.Message) error { // rate of send in bits per nanosecond rate := float64(bits) / float64(delta.Nanoseconds()) - // + // default the rate if its zero if l.rate == 0 { // rate per second l.rate = rate * 1e9 From d4832e8f34492e6729bad1018452e11cd1790ce2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 15:53:28 +0100 Subject: [PATCH 114/344] Remove consul registry (#818) --- config/cmd/cmd.go | 4 +- registry/consul/consul.go | 438 ------------------------------- registry/consul/encoding.go | 170 ------------ registry/consul/encoding_test.go | 147 ----------- registry/consul/options.go | 81 ------ registry/consul/registry_test.go | 208 --------------- registry/consul/watcher.go | 290 -------------------- registry/consul/watcher_test.go | 86 ------ 8 files changed, 1 insertion(+), 1423 deletions(-) delete mode 100644 registry/consul/consul.go delete mode 100644 registry/consul/encoding.go delete mode 100644 registry/consul/encoding_test.go delete mode 100644 registry/consul/options.go delete mode 100644 registry/consul/registry_test.go delete mode 100644 registry/consul/watcher.go delete mode 100644 registry/consul/watcher_test.go diff --git a/config/cmd/cmd.go b/config/cmd/cmd.go index 6cb6835b..a99557d2 100644 --- a/config/cmd/cmd.go +++ b/config/cmd/cmd.go @@ -27,7 +27,6 @@ import ( // registries "github.com/micro/go-micro/registry" - "github.com/micro/go-micro/registry/consul" "github.com/micro/go-micro/registry/etcd" "github.com/micro/go-micro/registry/mdns" rmem "github.com/micro/go-micro/registry/memory" @@ -155,7 +154,7 @@ var ( cli.StringFlag{ Name: "registry", EnvVar: "MICRO_REGISTRY", - Usage: "Registry for discovery. consul, etcd, mdns", + Usage: "Registry for discovery. etcd, mdns", }, cli.StringFlag{ Name: "registry_address", @@ -196,7 +195,6 @@ var ( DefaultRegistries = map[string]func(...registry.Option) registry.Registry{ "go.micro.registry": regSrv.NewRegistry, "service": regSrv.NewRegistry, - "consul": consul.NewRegistry, "etcd": etcd.NewRegistry, "mdns": mdns.NewRegistry, "memory": rmem.NewRegistry, diff --git a/registry/consul/consul.go b/registry/consul/consul.go deleted file mode 100644 index 152aae69..00000000 --- a/registry/consul/consul.go +++ /dev/null @@ -1,438 +0,0 @@ -package consul - -import ( - "crypto/tls" - "errors" - "fmt" - "net" - "net/http" - "runtime" - "strconv" - "sync" - "time" - - consul "github.com/hashicorp/consul/api" - "github.com/micro/go-micro/registry" - mnet "github.com/micro/go-micro/util/net" - hash "github.com/mitchellh/hashstructure" -) - -type consulRegistry struct { - Address []string - opts registry.Options - - client *consul.Client - config *consul.Config - - // 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 - var addrs []string - - // iterate the options addresses - for _, address := range c.opts.Addrs { - // check we have a port - addr, port, err := net.SplitHostPort(address) - if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { - port = "8500" - addr = address - addrs = append(addrs, net.JoinHostPort(addr, port)) - } else if err == nil { - addrs = append(addrs, net.JoinHostPort(addr, port)) - } - } - - // set the addrs - if len(addrs) > 0 { - c.Address = addrs - config.Address = c.Address[0] - } - - if config.HttpClient == nil { - config.HttpClient = new(http.Client) - } - - // 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) - } - - // set timeout - if c.opts.Timeout > 0 { - config.HttpClient.Timeout = c.opts.Timeout - } - - // set the config - c.config = config - - // remove client - c.client = nil - - // setup the client - c.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: node.Address, - 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), - } - } - - host, pt, _ := net.SplitHostPort(node.Address) - if host == "" { - host = node.Address - } - port, _ := strconv.Atoi(pt) - - // register the service - asr := &consul.AgentServiceRegistration{ - ID: node.Id, - Name: s.Name, - Tags: tags, - Port: port, - Address: host, - 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: mnet.HostPort(address, 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 (c *consulRegistry) Client() *consul.Client { - if c.client != nil { - return c.client - } - - for _, addr := range c.Address { - // set the address - c.config.Address = addr - - // create a new client - tmpClient, _ := consul.NewClient(c.config) - - // test the client - _, err := tmpClient.Agent().Host() - if err != nil { - continue - } - - // set the client - c.client = tmpClient - return c.client - } - - // set the default - c.client, _ = consul.NewClient(c.config) - - // return the client - return c.client -} - -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 deleted file mode 100644 index 8a152683..00000000 --- a/registry/consul/encoding.go +++ /dev/null @@ -1,170 +0,0 @@ -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 deleted file mode 100644 index 7f511174..00000000 --- a/registry/consul/encoding_test.go +++ /dev/null @@ -1,147 +0,0 @@ -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/options.go b/registry/consul/options.go deleted file mode 100644 index 29bc3ee5..00000000 --- a/registry/consul/options.go +++ /dev/null @@ -1,81 +0,0 @@ -package consul - -import ( - "context" - "time" - - consul "github.com/hashicorp/consul/api" - "github.com/micro/go-micro/registry" -) - -// Connect specifies services should be registered as Consul Connect services -func Connect() registry.Option { - return func(o *registry.Options) { - if o.Context == nil { - o.Context = context.Background() - } - o.Context = context.WithValue(o.Context, "consul_connect", true) - } -} - -func Config(c *consul.Config) registry.Option { - return func(o *registry.Options) { - if o.Context == nil { - o.Context = context.Background() - } - o.Context = context.WithValue(o.Context, "consul_config", c) - } -} - -// 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. -// See `TCP + Interval` for more information [1]. -// -// [1] https://www.consul.io/docs/agent/checks.html -// -func TCPCheck(t time.Duration) registry.Option { - return func(o *registry.Options) { - if t <= time.Duration(0) { - return - } - if o.Context == nil { - o.Context = context.Background() - } - o.Context = context.WithValue(o.Context, "consul_tcp_check", t) - } -} diff --git a/registry/consul/registry_test.go b/registry/consul/registry_test.go deleted file mode 100644 index 3a275030..00000000 --- a/registry/consul/registry_test.go +++ /dev/null @@ -1,208 +0,0 @@ -package consul - -import ( - "bytes" - "encoding/json" - "errors" - "net" - "net/http" - "testing" - "time" - - consul "github.com/hashicorp/consul/api" - "github.com/micro/go-micro/registry" -) - -type mockRegistry struct { - body []byte - status int - err error - url string -} - -func encodeData(obj interface{}) ([]byte, error) { - buf := bytes.NewBuffer(nil) - enc := json.NewEncoder(buf) - if err := enc.Encode(obj); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -func newMockServer(rg *mockRegistry, l net.Listener) error { - mux := http.NewServeMux() - mux.HandleFunc(rg.url, func(w http.ResponseWriter, r *http.Request) { - if rg.err != nil { - http.Error(w, rg.err.Error(), 500) - return - } - w.WriteHeader(rg.status) - w.Write(rg.body) - }) - return http.Serve(l, mux) -} - -func newConsulTestRegistry(r *mockRegistry) (*consulRegistry, func()) { - l, err := net.Listen("tcp", "localhost:0") - if err != nil { - // blurgh?!! - panic(err.Error()) - } - cfg := consul.DefaultConfig() - cfg.Address = l.Addr().String() - - go newMockServer(r, l) - - var cr = &consulRegistry{ - config: cfg, - Address: []string{cfg.Address}, - opts: registry.Options{}, - register: make(map[string]uint64), - lastChecked: make(map[string]time.Time), - queryOptions: &consul.QueryOptions{ - AllowStale: true, - }, - } - cr.Client() - - return cr, func() { - l.Close() - } -} - -func newServiceList(svc []*consul.ServiceEntry) []byte { - bts, _ := encodeData(svc) - return bts -} - -func TestConsul_GetService_WithError(t *testing.T) { - cr, cl := newConsulTestRegistry(&mockRegistry{ - err: errors.New("client-error"), - url: "/v1/health/service/service-name", - }) - defer cl() - - if _, err := cr.GetService("test-service"); err == nil { - t.Fatalf("Expected error not to be `nil`") - } -} - -func TestConsul_GetService_WithHealthyServiceNodes(t *testing.T) { - // warning is still seen as healthy, critical is not - svcs := []*consul.ServiceEntry{ - newServiceEntry( - "node-name-1", "node-address-1", "service-name", "v1.0.0", - []*consul.HealthCheck{ - newHealthCheck("node-name-1", "service-name", "passing"), - newHealthCheck("node-name-1", "service-name", "warning"), - }, - ), - newServiceEntry( - "node-name-2", "node-address-2", "service-name", "v1.0.0", - []*consul.HealthCheck{ - newHealthCheck("node-name-2", "service-name", "passing"), - newHealthCheck("node-name-2", "service-name", "warning"), - }, - ), - } - - cr, cl := newConsulTestRegistry(&mockRegistry{ - status: 200, - body: newServiceList(svcs), - url: "/v1/health/service/service-name", - }) - defer cl() - - svc, err := cr.GetService("service-name") - if err != nil { - t.Fatal("Unexpected error", err) - } - - if exp, act := 1, len(svc); exp != act { - t.Fatalf("Expected len of svc to be `%d`, got `%d`.", exp, act) - } - - if exp, act := 2, len(svc[0].Nodes); exp != act { - t.Fatalf("Expected len of nodes to be `%d`, got `%d`.", exp, act) - } -} - -func TestConsul_GetService_WithUnhealthyServiceNode(t *testing.T) { - // warning is still seen as healthy, critical is not - svcs := []*consul.ServiceEntry{ - newServiceEntry( - "node-name-1", "node-address-1", "service-name", "v1.0.0", - []*consul.HealthCheck{ - newHealthCheck("node-name-1", "service-name", "passing"), - newHealthCheck("node-name-1", "service-name", "warning"), - }, - ), - newServiceEntry( - "node-name-2", "node-address-2", "service-name", "v1.0.0", - []*consul.HealthCheck{ - newHealthCheck("node-name-2", "service-name", "passing"), - newHealthCheck("node-name-2", "service-name", "critical"), - }, - ), - } - - cr, cl := newConsulTestRegistry(&mockRegistry{ - status: 200, - body: newServiceList(svcs), - url: "/v1/health/service/service-name", - }) - defer cl() - - svc, err := cr.GetService("service-name") - if err != nil { - t.Fatal("Unexpected error", err) - } - - if exp, act := 1, len(svc); exp != act { - t.Fatalf("Expected len of svc to be `%d`, got `%d`.", exp, act) - } - - if exp, act := 1, len(svc[0].Nodes); exp != act { - t.Fatalf("Expected len of nodes to be `%d`, got `%d`.", exp, act) - } -} - -func TestConsul_GetService_WithUnhealthyServiceNodes(t *testing.T) { - // warning is still seen as healthy, critical is not - svcs := []*consul.ServiceEntry{ - newServiceEntry( - "node-name-1", "node-address-1", "service-name", "v1.0.0", - []*consul.HealthCheck{ - newHealthCheck("node-name-1", "service-name", "passing"), - newHealthCheck("node-name-1", "service-name", "critical"), - }, - ), - newServiceEntry( - "node-name-2", "node-address-2", "service-name", "v1.0.0", - []*consul.HealthCheck{ - newHealthCheck("node-name-2", "service-name", "passing"), - newHealthCheck("node-name-2", "service-name", "critical"), - }, - ), - } - - cr, cl := newConsulTestRegistry(&mockRegistry{ - status: 200, - body: newServiceList(svcs), - url: "/v1/health/service/service-name", - }) - defer cl() - - svc, err := cr.GetService("service-name") - if err != nil { - t.Fatal("Unexpected error", err) - } - - if exp, act := 1, len(svc); exp != act { - t.Fatalf("Expected len of svc to be `%d`, got `%d`.", exp, act) - } - - if exp, act := 0, len(svc[0].Nodes); exp != act { - t.Fatalf("Expected len of nodes to be `%d`, got `%d`.", exp, act) - } -} diff --git a/registry/consul/watcher.go b/registry/consul/watcher.go deleted file mode 100644 index 62829136..00000000 --- a/registry/consul/watcher.go +++ /dev/null @@ -1,290 +0,0 @@ -package consul - -import ( - "fmt" - "log" - "os" - "sync" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/api/watch" - "github.com/micro/go-micro/registry" -) - -type consulWatcher struct { - r *consulRegistry - wo registry.WatchOptions - wp *watch.Plan - watchers map[string]*watch.Plan - - next chan *registry.Result - exit chan bool - - sync.RWMutex - services map[string][]*registry.Service -} - -func newConsulWatcher(cr *consulRegistry, opts ...registry.WatchOption) (registry.Watcher, error) { - var wo registry.WatchOptions - for _, o := range opts { - o(&wo) - } - - cw := &consulWatcher{ - r: cr, - wo: wo, - exit: make(chan bool), - next: make(chan *registry.Result, 10), - watchers: make(map[string]*watch.Plan), - services: make(map[string][]*registry.Service), - } - - wp, err := watch.Parse(map[string]interface{}{"type": "services"}) - if err != nil { - return nil, err - } - - wp.Handler = cw.handle - go wp.RunWithClientAndLogger(cr.Client(), log.New(os.Stderr, "", log.LstdFlags)) - cw.wp = wp - - return cw, nil -} - -func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { - entries, ok := data.([]*api.ServiceEntry) - if !ok { - return - } - - serviceMap := map[string]*registry.Service{} - serviceName := "" - - for _, e := range entries { - serviceName = e.Service.Service - // version is now a tag - version, _ := decodeVersion(e.Service.Tags) - // service ID is now the node id - id := e.Service.ID - // key is always the version - key := version - // address is service address - address := e.Service.Address - - // use node address - if len(address) == 0 { - address = e.Node.Address - } - - svc, ok := serviceMap[key] - if !ok { - svc = ®istry.Service{ - Endpoints: decodeEndpoints(e.Service.Tags), - Name: e.Service.Service, - Version: version, - } - serviceMap[key] = svc - } - - var del bool - - for _, check := range e.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: fmt.Sprintf("%s:%d", address, e.Service.Port), - Metadata: decodeMetadata(e.Service.Tags), - }) - } - - cw.RLock() - // make a copy - rservices := make(map[string][]*registry.Service) - for k, v := range cw.services { - rservices[k] = v - } - cw.RUnlock() - - var newServices []*registry.Service - - // serviceMap is the new set of services keyed by name+version - for _, newService := range serviceMap { - // append to the new set of cached services - newServices = append(newServices, newService) - - // check if the service exists in the existing cache - oldServices, ok := rservices[serviceName] - if !ok { - // does not exist? then we're creating brand new entries - cw.next <- ®istry.Result{Action: "create", Service: newService} - continue - } - - // service exists. ok let's figure out what to update and delete version wise - action := "create" - - for _, oldService := range oldServices { - // does this version exist? - // no? then default to create - if oldService.Version != newService.Version { - continue - } - - // yes? then it's an update - action = "update" - - var nodes []*registry.Node - // check the old nodes to see if they've been deleted - for _, oldNode := range oldService.Nodes { - var seen bool - for _, newNode := range newService.Nodes { - if newNode.Id == oldNode.Id { - seen = true - break - } - } - // does the old node exist in the new set of nodes - // no? then delete that shit - if !seen { - nodes = append(nodes, oldNode) - } - } - - // it's an update rather than creation - if len(nodes) > 0 { - delService := registry.CopyService(oldService) - delService.Nodes = nodes - cw.next <- ®istry.Result{Action: "delete", Service: delService} - } - } - - cw.next <- ®istry.Result{Action: action, Service: newService} - } - - // Now check old versions that may not be in new services map - for _, old := range rservices[serviceName] { - // old version does not exist in new version map - // kill it with fire! - if _, ok := serviceMap[old.Version]; !ok { - cw.next <- ®istry.Result{Action: "delete", Service: old} - } - } - - cw.Lock() - cw.services[serviceName] = newServices - cw.Unlock() -} - -func (cw *consulWatcher) handle(idx uint64, data interface{}) { - services, ok := data.(map[string][]string) - if !ok { - return - } - - // add new watchers - for service, _ := range services { - // Filter on watch options - // wo.Service: Only watch services we care about - if len(cw.wo.Service) > 0 && service != cw.wo.Service { - continue - } - - if _, ok := cw.watchers[service]; ok { - continue - } - wp, err := watch.Parse(map[string]interface{}{ - "type": "service", - "service": service, - }) - if err == nil { - wp.Handler = cw.serviceHandler - 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}} - } - } - - cw.RLock() - // make a copy - rservices := make(map[string][]*registry.Service) - for k, v := range cw.services { - rservices[k] = v - } - cw.RUnlock() - - // remove unknown services from registry - // save the things we want to delete - deleted := make(map[string][]*registry.Service) - - for service, _ := range rservices { - if _, ok := services[service]; !ok { - cw.Lock() - // save this before deleting - deleted[service] = cw.services[service] - delete(cw.services, service) - cw.Unlock() - } - } - - // remove unknown services from watchers - for service, w := range cw.watchers { - if _, ok := services[service]; !ok { - w.Stop() - delete(cw.watchers, service) - for _, oldService := range deleted[service] { - // send a delete for the service nodes that we're removing - cw.next <- ®istry.Result{Action: "delete", Service: oldService} - } - // sent the empty list as the last resort to indicate to delete the entire service - cw.next <- ®istry.Result{Action: "delete", Service: ®istry.Service{Name: service}} - } - } -} - -func (cw *consulWatcher) Next() (*registry.Result, error) { - select { - case <-cw.exit: - return nil, registry.ErrWatcherStopped - case r, ok := <-cw.next: - if !ok { - return nil, registry.ErrWatcherStopped - } - return r, nil - } - // NOTE: This is a dead code path: e.g. it will never be reached - // as we return in all previous code paths never leading to this return - return nil, registry.ErrWatcherStopped -} - -func (cw *consulWatcher) Stop() { - select { - case <-cw.exit: - return - default: - close(cw.exit) - if cw.wp == nil { - return - } - cw.wp.Stop() - - // drain results - for { - select { - case <-cw.next: - default: - return - } - } - } -} diff --git a/registry/consul/watcher_test.go b/registry/consul/watcher_test.go deleted file mode 100644 index 19e0cb80..00000000 --- a/registry/consul/watcher_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package consul - -import ( - "testing" - - "github.com/hashicorp/consul/api" - "github.com/micro/go-micro/registry" -) - -func TestHealthyServiceHandler(t *testing.T) { - watcher := newWatcher() - serviceEntry := newServiceEntry( - "node-name", "node-address", "service-name", "v1.0.0", - []*api.HealthCheck{ - newHealthCheck("node-name", "service-name", "passing"), - }, - ) - - watcher.serviceHandler(1234, []*api.ServiceEntry{serviceEntry}) - - if len(watcher.services["service-name"][0].Nodes) != 1 { - t.Errorf("Expected length of the service nodes to be 1") - } -} - -func TestUnhealthyServiceHandler(t *testing.T) { - watcher := newWatcher() - serviceEntry := newServiceEntry( - "node-name", "node-address", "service-name", "v1.0.0", - []*api.HealthCheck{ - newHealthCheck("node-name", "service-name", "critical"), - }, - ) - - watcher.serviceHandler(1234, []*api.ServiceEntry{serviceEntry}) - - if len(watcher.services["service-name"][0].Nodes) != 0 { - t.Errorf("Expected length of the service nodes to be 0") - } -} - -func TestUnhealthyNodeServiceHandler(t *testing.T) { - watcher := newWatcher() - serviceEntry := newServiceEntry( - "node-name", "node-address", "service-name", "v1.0.0", - []*api.HealthCheck{ - newHealthCheck("node-name", "service-name", "passing"), - newHealthCheck("node-name", "serfHealth", "critical"), - }, - ) - - watcher.serviceHandler(1234, []*api.ServiceEntry{serviceEntry}) - - if len(watcher.services["service-name"][0].Nodes) != 0 { - t.Errorf("Expected length of the service nodes to be 0") - } -} - -func newWatcher() *consulWatcher { - return &consulWatcher{ - exit: make(chan bool), - next: make(chan *registry.Result, 10), - services: make(map[string][]*registry.Service), - } -} - -func newHealthCheck(node, name, status string) *api.HealthCheck { - return &api.HealthCheck{ - Node: node, - Name: name, - Status: status, - ServiceName: name, - } -} - -func newServiceEntry(node, address, name, version string, checks []*api.HealthCheck) *api.ServiceEntry { - return &api.ServiceEntry{ - Node: &api.Node{Node: node, Address: name}, - Service: &api.AgentService{ - Service: name, - Address: address, - Tags: encodeVersion(version), - }, - Checks: checks, - } -} From 842fc0156869a5210732c8e05f911a5558457a19 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 16:05:21 +0100 Subject: [PATCH 115/344] add send/recv queues for link --- tunnel/default.go | 2 +- tunnel/link.go | 228 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 170 insertions(+), 60 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index 6cc48d3c..448fa3f1 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -427,7 +427,7 @@ func (t *tun) listen(link *link) { // process anything via the net interface msg := new(transport.Message) if err := link.Recv(msg); err != nil { - log.Debugf("Tunnel link %s receive error: %#v", link.Remote(), err) + log.Debugf("Tunnel link %s receive error: %v", link.Remote(), err) return } diff --git a/tunnel/link.go b/tunnel/link.go index 909ad489..fd1e3ad9 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -1,6 +1,7 @@ package tunnel import ( + "io" "sync" "time" @@ -14,6 +15,10 @@ type link struct { sync.RWMutex // stops the link closed chan bool + // send queue + sendQueue chan *packet + // receive queue + recvQueue chan *packet // unique id of this link e.g uuid // which we define for ourselves id string @@ -31,25 +36,37 @@ type link struct { lastKeepAlive time.Time // channels keeps a mapping of channels and last seen channels map[string]time.Time - // the weighted moving average roundtrip - rtt int64 - + length int64 // weighted moving average of bits flowing rate float64 - // keep an error count on the link errCount int } +// packet send over link +type packet struct { + // message to send or received + message *transport.Message + + // status returned when sent + status chan error + + // receive related error + err error +} + func newLink(s transport.Socket) *link { l := &link{ Socket: s, id: uuid.New().String(), - channels: make(map[string]time.Time), - closed: make(chan bool), lastKeepAlive: time.Now(), + closed: make(chan bool), + channels: make(map[string]time.Time), + sendQueue: make(chan *packet, 128), + recvQueue: make(chan *packet, 128), } + go l.process() go l.expiry() return l } @@ -58,15 +75,51 @@ func (l *link) setRTT(d time.Duration) { l.Lock() defer l.Unlock() - if l.rtt <= 0 { - l.rtt = d.Nanoseconds() + if l.length <= 0 { + l.length = d.Nanoseconds() return } // https://fishi.devtail.io/weblog/2015/04/12/measuring-bandwidth-and-round-trip-time-tcp-connection-inside-application-layer/ - rtt := 0.8*float64(l.rtt) + 0.2*float64(d.Nanoseconds()) - // set new rtt - l.rtt = int64(rtt) + length := 0.8*float64(l.length) + 0.2*float64(d.Nanoseconds()) + // set new length + l.length = int64(length) +} + +// process deals with the send queue +func (l *link) process() { + // receive messages + go func() { + for { + m := new(transport.Message) + err := l.recv(m) + if err != nil { + l.Lock() + l.errCount++ + l.Unlock() + } + + // process new received message + + select { + case l.recvQueue <- &packet{message: m, err: err}: + case <-l.closed: + return + } + } + }() + + // send messages + + for { + select { + case pk := <-l.sendQueue: + // send the message + pk.status <- l.send(pk.message) + case <-l.closed: + return + } + } } // watches the channel expiry @@ -106,46 +159,7 @@ func (l *link) expiry() { } } -// Delay is the current load on the link -func (l *link) Delay() int64 { - return 0 -} - -// Current transfer rate as bits per second (lower is better) -func (l *link) Rate() float64 { - l.RLock() - defer l.RUnlock() - return l.rate -} - -// Length returns the roundtrip time as nanoseconds (lower is better). -// Returns 0 where no measurement has been taken. -func (l *link) Length() int64 { - l.RLock() - defer l.RUnlock() - - return l.rtt -} - -func (l *link) Id() string { - l.RLock() - defer l.RUnlock() - - return l.id -} - -func (l *link) Close() error { - select { - case <-l.closed: - return nil - default: - close(l.closed) - } - - return nil -} - -func (l *link) Send(m *transport.Message) error { +func (l *link) send(m *transport.Message) error { dataSent := len(m.Body) // set header length @@ -162,6 +176,15 @@ func (l *link) Send(m *transport.Message) error { l.Lock() defer l.Unlock() + // there's an error increment the counter and bail + if err != nil { + l.errCount++ + return err + } + + // reset the counter + l.errCount = 0 + // calculate based on data if dataSent > 0 { // measure time taken @@ -183,17 +206,104 @@ func (l *link) Send(m *transport.Message) error { } } - // if theres no error reset the counter - if err == nil { - l.errCount = 0 - } - - // otherwise increment the counter - l.errCount++ - return err } +// recv a message on the link +func (l *link) recv(m *transport.Message) error { + if m.Header == nil { + m.Header = make(map[string]string) + } + + // TODO measure the receive latency if possible + + // receive the transport message + return l.Socket.Recv(m) +} + +// Delay is the current load on the link +func (l *link) Delay() int64 { + return int64(len(l.sendQueue) + len(l.recvQueue)) +} + +// Current transfer rate as bits per second (lower is better) +func (l *link) Rate() float64 { + l.RLock() + defer l.RUnlock() + + return l.rate +} + +// Length returns the roundtrip time as nanoseconds (lower is better). +// Returns 0 where no measurement has been taken. +func (l *link) Length() int64 { + l.RLock() + defer l.RUnlock() + + return l.length +} + +func (l *link) Id() string { + l.RLock() + defer l.RUnlock() + + return l.id +} + +func (l *link) Close() error { + select { + case <-l.closed: + return nil + default: + close(l.closed) + } + + return nil +} + +// Send sencs a message on the link +func (l *link) Send(m *transport.Message) error { + // create a new packet to send over the link + p := &packet{ + message: m, + status: make(chan error, 1), + } + + select { + case <-l.closed: + return io.EOF + case l.sendQueue <- p: + // in the send queue + } + + // wait for response + select { + case <-l.closed: + return io.EOF + case err := <-p.status: + return err + } + + // never reached + return nil +} + +// Accept accepts a message on the socket +func (l *link) Recv(m *transport.Message) error { + select { + case <-l.closed: + return io.EOF + case pk := <-l.recvQueue: + // check the packet receive error + if pk.err != nil { + return pk.err + } + *m = *pk.message + } + return nil +} + +// Status can return connected, closed, error func (l *link) Status() string { select { case <-l.closed: From fe180148a1ffa74e11cc310e3eef3a793053a673 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 16:15:39 +0100 Subject: [PATCH 116/344] rearrange where we account for errors and data sent --- tunnel/link.go | 101 +++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/tunnel/link.go b/tunnel/link.go index fd1e3ad9..06871a13 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -160,53 +160,11 @@ func (l *link) expiry() { } func (l *link) send(m *transport.Message) error { - dataSent := len(m.Body) - - // set header length - for k, v := range m.Header { - dataSent += (len(k) + len(v)) + if m.Header == nil { + m.Header = make(map[string]string) } - - // get time now - now := time.Now() - // send the message - err := l.Socket.Send(m) - - l.Lock() - defer l.Unlock() - - // there's an error increment the counter and bail - if err != nil { - l.errCount++ - return err - } - - // reset the counter - l.errCount = 0 - - // calculate based on data - if dataSent > 0 { - // measure time taken - delta := time.Since(now) - - // bit sent - bits := dataSent * 1024 - - // rate of send in bits per nanosecond - rate := float64(bits) / float64(delta.Nanoseconds()) - - // default the rate if its zero - if l.rate == 0 { - // rate per second - l.rate = rate * 1e9 - } else { - // set new rate per second - l.rate = 0.8*l.rate + 0.2*(rate*1e9) - } - } - - return err + return l.Socket.Send(m) } // recv a message on the link @@ -214,9 +172,6 @@ func (l *link) recv(m *transport.Message) error { if m.Header == nil { m.Header = make(map[string]string) } - - // TODO measure the receive latency if possible - // receive the transport message return l.Socket.Recv(m) } @@ -269,6 +224,10 @@ func (l *link) Send(m *transport.Message) error { status: make(chan error, 1), } + // get time now + now := time.Now() + + // queue the message select { case <-l.closed: return io.EOF @@ -276,15 +235,57 @@ func (l *link) Send(m *transport.Message) error { // in the send queue } + // error to use + var err error + // wait for response select { case <-l.closed: return io.EOF - case err := <-p.status: + case err = <-p.status: + } + + l.Lock() + defer l.Unlock() + + // there's an error increment the counter and bail + if err != nil { + l.errCount++ return err } - // never reached + // reset the counter + l.errCount = 0 + + // calculate the data sent + dataSent := len(m.Body) + + // set header length + for k, v := range m.Header { + dataSent += (len(k) + len(v)) + } + + // calculate based on data + if dataSent > 0 { + // measure time taken + delta := time.Since(now) + + // bit sent + bits := dataSent * 1024 + + // rate of send in bits per nanosecond + rate := float64(bits) / float64(delta.Nanoseconds()) + + // default the rate if its zero + if l.rate == 0 { + // rate per second + l.rate = rate * 1e9 + } else { + // set new rate per second + l.rate = 0.8*l.rate + 0.2*(rate*1e9) + } + } + return nil } From bf4a73d5c0c3fffbbe81db7b0e0299cbd3d637f9 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 16:39:26 +0100 Subject: [PATCH 117/344] Close the socket in the link --- tunnel/link.go | 22 ++++++++++++++++++++-- tunnel/tunnel_test.go | 8 ++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/tunnel/link.go b/tunnel/link.go index 06871a13..036a4830 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -210,6 +210,7 @@ func (l *link) Close() error { case <-l.closed: return nil default: + l.Socket.Close() close(l.closed) } @@ -227,12 +228,19 @@ func (l *link) Send(m *transport.Message) error { // get time now now := time.Now() - // queue the message + // check if its closed first select { case <-l.closed: return io.EOF + default: + } + + // queue the message + select { case l.sendQueue <- p: // in the send queue + case <-l.closed: + return io.EOF } // error to use @@ -293,7 +301,17 @@ func (l *link) Send(m *transport.Message) error { func (l *link) Recv(m *transport.Message) error { select { case <-l.closed: - return io.EOF + // check if there's any messages left + select { + case pk := <-l.recvQueue: + // check the packet receive error + if pk.err != nil { + return pk.err + } + *m = *pk.message + default: + return io.EOF + } case pk := <-l.recvQueue: // check the packet receive error if pk.err != nil { diff --git a/tunnel/tunnel_test.go b/tunnel/tunnel_test.go index a06a1b01..e884e692 100644 --- a/tunnel/tunnel_test.go +++ b/tunnel/tunnel_test.go @@ -202,8 +202,8 @@ func testBrokenTunAccept(t *testing.T, tun Tunnel, wait chan bool, wg *sync.Wait t.Fatal(err) } - // notify sender we have received the message - <-wait + // notify the sender we have received + wait <- true } func testBrokenTunSend(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGroup) { @@ -234,7 +234,7 @@ func testBrokenTunSend(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGr <-wait // give it time to reconnect - time.Sleep(2 * ReconnectTime) + time.Sleep(5 * ReconnectTime) // send the message if err := c.Send(&m); err != nil { @@ -244,7 +244,7 @@ func testBrokenTunSend(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGr // wait for the listener to receive the message // c.Send merely enqueues the message to the link send queue and returns // in order to verify it was received we wait for the listener to tell us - wait <- true + <-wait } func TestReconnectTunnel(t *testing.T) { From 6353b2b89499a66624e8f3893390f769ab5fa02f Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 22 Oct 2019 20:48:51 +0100 Subject: [PATCH 118/344] Keep track of peer links --- network/default.go | 96 ++++++++++++++++++++++++++++++++++++---------- network/network.go | 10 +++++ 2 files changed, 86 insertions(+), 20 deletions(-) diff --git a/network/default.go b/network/default.go index 36f80da3..782c0b55 100644 --- a/network/default.go +++ b/network/default.go @@ -37,6 +37,8 @@ var ( var ( // ErrClientNotFound is returned when client for tunnel channel could not be found ErrClientNotFound = errors.New("client not found") + // ErrPeerLinkNotFound is returned when peer link could not be found in tunnel Links + ErrPeerLinkNotFound = errors.New("peer link not found") ) // network implements Network interface @@ -58,6 +60,8 @@ type network struct { // tunClient is a map of tunnel clients keyed over tunnel channel names tunClient map[string]transport.Client + // peerLinks is a map of links for each peer + peerLinks map[string]tunnel.Link sync.RWMutex // connected marks the network as connected @@ -138,6 +142,7 @@ func newNetwork(opts ...Option) Network { server: server, client: client, tunClient: make(map[string]transport.Client), + peerLinks: make(map[string]tunnel.Link), } network.node.network = network @@ -246,19 +251,22 @@ func (n *network) resolve() { } // handleNetConn handles network announcement messages -func (n *network) handleNetConn(sess tunnel.Session, msg chan *transport.Message) { +func (n *network) handleNetConn(s tunnel.Session, msg chan *Message) { for { m := new(transport.Message) - if err := sess.Recv(m); err != nil { + if err := s.Recv(m); err != nil { log.Debugf("Network tunnel [%s] receive error: %v", NetworkChannel, err) - if sessErr := sess.Close(); sessErr != nil { - log.Debugf("Network tunnel [%s] closing connection error: %v", sessErr) + if sessionErr := s.Close(); sessionErr != nil { + log.Debugf("Network tunnel [%s] closing connection error: %v", NetworkChannel, sessionErr) } return } select { - case msg <- m: + case msg <- &Message{ + msg: m, + session: s, + }: case <-n.closed: return } @@ -266,7 +274,7 @@ func (n *network) handleNetConn(sess tunnel.Session, msg chan *transport.Message } // acceptNetConn accepts connections from NetworkChannel -func (n *network) acceptNetConn(l tunnel.Listener, recv chan *transport.Message) { +func (n *network) acceptNetConn(l tunnel.Listener, recv chan *Message) { var i int for { // accept a connection @@ -295,10 +303,40 @@ func (n *network) acceptNetConn(l tunnel.Listener, recv chan *transport.Message) } } +func (n *network) updatePeerLinks(peerAddr string, linkId string) error { + n.Lock() + defer n.Unlock() + log.Debugf("Network looking up link %s in the peer links", linkId) + // lookup the peer link + var peerLink tunnel.Link + for _, link := range n.tunnel.Links() { + if link.Id() == linkId { + peerLink = link + break + } + } + if peerLink == nil { + return ErrPeerLinkNotFound + } + // if the peerLink is found in the returned links update peerLinks + log.Debugf("Network updating peer links for peer %s", peerAddr) + // add peerLink to the peerLinks map + if link, ok := n.peerLinks[peerAddr]; ok { + // if the existing has better Length then the new, replace it + if link.Length() < peerLink.Length() { + n.peerLinks[peerAddr] = peerLink + } + } else { + n.peerLinks[peerAddr] = peerLink + } + + return nil +} + // processNetChan processes messages received on NetworkChannel func (n *network) processNetChan(listener tunnel.Listener) { // receive network message queue - recv := make(chan *transport.Message, 128) + recv := make(chan *Message, 128) // accept NetworkChannel connections go n.acceptNetConn(listener, recv) @@ -307,12 +345,12 @@ func (n *network) processNetChan(listener tunnel.Listener) { select { case m := <-recv: // switch on type of message and take action - switch m.Header["Micro-Method"] { + switch m.msg.Header["Micro-Method"] { case "connect": // mark the time the message has been received now := time.Now() pbNetConnect := &pbNet.Connect{} - if err := proto.Unmarshal(m.Body, pbNetConnect); err != nil { + if err := proto.Unmarshal(m.msg.Body, pbNetConnect); err != nil { log.Debugf("Network tunnel [%s] connect unmarshal error: %v", NetworkChannel, err) continue } @@ -327,6 +365,10 @@ func (n *network) processNetChan(listener tunnel.Listener) { peers: make(map[string]*node), lastSeen: now, } + // update peer links + if err := n.updatePeerLinks(pbNetConnect.Node.Address, m.session.Link()); err != nil { + log.Debugf("Network failed updating peer links: %s", err) + } if err := n.node.AddPeer(peer); err == ErrPeerExists { log.Debugf("Network peer exists, refreshing: %s", peer.id) // update lastSeen time for the existing node @@ -349,7 +391,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { // mark the time the message has been received now := time.Now() pbNetPeer := &pbNet.Peer{} - if err := proto.Unmarshal(m.Body, pbNetPeer); err != nil { + if err := proto.Unmarshal(m.msg.Body, pbNetPeer); err != nil { log.Debugf("Network tunnel [%s] peer unmarshal error: %v", NetworkChannel, err) continue } @@ -364,6 +406,10 @@ func (n *network) processNetChan(listener tunnel.Listener) { peers: make(map[string]*node), lastSeen: now, } + // update peer links + if err := n.updatePeerLinks(pbNetPeer.Node.Address, m.session.Link()); err != nil { + log.Debugf("Network failed updating peer links: %s", err) + } if err := n.node.AddPeer(peer); err == nil { // send a solicit message when discovering new peer msg := &pbRtr.Solicit{ @@ -393,7 +439,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { } case "close": pbNetClose := &pbNet.Close{} - if err := proto.Unmarshal(m.Body, pbNetClose); err != nil { + if err := proto.Unmarshal(m.msg.Body, pbNetClose); err != nil { log.Debugf("Network tunnel [%s] close unmarshal error: %v", NetworkChannel, err) continue } @@ -412,6 +458,10 @@ func (n *network) processNetChan(listener tunnel.Listener) { if err := n.prunePeerRoutes(peer); err != nil { log.Debugf("Network failed pruning peer %s routes: %v", peer.id, err) } + // deelete peer from the peerLinks + n.Lock() + delete(n.peerLinks, pbNetClose.Node.Address) + n.Unlock() } case <-n.closed: return @@ -549,16 +599,22 @@ func (n *network) prune() { } // handleCtrlConn handles ControlChannel connections -func (n *network) handleCtrlConn(sess tunnel.Session, msg chan *transport.Message) { +func (n *network) handleCtrlConn(s tunnel.Session, msg chan *Message) { for { m := new(transport.Message) - if err := sess.Recv(m); err != nil { - log.Debugf("Network tunnel advert receive error: %v", err) + if err := s.Recv(m); err != nil { + log.Debugf("Network tunnel [%s] receive error: %v", ControlChannel, err) + if sessionErr := s.Close(); sessionErr != nil { + log.Debugf("Network tunnel [%s] closing connection error: %v", ControlChannel, sessionErr) + } return } select { - case msg <- m: + case msg <- &Message{ + msg: m, + session: s, + }: case <-n.closed: return } @@ -566,7 +622,7 @@ func (n *network) handleCtrlConn(sess tunnel.Session, msg chan *transport.Messag } // acceptCtrlConn accepts connections from ControlChannel -func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *transport.Message) { +func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *Message) { var i int for { // accept a connection @@ -631,7 +687,7 @@ func (n *network) setRouteMetric(route *router.Route) { // processCtrlChan processes messages received on ControlChannel func (n *network) processCtrlChan(listener tunnel.Listener) { // receive control message queue - recv := make(chan *transport.Message, 128) + recv := make(chan *Message, 128) // accept ControlChannel cconnections go n.acceptCtrlConn(listener, recv) @@ -640,10 +696,10 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { select { case m := <-recv: // switch on type of message and take action - switch m.Header["Micro-Method"] { + switch m.msg.Header["Micro-Method"] { case "advert": pbRtrAdvert := &pbRtr.Advert{} - if err := proto.Unmarshal(m.Body, pbRtrAdvert); err != nil { + if err := proto.Unmarshal(m.msg.Body, pbRtrAdvert); err != nil { log.Debugf("Network fail to unmarshal advert message: %v", err) continue } @@ -717,7 +773,7 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { } case "solicit": pbRtrSolicit := &pbRtr.Solicit{} - if err := proto.Unmarshal(m.Body, pbRtrSolicit); err != nil { + if err := proto.Unmarshal(m.msg.Body, pbRtrSolicit); err != nil { log.Debugf("Network fail to unmarshal solicit message: %v", err) continue } diff --git a/network/network.go b/network/network.go index e927241b..44e205e6 100644 --- a/network/network.go +++ b/network/network.go @@ -6,6 +6,8 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/server" + "github.com/micro/go-micro/transport" + "github.com/micro/go-micro/tunnel" ) var ( @@ -54,6 +56,14 @@ type Network interface { Server() server.Server } +// Message is network message +type Message struct { + // msg is transport message + msg *transport.Message + // session is tunnel session + session tunnel.Session +} + // NewNetwork returns a new network interface func NewNetwork(opts ...Option) Network { return newNetwork(opts...) From 326156671dd9a1aea02b08060aef8f491ae34b39 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 22 Oct 2019 22:46:25 +0100 Subject: [PATCH 119/344] Set route metric to link Length --- network/default.go | 53 ++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 39 deletions(-) diff --git a/network/default.go b/network/default.go index 782c0b55..89a1ea59 100644 --- a/network/default.go +++ b/network/default.go @@ -369,6 +369,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { if err := n.updatePeerLinks(pbNetConnect.Node.Address, m.session.Link()); err != nil { log.Debugf("Network failed updating peer links: %s", err) } + // add peer to the list of node peers if err := n.node.AddPeer(peer); err == ErrPeerExists { log.Debugf("Network peer exists, refreshing: %s", peer.id) // update lastSeen time for the existing node @@ -652,38 +653,6 @@ func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *Message) { } } -// setRouteMetric calculates metric of the route and updates it in place -// - Local route metric is 1 -// - Routes with ID of adjacent nodes are 10 -// - Routes by peers of the advertiser are 100 -// - Routes beyond your neighbourhood are 1000 -func (n *network) setRouteMetric(route *router.Route) { - // we are the origin of the route - if route.Router == n.options.Id { - route.Metric = 1 - return - } - - // check if the route origin is our peer - if _, ok := n.peers[route.Router]; ok { - route.Metric = 10 - return - } - - // check if the route origin is the peer of our peer - for _, peer := range n.peers { - for id := range peer.peers { - if route.Router == id { - route.Metric = 100 - return - } - } - } - - // the origin of the route is beyond our neighbourhood - route.Metric = 1000 -} - // processCtrlChan processes messages received on ControlChannel func (n *network) processCtrlChan(listener tunnel.Listener) { // receive control message queue @@ -737,14 +706,20 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { Metric: int(event.Route.Metric), } // set the route metric - n.node.RLock() - n.setRouteMetric(&route) - n.node.RUnlock() - // throw away metric bigger than 1000 - if route.Metric > 1000 { - log.Debugf("Network route metric %d dropping node: %s", route.Metric, route.Router) - continue + n.RLock() + if link, ok := n.peerLinks[event.Route.Gateway]; ok { + // NOTE: should we change router.Route.Metric to int64? + if int(link.Length()) < route.Metric { + route.Metric = int(link.Length()) + } } + n.RUnlock() + // TODO: Are we dropping any routes? + // throw away metric bigger than 1000 + //if route.Metric > 1000 { + // log.Debugf("Network route metric %d dropping node: %s", route.Metric, route.Router) + // continue + //} // create router event e := &router.Event{ Type: router.EventType(event.Type), From 1ff65e140a0818bd7a68fd9dcec0421cd86efb34 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 23 Oct 2019 12:53:36 +0100 Subject: [PATCH 120/344] Change router.Route metric to int64. Set the route metric properly --- client/selector/router/router.go | 2 +- network/default.go | 56 ++++++++++++++++++++++++++------ router/handler/router.go | 8 ++--- router/handler/table.go | 10 +++--- router/route.go | 6 ++-- router/service/service.go | 6 ++-- router/service/table.go | 10 +++--- router/service/watcher.go | 2 +- 8 files changed, 67 insertions(+), 33 deletions(-) diff --git a/client/selector/router/router.go b/client/selector/router/router.go index 0f1f6c58..015bc1e3 100644 --- a/client/selector/router/router.go +++ b/client/selector/router/router.go @@ -111,7 +111,7 @@ func (r *routerSelector) getRoutes(service string) ([]router.Route, error) { Gateway: r.Gateway, Network: r.Network, Link: r.Link, - Metric: int(r.Metric), + Metric: r.Metric, }) } diff --git a/network/default.go b/network/default.go index 89a1ea59..2ef22ff3 100644 --- a/network/default.go +++ b/network/default.go @@ -653,6 +653,38 @@ func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *Message) { } } +// getHopCount queries network graph and returns hop count for given router +// - Routes for local services have hop count 1 +// - Routes with ID of adjacent nodes have hop count 2 +// - Routes by peers of the advertiser have hop count 3 +// - Routes beyond node neighbourhood have hop count 4 +func (n *network) getHopCount(rtr string) int { + // make sure node.peers are not modified + n.node.RLock() + defer n.node.RUnlock() + + // we are the origin of the route + if rtr == n.options.Id { + return 1 + } + + // the route origin is our peer + if _, ok := n.peers[rtr]; ok { + return 2 + } + + // the route origin is the peer of our peer + for _, peer := range n.peers { + for id := range peer.peers { + if rtr == id { + return 3 + } + } + } + // otherwise we are three hops away + return 4 +} + // processCtrlChan processes messages received on ControlChannel func (n *network) processCtrlChan(listener tunnel.Listener) { // receive control message queue @@ -703,23 +735,27 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { Network: event.Route.Network, Router: event.Route.Router, Link: event.Route.Link, - Metric: int(event.Route.Metric), + Metric: event.Route.Metric, } // set the route metric n.RLock() if link, ok := n.peerLinks[event.Route.Gateway]; ok { - // NOTE: should we change router.Route.Metric to int64? - if int(link.Length()) < route.Metric { - route.Metric = int(link.Length()) + // maka sure delay is non-zero + delay := link.Delay() + if delay == 0 { + delay = 1 } + // get the route hop count + hops := n.getHopCount(event.Route.Router) + // make sure length is non-zero + length := link.Length() + if length == 0 { + length = 10e10 + } + metric := (delay * length * int64(hops)) / 10e9 + route.Metric += metric } n.RUnlock() - // TODO: Are we dropping any routes? - // throw away metric bigger than 1000 - //if route.Metric > 1000 { - // log.Debugf("Network route metric %d dropping node: %s", route.Metric, route.Router) - // continue - //} // create router event e := &router.Event{ Type: router.EventType(event.Type), diff --git a/router/handler/router.go b/router/handler/router.go index f8b8cc51..6b71f70f 100644 --- a/router/handler/router.go +++ b/router/handler/router.go @@ -31,7 +31,7 @@ func (r *Router) Lookup(ctx context.Context, req *pb.LookupRequest, resp *pb.Loo Network: route.Network, Router: route.Router, Link: route.Link, - Metric: int64(route.Metric), + Metric: route.Metric, } respRoutes = append(respRoutes, respRoute) } @@ -67,7 +67,7 @@ func (r *Router) Advertise(ctx context.Context, req *pb.Request, stream pb.Route Network: event.Route.Network, Router: event.Route.Router, Link: event.Route.Link, - Metric: int64(event.Route.Metric), + Metric: event.Route.Metric, } e := &pb.Event{ Type: pb.EventType(event.Type), @@ -108,7 +108,7 @@ func (r *Router) Process(ctx context.Context, req *pb.Advert, rsp *pb.ProcessRes Network: event.Route.Network, Router: event.Route.Router, Link: event.Route.Link, - Metric: int(event.Route.Metric), + Metric: event.Route.Metric, } events[i] = &router.Event{ @@ -174,7 +174,7 @@ func (r *Router) Watch(ctx context.Context, req *pb.WatchRequest, stream pb.Rout Network: event.Route.Network, Router: event.Route.Router, Link: event.Route.Link, - Metric: int64(event.Route.Metric), + Metric: event.Route.Metric, } tableEvent := &pb.Event{ diff --git a/router/handler/table.go b/router/handler/table.go index 899a2795..bf972efb 100644 --- a/router/handler/table.go +++ b/router/handler/table.go @@ -20,7 +20,7 @@ func (t *Table) Create(ctx context.Context, route *pb.Route, resp *pb.CreateResp Network: route.Network, Router: route.Router, Link: route.Link, - Metric: int(route.Metric), + Metric: route.Metric, }) if err != nil { return errors.InternalServerError("go.micro.router", "failed to create route: %s", err) @@ -37,7 +37,7 @@ func (t *Table) Update(ctx context.Context, route *pb.Route, resp *pb.UpdateResp Network: route.Network, Router: route.Router, Link: route.Link, - Metric: int(route.Metric), + Metric: route.Metric, }) if err != nil { return errors.InternalServerError("go.micro.router", "failed to update route: %s", err) @@ -54,7 +54,7 @@ func (t *Table) Delete(ctx context.Context, route *pb.Route, resp *pb.DeleteResp Network: route.Network, Router: route.Router, Link: route.Link, - Metric: int(route.Metric), + Metric: route.Metric, }) if err != nil { return errors.InternalServerError("go.micro.router", "failed to delete route: %s", err) @@ -79,7 +79,7 @@ func (t *Table) List(ctx context.Context, req *pb.Request, resp *pb.ListResponse Network: route.Network, Router: route.Router, Link: route.Link, - Metric: int64(route.Metric), + Metric: route.Metric, } respRoutes = append(respRoutes, respRoute) } @@ -104,7 +104,7 @@ func (t *Table) Query(ctx context.Context, req *pb.QueryRequest, resp *pb.QueryR Network: route.Network, Router: route.Router, Link: route.Link, - Metric: int64(route.Metric), + Metric: route.Metric, } respRoutes = append(respRoutes, respRoute) } diff --git a/router/route.go b/router/route.go index f2768403..ed384e7c 100644 --- a/router/route.go +++ b/router/route.go @@ -8,9 +8,7 @@ var ( // DefaultLink is default network link DefaultLink = "local" // DefaultLocalMetric is default route cost for a local route - DefaultLocalMetric = 1 - // DefaultNetworkMetric is default route cost for a network route - DefaultNetworkMetric = 10 + DefaultLocalMetric int64 = 1 ) // Route is network route @@ -28,7 +26,7 @@ type Route struct { // Link is network link Link string // Metric is the route cost metric - Metric int + Metric int64 } // Hash returns route hash sum. diff --git a/router/service/service.go b/router/service/service.go index 068d0ae3..4f9dcb9b 100644 --- a/router/service/service.go +++ b/router/service/service.go @@ -132,7 +132,7 @@ func (s *svc) advertiseEvents(advertChan chan *router.Advert, stream pb.Router_A Gateway: event.Route.Gateway, Network: event.Route.Network, Link: event.Route.Link, - Metric: int(event.Route.Metric), + Metric: event.Route.Metric, } events[i] = &router.Event{ @@ -196,7 +196,7 @@ func (s *svc) Process(advert *router.Advert) error { Gateway: event.Route.Gateway, Network: event.Route.Network, Link: event.Route.Link, - Metric: int64(event.Route.Metric), + Metric: event.Route.Metric, } e := &pb.Event{ Type: pb.EventType(event.Type), @@ -346,7 +346,7 @@ func (s *svc) Lookup(q ...router.QueryOption) ([]router.Route, error) { Gateway: route.Gateway, Network: route.Network, Link: route.Link, - Metric: int(route.Metric), + Metric: route.Metric, } } diff --git a/router/service/table.go b/router/service/table.go index 940fbd41..77e288db 100644 --- a/router/service/table.go +++ b/router/service/table.go @@ -21,7 +21,7 @@ func (t *table) Create(r router.Route) error { Gateway: r.Gateway, Network: r.Network, Link: r.Link, - Metric: int64(r.Metric), + Metric: r.Metric, } if _, err := t.table.Create(context.Background(), route, t.callOpts...); err != nil { @@ -39,7 +39,7 @@ func (t *table) Delete(r router.Route) error { Gateway: r.Gateway, Network: r.Network, Link: r.Link, - Metric: int64(r.Metric), + Metric: r.Metric, } if _, err := t.table.Delete(context.Background(), route, t.callOpts...); err != nil { @@ -57,7 +57,7 @@ func (t *table) Update(r router.Route) error { Gateway: r.Gateway, Network: r.Network, Link: r.Link, - Metric: int64(r.Metric), + Metric: r.Metric, } if _, err := t.table.Update(context.Background(), route, t.callOpts...); err != nil { @@ -82,7 +82,7 @@ func (t *table) List() ([]router.Route, error) { Gateway: route.Gateway, Network: route.Network, Link: route.Link, - Metric: int(route.Metric), + Metric: route.Metric, } } @@ -115,7 +115,7 @@ func (t *table) Query(q ...router.QueryOption) ([]router.Route, error) { Gateway: route.Gateway, Network: route.Network, Link: route.Link, - Metric: int(route.Metric), + Metric: route.Metric, } } diff --git a/router/service/watcher.go b/router/service/watcher.go index 01124473..616dc2d4 100644 --- a/router/service/watcher.go +++ b/router/service/watcher.go @@ -61,7 +61,7 @@ func (w *watcher) watch(stream pb.Router_WatchService) error { Gateway: resp.Route.Gateway, Network: resp.Route.Network, Link: resp.Route.Link, - Metric: int(resp.Route.Metric), + Metric: resp.Route.Metric, } event := &router.Event{ From f4f178c130be66ce19cd41a42d441ae8319e7ac5 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 23 Oct 2019 15:33:51 +0100 Subject: [PATCH 121/344] Set metric on egress. Increment metric on ingress. --- network/default.go | 52 ++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/network/default.go b/network/default.go index 2ef22ff3..39a9a83d 100644 --- a/network/default.go +++ b/network/default.go @@ -653,6 +653,31 @@ func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *Message) { } } +// getRouteMetric calculates router metric and returns it +// Route metric is calculated based on link status and route hopd count +func (n *network) getRouteMetric(router string, gateway string) int64 { + // set the route metric + n.RLock() + defer n.RUnlock() + + if link, ok := n.peerLinks[gateway]; ok { + // maka sure delay is non-zero + delay := link.Delay() + if delay == 0 { + delay = 1 + } + // get the route hop count + hops := n.getHopCount(router) + // make sure length is non-zero + length := link.Length() + if length == 0 { + length = 10e10 + } + return (delay * length * int64(hops)) / 10e9 + } + return 0 +} + // getHopCount queries network graph and returns hop count for given router // - Routes for local services have hop count 1 // - Routes with ID of adjacent nodes have hop count 2 @@ -737,25 +762,8 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { Link: event.Route.Link, Metric: event.Route.Metric, } - // set the route metric - n.RLock() - if link, ok := n.peerLinks[event.Route.Gateway]; ok { - // maka sure delay is non-zero - delay := link.Delay() - if delay == 0 { - delay = 1 - } - // get the route hop count - hops := n.getHopCount(event.Route.Router) - // make sure length is non-zero - length := link.Length() - if length == 0 { - length = 10e10 - } - metric := (delay * length * int64(hops)) / 10e9 - route.Metric += metric - } - n.RUnlock() + // calculate route metric and add to the advertised metric + route.Metric += n.getRouteMetric(event.Route.Router, event.Route.Gateway) // create router event e := &router.Event{ Type: router.EventType(event.Type), @@ -825,9 +833,9 @@ func (n *network) advertise(advertChan <-chan *router.Advert) { hasher.Write([]byte(event.Route.Address + n.node.id)) address = fmt.Sprintf("%d", hasher.Sum64()) } - + // calculate route metric to advertise + metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway) // NOTE: we override Gateway, Link and Address here - // TODO: should we avoid overriding gateway? route := &pbRtr.Route{ Service: event.Route.Service, Address: address, @@ -835,7 +843,7 @@ func (n *network) advertise(advertChan <-chan *router.Advert) { Network: event.Route.Network, Router: event.Route.Router, Link: DefaultLink, - Metric: int64(event.Route.Metric), + Metric: metric, } e := &pbRtr.Event{ Type: pbRtr.EventType(event.Type), From b3d4a7f740574859d5b879ffa27645478b5eea3e Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 23 Oct 2019 16:48:47 +0100 Subject: [PATCH 122/344] If no link found, return max possible value --- network/default.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index 39a9a83d..b0353058 100644 --- a/network/default.go +++ b/network/default.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "hash/fnv" + "math" "sync" "time" @@ -675,7 +676,7 @@ func (n *network) getRouteMetric(router string, gateway string) int64 { } return (delay * length * int64(hops)) / 10e9 } - return 0 + return math.MaxInt64 } // getHopCount queries network graph and returns hop count for given router From 68789af4ea0b4d33f1d3d29fca65d5e9566d606b Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 23 Oct 2019 17:29:03 +0100 Subject: [PATCH 123/344] Prune peerlinks of pruned nodes --- network/default.go | 55 ++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/network/default.go b/network/default.go index b0353058..a4af17c0 100644 --- a/network/default.go +++ b/network/default.go @@ -573,6 +573,9 @@ func (n *network) prune() { pruned := n.PruneStalePeerNodes(PruneTime) for id, peer := range pruned { log.Debugf("Network peer exceeded prune time: %s", id) + n.Lock() + delete(n.peerLinks, peer.address) + n.Unlock() if err := n.prunePeerRoutes(peer); err != nil { log.Debugf("Network failed pruning peer %s routes: %v", id, err) } @@ -580,7 +583,7 @@ func (n *network) prune() { // get a list of all routes routes, err := n.options.Router.Table().List() if err != nil { - log.Debugf("Network failed listing routes: %v", err) + log.Debugf("Network failed listing routes when pruning peers: %v", err) continue } // collect all the router IDs in the routing table @@ -654,31 +657,6 @@ func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *Message) { } } -// getRouteMetric calculates router metric and returns it -// Route metric is calculated based on link status and route hopd count -func (n *network) getRouteMetric(router string, gateway string) int64 { - // set the route metric - n.RLock() - defer n.RUnlock() - - if link, ok := n.peerLinks[gateway]; ok { - // maka sure delay is non-zero - delay := link.Delay() - if delay == 0 { - delay = 1 - } - // get the route hop count - hops := n.getHopCount(router) - // make sure length is non-zero - length := link.Length() - if length == 0 { - length = 10e10 - } - return (delay * length * int64(hops)) / 10e9 - } - return math.MaxInt64 -} - // getHopCount queries network graph and returns hop count for given router // - Routes for local services have hop count 1 // - Routes with ID of adjacent nodes have hop count 2 @@ -711,6 +689,31 @@ func (n *network) getHopCount(rtr string) int { return 4 } +// getRouteMetric calculates router metric and returns it +// Route metric is calculated based on link status and route hopd count +func (n *network) getRouteMetric(router string, gateway string) int64 { + // set the route metric + n.RLock() + defer n.RUnlock() + + if link, ok := n.peerLinks[gateway]; ok { + // maka sure delay is non-zero + delay := link.Delay() + if delay == 0 { + delay = 1 + } + // get the route hop count + hops := n.getHopCount(router) + // make sure length is non-zero + length := link.Length() + if length == 0 { + length = 10e10 + } + return (delay * length * int64(hops)) / 10e9 + } + return math.MaxInt64 +} + // processCtrlChan processes messages received on ControlChannel func (n *network) processCtrlChan(listener tunnel.Listener) { // receive control message queue From 4f5db082387ed96f510e5324e962c5831c1a75e5 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Wed, 23 Oct 2019 17:26:34 +0100 Subject: [PATCH 124/344] Remove cloudflare-go and reimplement workers KV --- store/cloudflare/cloudflare.go | 197 +++++++++++++++++++++++++--- store/cloudflare/cloudflare_test.go | 36 ++++- 2 files changed, 207 insertions(+), 26 deletions(-) diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index a35302dd..61bf592a 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -3,20 +3,29 @@ package cloudflare import ( + "bytes" "context" + "encoding/json" + "fmt" + "io" + "io/ioutil" "log" + "math" + "net/http" + "net/url" + "strconv" "time" - "github.com/cloudflare/cloudflare-go" "github.com/micro/go-micro/config/options" "github.com/micro/go-micro/store" + "github.com/pkg/errors" ) -var namespaceUUID string +const apiBaseURL = "https://api.cloudflare.com/client/v4/" type workersKV struct { options.Options - api *cloudflare.API + httpClient *http.Client } // New returns a cloudflare Store implementation. @@ -30,7 +39,7 @@ func New(opts ...options.Option) (store.Store, error) { if !ok { log.Fatal("Store: No CF_API_TOKEN passed as an option") } - apiTokenString, ok := apiToken.(string) + _, ok = apiToken.(string) if !ok { log.Fatal("Store: Option CF_API_TOKEN contains a non-string") } @@ -38,7 +47,7 @@ func New(opts ...options.Option) (store.Store, error) { if !ok { log.Fatal("Store: No CF_ACCOUNT_ID passed as an option") } - accountIDString, ok := accountID.(string) + _, ok = accountID.(string) if !ok { log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string") } @@ -46,31 +55,45 @@ func New(opts ...options.Option) (store.Store, error) { if !ok { log.Fatal("Store: No KV_NAMESPACE_ID passed as an option") } - namespaceUUID, ok = uuid.(string) + _, ok = uuid.(string) if !ok { log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string") } - // Create API client - api, err := cloudflare.NewWithAPIToken(apiTokenString, cloudflare.UsingAccount(accountIDString)) - if err != nil { - return nil, err - } return &workersKV{ - Options: options, - api: api, + Options: options, + httpClient: &http.Client{}, }, nil } // In the cloudflare workers KV implemention, Sync() doesn't guarantee // anything as the workers API is eventually consistent. func (w *workersKV) Sync() ([]*store.Record, error) { - response, err := w.api.ListWorkersKVs(context.Background(), namespaceUUID) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID") + kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID") + + path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/keys", accountID.(string), kvID.(string)) + response, _, _, err := w.request(ctx, http.MethodGet, path, nil, make(http.Header)) if err != nil { return nil, err } + a := &APIResponse{} + if err := json.Unmarshal(response, a); err != nil { + return nil, err + } + if !a.Success { + messages := "" + for _, m := range a.Errors { + messages += strconv.Itoa(m.Code) + " " + m.Message + "\n" + } + return nil, errors.New(messages) + } + var keys []string - for _, r := range response.Result { + for _, r := range a.Result { keys = append(keys, r.Name) } return w.Read(keys...) @@ -80,16 +103,31 @@ func (w *workersKV) Read(keys ...string) ([]*store.Record, error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() + accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID") + kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID") + var records []*store.Record for _, k := range keys { - v, err := w.api.ReadWorkersKV(ctx, namespaceUUID, k) + path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", accountID.(string), kvID.(string), url.PathEscape(k)) + response, headers, status, err := w.request(ctx, http.MethodGet, path, nil, make(http.Header)) if err != nil { return records, err } - records = append(records, &store.Record{ + if status < 200 || status >= 300 { + return records, errors.New("Received unexpected Status " + strconv.Itoa(status) + string(response)) + } + record := &store.Record{ Key: k, - Value: v, - }) + Value: response, + } + if expiry := headers.Get("Expiration"); len(expiry) != 0 { + expiryUnix, err := strconv.ParseInt(expiry, 10, 64) + if err != nil { + return records, err + } + record.Expiry = time.Until(time.Unix(expiryUnix, 0)) + } + records = append(records, record) } return records, nil } @@ -98,10 +136,32 @@ func (w *workersKV) Write(records ...*store.Record) error { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() + accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID") + kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID") + for _, r := range records { - if _, err := w.api.WriteWorkersKV(ctx, namespaceUUID, r.Key, r.Value); err != nil { + path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", accountID.(string), kvID.(string), url.PathEscape(r.Key)) + if r.Expiry != 0 { + // Minimum cloudflare TTL is 60 Seconds + exp := int(math.Max(60, math.Round(r.Expiry.Seconds()))) + path = path + "?expiration_ttl=" + strconv.Itoa(exp) + } + headers := make(http.Header) + resp, _, _, err := w.request(ctx, http.MethodPut, path, r.Value, headers) + if err != nil { return err } + a := &APIResponse{} + if err := json.Unmarshal(resp, a); err != nil { + return err + } + if !a.Success { + messages := "" + for _, m := range a.Errors { + messages += strconv.Itoa(m.Code) + " " + m.Message + "\n" + } + return errors.New(messages) + } } return nil } @@ -110,10 +170,105 @@ func (w *workersKV) Delete(keys ...string) error { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() + accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID") + kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID") + for _, k := range keys { - if _, err := w.api.DeleteWorkersKV(ctx, namespaceUUID, k); err != nil { + path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", accountID.(string), kvID.(string), url.PathEscape(k)) + resp, _, _, err := w.request(ctx, http.MethodDelete, path, nil, make(http.Header)) + if err != nil { return err } + + a := &APIResponse{} + if err := json.Unmarshal(resp, a); err != nil { + return err + } + if !a.Success { + messages := "" + for _, m := range a.Errors { + messages += strconv.Itoa(m.Code) + " " + m.Message + "\n" + } + return errors.New(messages) + } } return nil } + +func (w *workersKV) request(ctx context.Context, method, path string, body interface{}, headers http.Header) ([]byte, http.Header, int, error) { + var jsonBody []byte + var err error + + if body != nil { + if paramBytes, ok := body.([]byte); ok { + jsonBody = paramBytes + } else { + jsonBody, err = json.Marshal(body) + if err != nil { + return nil, nil, 0, errors.Wrap(err, "error marshalling params to JSON") + } + } + } else { + jsonBody = nil + } + var reqBody io.Reader + if jsonBody != nil { + reqBody = bytes.NewReader(jsonBody) + } + req, err := http.NewRequestWithContext(ctx, method, apiBaseURL+path, reqBody) + for key, value := range headers { + req.Header[key] = value + } + if token, found := w.Options.Values().Get("CF_API_TOKEN"); found { + req.Header.Set("Authorization", "Bearer "+token.(string)) + } + req.Header.Set("User-Agent", "micro/1.0 (https://micro.mu)") + + // Official cloudflare client does exponential backoff here + resp, err := w.httpClient.Do(req) + if err != nil { + return nil, nil, 0, err + } + defer resp.Body.Close() + respBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + return respBody, resp.Header, resp.StatusCode, err + } + return respBody, resp.Header, resp.StatusCode, nil +} + +// APIResponse is a cloudflare v4 api response +type APIResponse struct { + Result []struct { + ID string `json:"id"` + Type string `json:"type"` + Name string `json:"name"` + Expiration string `json:"expiration"` + Content string `json:"content"` + Proxiable bool `json:"proxiable"` + Proxied bool `json:"proxied"` + TTL int `json:"ttl"` + Priority int `json:"priority"` + Locked bool `json:"locked"` + ZoneID string `json:"zone_id"` + ZoneName string `json:"zone_name"` + ModifiedOn time.Time `json:"modified_on"` + CreatedOn time.Time `json:"created_on"` + } `json:"result"` + Success bool `json:"success"` + Errors []APIMessage `json:"errors"` + // not sure Messages is ever populated? + Messages []APIMessage `json:"messages"` + ResultInfo struct { + Page int `json:"page"` + PerPage int `json:"per_page"` + Count int `json:"count"` + TotalCount int `json:"total_count"` + } `json:"result_info"` +} + +// APIMessage is a Cloudflare v4 API Error +type APIMessage struct { + Code int `json:"code"` + Message string `json:"message"` +} diff --git a/store/cloudflare/cloudflare_test.go b/store/cloudflare/cloudflare_test.go index faf4465f..ed73e796 100644 --- a/store/cloudflare/cloudflare_test.go +++ b/store/cloudflare/cloudflare_test.go @@ -31,15 +31,24 @@ func TestCloudflare(t *testing.T) { t.Fatal(err.Error()) } - _, err = wkv.Sync() + records, err := wkv.Sync() if err != nil { t.Fatalf("Sync: %s\n", err.Error()) + } else { + t.Log("Synced " + strconv.Itoa(len(records)) + " records") } - err = wkv.Write(&store.Record{ - Key: randomK, - Value: []byte(randomV), - }) + err = wkv.Write( + &store.Record{ + Key: randomK, + Value: []byte(randomV), + }, + &store.Record{ + Key: "expirationtest", + Value: []byte("This message will self destruct"), + Expiry: 75 * time.Second, + }, + ) if err != nil { t.Errorf("Write: %s", err.Error()) } @@ -58,6 +67,23 @@ func TestCloudflare(t *testing.T) { t.Errorf("Read: expected %s, got %s\n", randomK, string(r[0].Value)) } + r, err = wkv.Read("expirationtest") + if err != nil { + t.Errorf("Read: expirationtest should still exist") + } + if r[0].Expiry == 0 { + t.Error("Expected r to have an expiry") + } else { + t.Log(r[0].Expiry) + } + + time.Sleep(20 * time.Second) + r, err = wkv.Read("expirationtest") + if err == nil && len(r) != 0 { + t.Error("Read: Managed to read expirationtest, but it should have expired") + t.Log(err, r[0].Key, string(r[0].Value), r[0].Expiry, len(r)) + } + err = wkv.Delete(randomK) if err != nil { t.Errorf("Delete: %s\n", err.Error()) From 35729092e041bff9c76569959ff51d2518aa1a27 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 23 Oct 2019 17:32:45 +0100 Subject: [PATCH 125/344] Unexport network.Message --- network/default.go | 16 ++++++++-------- network/network.go | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/network/default.go b/network/default.go index a4af17c0..8490ce54 100644 --- a/network/default.go +++ b/network/default.go @@ -252,7 +252,7 @@ func (n *network) resolve() { } // handleNetConn handles network announcement messages -func (n *network) handleNetConn(s tunnel.Session, msg chan *Message) { +func (n *network) handleNetConn(s tunnel.Session, msg chan *message) { for { m := new(transport.Message) if err := s.Recv(m); err != nil { @@ -264,7 +264,7 @@ func (n *network) handleNetConn(s tunnel.Session, msg chan *Message) { } select { - case msg <- &Message{ + case msg <- &message{ msg: m, session: s, }: @@ -275,7 +275,7 @@ func (n *network) handleNetConn(s tunnel.Session, msg chan *Message) { } // acceptNetConn accepts connections from NetworkChannel -func (n *network) acceptNetConn(l tunnel.Listener, recv chan *Message) { +func (n *network) acceptNetConn(l tunnel.Listener, recv chan *message) { var i int for { // accept a connection @@ -337,7 +337,7 @@ func (n *network) updatePeerLinks(peerAddr string, linkId string) error { // processNetChan processes messages received on NetworkChannel func (n *network) processNetChan(listener tunnel.Listener) { // receive network message queue - recv := make(chan *Message, 128) + recv := make(chan *message, 128) // accept NetworkChannel connections go n.acceptNetConn(listener, recv) @@ -604,7 +604,7 @@ func (n *network) prune() { } // handleCtrlConn handles ControlChannel connections -func (n *network) handleCtrlConn(s tunnel.Session, msg chan *Message) { +func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { for { m := new(transport.Message) if err := s.Recv(m); err != nil { @@ -616,7 +616,7 @@ func (n *network) handleCtrlConn(s tunnel.Session, msg chan *Message) { } select { - case msg <- &Message{ + case msg <- &message{ msg: m, session: s, }: @@ -627,7 +627,7 @@ func (n *network) handleCtrlConn(s tunnel.Session, msg chan *Message) { } // acceptCtrlConn accepts connections from ControlChannel -func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *Message) { +func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *message) { var i int for { // accept a connection @@ -717,7 +717,7 @@ func (n *network) getRouteMetric(router string, gateway string) int64 { // processCtrlChan processes messages received on ControlChannel func (n *network) processCtrlChan(listener tunnel.Listener) { // receive control message queue - recv := make(chan *Message, 128) + recv := make(chan *message, 128) // accept ControlChannel cconnections go n.acceptCtrlConn(listener, recv) diff --git a/network/network.go b/network/network.go index 44e205e6..08a45665 100644 --- a/network/network.go +++ b/network/network.go @@ -56,8 +56,8 @@ type Network interface { Server() server.Server } -// Message is network message -type Message struct { +// message is network message +type message struct { // msg is transport message msg *transport.Message // session is tunnel session From 53ee4ee48238eb4f15a4541a39c843e52e9c230e Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Wed, 23 Oct 2019 17:33:20 +0100 Subject: [PATCH 126/344] goodbye cloudflare-go --- go.mod | 2 -- go.sum | 58 ---------------------------------------------------------- 2 files changed, 60 deletions(-) diff --git a/go.mod b/go.mod index caf4e6c8..a08ccfe0 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/bitly/go-simplejson v0.5.0 github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/bwmarrin/discordgo v0.19.0 - github.com/cloudflare/cloudflare-go v0.10.4 github.com/coreos/bbolt v1.3.3 // indirect github.com/coreos/etcd v3.3.17+incompatible github.com/coreos/go-semver v0.3.0 // indirect @@ -30,7 +29,6 @@ require ( github.com/gorilla/websocket v1.4.1 github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/hashicorp/consul/api v1.2.0 github.com/hashicorp/hcl v1.0.0 github.com/imdario/mergo v0.3.8 github.com/jonboulle/clockwork v0.1.0 // indirect diff --git a/go.sum b/go.sum index dfcc6613..6970348f 100644 --- a/go.sum +++ b/go.sum @@ -36,10 +36,6 @@ github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -50,7 +46,6 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= @@ -65,8 +60,6 @@ github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wX github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.10.2 h1:VBodKICVPnwmDxstcW3biKcDSpFIfS/RELUXsZSBYK4= github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= -github.com/cloudflare/cloudflare-go v0.10.4 h1:7C1D9mtcNFZLCqmhkHK2BlwKKm9fi4cBqY6qpYtQv5E= -github.com/cloudflare/cloudflare-go v0.10.4/go.mod h1:4HgmUutVbZTRnHg91bS8lvlA0Wx+TgqttLDcwey2S6E= 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/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= @@ -105,7 +98,6 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -187,41 +179,12 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf 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/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= -github.com/hashicorp/consul/api v1.2.0 h1:oPsuzLp2uk7I7rojPKuncWbZ+m5TMoD4Ivs+2Rkeh4Y= -github.com/hashicorp/consul/api v1.2.0/go.mod h1:1SIkFYi2ZTXUE5Kgt179+4hH33djo11+0Eo2XgTAtkw= -github.com/hashicorp/consul/sdk v0.2.0 h1:GWFYFmry/k4b1hEoy7kSkmU8e30GAyI4VZHk0fRxeL4= -github.com/hashicorp/consul/sdk v0.2.0/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-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= -github.com/hashicorp/go-cleanhttp v0.5.1/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: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-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.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 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/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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= @@ -272,7 +235,6 @@ github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gN github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI= github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -285,22 +247,14 @@ github.com/micro/cli v0.2.0 h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA= github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= -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.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -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-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= -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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -345,8 +299,6 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= -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/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= 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= @@ -354,7 +306,6 @@ 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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -377,11 +328,8 @@ github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKc github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ= 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/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -436,7 +384,6 @@ go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/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= @@ -459,9 +406,7 @@ golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73r 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-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= @@ -474,7 +419,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191011234655-491137f69257 h1:ry8e2D+cwaV6hk7lb3aRTjjZo24shrbK0e11QEOkTIg= golang.org/x/net v0.0.0-20191011234655-491137f69257/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -487,11 +431,9 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ 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-20180622082034-63fc586f45fe/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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-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-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= From 776284b1873d6799bc726401e1fb0e5b10d80a03 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 23 Oct 2019 17:42:04 +0100 Subject: [PATCH 127/344] Make sure you dont overflow MaxInt64 --- network/default.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index 8490ce54..4f60dacd 100644 --- a/network/default.go +++ b/network/default.go @@ -767,7 +767,12 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { Metric: event.Route.Metric, } // calculate route metric and add to the advertised metric - route.Metric += n.getRouteMetric(event.Route.Router, event.Route.Gateway) + // we need to make sure we do not overflow math.MaxInt64 + if metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway); metric != math.MaxInt64 { + route.Metric += n.getRouteMetric(event.Route.Router, event.Route.Gateway) + } else { + route.Metric = metric + } // create router event e := &router.Event{ Type: router.EventType(event.Type), From b67be88952f584db50b9bb78ed11768c0210c94f Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 23 Oct 2019 19:48:26 +0100 Subject: [PATCH 128/344] Check for local links and empty gateways --- network/default.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/network/default.go b/network/default.go index 4f60dacd..57dd991e 100644 --- a/network/default.go +++ b/network/default.go @@ -304,6 +304,7 @@ func (n *network) acceptNetConn(l tunnel.Listener, recv chan *message) { } } +// updatePeerLinks updates link for a given peer func (n *network) updatePeerLinks(peerAddr string, linkId string) error { n.Lock() defer n.Unlock() @@ -367,6 +368,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { lastSeen: now, } // update peer links + log.Debugf("Network updating peer link %s for peer: %s", m.session.Link(), pbNetConnect.Node.Address) if err := n.updatePeerLinks(pbNetConnect.Node.Address, m.session.Link()); err != nil { log.Debugf("Network failed updating peer links: %s", err) } @@ -409,6 +411,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { lastSeen: now, } // update peer links + log.Debugf("Network updating peer link %s for peer: %s", m.session.Link(), pbNetPeer.Node.Address) if err := n.updatePeerLinks(pbNetPeer.Node.Address, m.session.Link()); err != nil { log.Debugf("Network failed updating peer links: %s", err) } @@ -691,11 +694,22 @@ func (n *network) getHopCount(rtr string) int { // getRouteMetric calculates router metric and returns it // Route metric is calculated based on link status and route hopd count -func (n *network) getRouteMetric(router string, gateway string) int64 { +func (n *network) getRouteMetric(router string, gateway string, link string) int64 { // set the route metric n.RLock() defer n.RUnlock() + if link == "local" && gateway == "" { + log.Debugf("Network link: %s, gateway: blank", link, gateway) + return 1 + } + + if link == "local" && gateway != "" { + log.Debugf("Network link: %s, gateway: %s", link, gateway) + return 2 + } + + log.Debugf("Network looking up %s link to gateway: %s", link, gateway) if link, ok := n.peerLinks[gateway]; ok { // maka sure delay is non-zero delay := link.Delay() @@ -711,6 +725,7 @@ func (n *network) getRouteMetric(router string, gateway string) int64 { } return (delay * length * int64(hops)) / 10e9 } + log.Debugf("Network failed to find a link to gateway: %s", gateway) return math.MaxInt64 } @@ -768,8 +783,9 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { } // calculate route metric and add to the advertised metric // we need to make sure we do not overflow math.MaxInt64 - if metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway); metric != math.MaxInt64 { - route.Metric += n.getRouteMetric(event.Route.Router, event.Route.Gateway) + log.Debugf("Network metric for router %s and gateway %s", event.Route.Router, event.Route.Gateway) + if metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link); metric != math.MaxInt64 { + route.Metric += metric } else { route.Metric = metric } @@ -843,7 +859,7 @@ func (n *network) advertise(advertChan <-chan *router.Advert) { address = fmt.Sprintf("%d", hasher.Sum64()) } // calculate route metric to advertise - metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway) + metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, DefaultLink) // NOTE: we override Gateway, Link and Address here route := &pbRtr.Route{ Service: event.Route.Service, From 71122836b8f94bc29d5fcb1a8005ac12ddbd3217 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 23 Oct 2019 19:55:01 +0100 Subject: [PATCH 129/344] Use event.Route.Link for getting the route metrics --- network/default.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index 57dd991e..eddb2b93 100644 --- a/network/default.go +++ b/network/default.go @@ -859,7 +859,7 @@ func (n *network) advertise(advertChan <-chan *router.Advert) { address = fmt.Sprintf("%d", hasher.Sum64()) } // calculate route metric to advertise - metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, DefaultLink) + metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link) // NOTE: we override Gateway, Link and Address here route := &pbRtr.Route{ Service: event.Route.Service, From 4f1dd3f9657e1564f7371bd73a0b039c65671961 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 23 Oct 2019 20:01:45 +0100 Subject: [PATCH 130/344] Fixed a small messup when printing logs --- network/default.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index eddb2b93..741c4fb8 100644 --- a/network/default.go +++ b/network/default.go @@ -700,7 +700,7 @@ func (n *network) getRouteMetric(router string, gateway string, link string) int defer n.RUnlock() if link == "local" && gateway == "" { - log.Debugf("Network link: %s, gateway: blank", link, gateway) + log.Debugf("Network link: %s, gateway: blank", link) return 1 } From 4e5a568063e72d8926287955f3820e22db6f4e5b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 21:24:31 +0100 Subject: [PATCH 131/344] races, race conditions everywhere --- tunnel/link.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tunnel/link.go b/tunnel/link.go index 036a4830..26b568fc 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -206,6 +206,9 @@ func (l *link) Id() string { } func (l *link) Close() error { + l.Lock() + defer l.Unlock() + select { case <-l.closed: return nil From ecac392dbee74ae0bd35206870d0dce47e5a67ad Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 21:54:37 +0100 Subject: [PATCH 132/344] unexport api response/message in cloudflare store --- store/cloudflare/cloudflare.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index 61bf592a..a9ae58f7 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -80,7 +80,7 @@ func (w *workersKV) Sync() ([]*store.Record, error) { if err != nil { return nil, err } - a := &APIResponse{} + a := &apiResponse{} if err := json.Unmarshal(response, a); err != nil { return nil, err } @@ -151,7 +151,7 @@ func (w *workersKV) Write(records ...*store.Record) error { if err != nil { return err } - a := &APIResponse{} + a := &apiResponse{} if err := json.Unmarshal(resp, a); err != nil { return err } @@ -180,7 +180,7 @@ func (w *workersKV) Delete(keys ...string) error { return err } - a := &APIResponse{} + a := &apiResponse{} if err := json.Unmarshal(resp, a); err != nil { return err } @@ -237,8 +237,8 @@ func (w *workersKV) request(ctx context.Context, method, path string, body inter return respBody, resp.Header, resp.StatusCode, nil } -// APIResponse is a cloudflare v4 api response -type APIResponse struct { +// apiResponse is a cloudflare v4 api response +type apiResponse struct { Result []struct { ID string `json:"id"` Type string `json:"type"` @@ -256,9 +256,9 @@ type APIResponse struct { CreatedOn time.Time `json:"created_on"` } `json:"result"` Success bool `json:"success"` - Errors []APIMessage `json:"errors"` + Errors []apiMessage `json:"errors"` // not sure Messages is ever populated? - Messages []APIMessage `json:"messages"` + Messages []apiMessage `json:"messages"` ResultInfo struct { Page int `json:"page"` PerPage int `json:"per_page"` @@ -267,8 +267,8 @@ type APIResponse struct { } `json:"result_info"` } -// APIMessage is a Cloudflare v4 API Error -type APIMessage struct { +// apiMessage is a Cloudflare v4 API Error +type apiMessage struct { Code int `json:"code"` Message string `json:"message"` } From 82f94c78612392296afe4daea5a1100b47a3e970 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 22:05:39 +0100 Subject: [PATCH 133/344] Change store.Sync to store.List --- store/cloudflare/cloudflare.go | 4 +- store/cloudflare/cloudflare_test.go | 6 +- store/etcd/etcd.go | 2 +- store/memory/memory.go | 2 +- store/service/handler/handler.go | 6 +- store/service/proto/store.micro.go | 164 ++++++++++---------- store/service/proto/store.pb.go | 228 ++++++++++++++-------------- store/service/proto/store.proto | 6 +- store/service/service.go | 4 +- store/store.go | 14 +- 10 files changed, 216 insertions(+), 220 deletions(-) diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index a9ae58f7..e39d7763 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -66,9 +66,9 @@ func New(opts ...options.Option) (store.Store, error) { }, nil } -// In the cloudflare workers KV implemention, Sync() doesn't guarantee +// In the cloudflare workers KV implemention, List() doesn't guarantee // anything as the workers API is eventually consistent. -func (w *workersKV) Sync() ([]*store.Record, error) { +func (w *workersKV) List() ([]*store.Record, error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() diff --git a/store/cloudflare/cloudflare_test.go b/store/cloudflare/cloudflare_test.go index ed73e796..e079a106 100644 --- a/store/cloudflare/cloudflare_test.go +++ b/store/cloudflare/cloudflare_test.go @@ -31,11 +31,11 @@ func TestCloudflare(t *testing.T) { t.Fatal(err.Error()) } - records, err := wkv.Sync() + records, err := wkv.List() if err != nil { - t.Fatalf("Sync: %s\n", err.Error()) + t.Fatalf("List: %s\n", err.Error()) } else { - t.Log("Synced " + strconv.Itoa(len(records)) + " records") + t.Log("Listed " + strconv.Itoa(len(records)) + " records") } err = wkv.Write( diff --git a/store/etcd/etcd.go b/store/etcd/etcd.go index bd3697c7..82b62902 100644 --- a/store/etcd/etcd.go +++ b/store/etcd/etcd.go @@ -68,7 +68,7 @@ func (e *ekv) Write(records ...*store.Record) error { return gerr } -func (e *ekv) Sync() ([]*store.Record, error) { +func (e *ekv) List() ([]*store.Record, error) { keyval, err := e.kv.Get(context.Background(), "/", client.WithPrefix()) if err != nil { return nil, err diff --git a/store/memory/memory.go b/store/memory/memory.go index 3eeab31d..aa5f645f 100644 --- a/store/memory/memory.go +++ b/store/memory/memory.go @@ -21,7 +21,7 @@ type memoryRecord struct { c time.Time } -func (m *memoryStore) Sync() ([]*store.Record, error) { +func (m *memoryStore) List() ([]*store.Record, error) { m.RLock() defer m.RUnlock() diff --git a/store/service/handler/handler.go b/store/service/handler/handler.go index 51af02b6..f4dd0710 100644 --- a/store/service/handler/handler.go +++ b/store/service/handler/handler.go @@ -55,19 +55,19 @@ func (s *Store) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.Delet return nil } -func (s *Store) Sync(ctx context.Context, req *pb.SyncRequest, stream pb.Store_SyncStream) error { +func (s *Store) List(ctx context.Context, req *pb.ListRequest, stream pb.Store_ListStream) error { var vals []*store.Record var err error if len(req.Key) > 0 { vals, err = s.Store.Read(req.Key) } else { - vals, err = s.Store.Sync() + vals, err = s.Store.List() } if err != nil { return errors.InternalServerError("go.micro.store", err.Error()) } - rsp := new(pb.SyncResponse) + rsp := new(pb.ListResponse) // TODO: batch sync for _, val := range vals { diff --git a/store/service/proto/store.micro.go b/store/service/proto/store.micro.go index ce4885ec..422387b9 100644 --- a/store/service/proto/store.micro.go +++ b/store/service/proto/store.micro.go @@ -34,10 +34,10 @@ var _ server.Option // Client API for Store service type StoreService interface { + List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (Store_ListService, error) Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) Write(ctx context.Context, in *WriteRequest, opts ...client.CallOption) (*WriteResponse, error) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) - Sync(ctx context.Context, in *SyncRequest, opts ...client.CallOption) (Store_SyncService, error) } type storeService struct { @@ -58,6 +58,50 @@ func NewStoreService(name string, c client.Client) StoreService { } } +func (c *storeService) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (Store_ListService, error) { + req := c.c.NewRequest(c.name, "Store.List", &ListRequest{}) + stream, err := c.c.Stream(ctx, req, opts...) + if err != nil { + return nil, err + } + if err := stream.Send(in); err != nil { + return nil, err + } + return &storeServiceList{stream}, nil +} + +type Store_ListService interface { + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Recv() (*ListResponse, error) +} + +type storeServiceList struct { + stream client.Stream +} + +func (x *storeServiceList) Close() error { + return x.stream.Close() +} + +func (x *storeServiceList) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *storeServiceList) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *storeServiceList) Recv() (*ListResponse, error) { + m := new(ListResponse) + err := x.stream.Recv(m) + if err != nil { + return nil, err + } + return m, nil +} + func (c *storeService) Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) { req := c.c.NewRequest(c.name, "Store.Read", in) out := new(ReadResponse) @@ -88,65 +132,21 @@ func (c *storeService) Delete(ctx context.Context, in *DeleteRequest, opts ...cl return out, nil } -func (c *storeService) Sync(ctx context.Context, in *SyncRequest, opts ...client.CallOption) (Store_SyncService, error) { - req := c.c.NewRequest(c.name, "Store.Sync", &SyncRequest{}) - stream, err := c.c.Stream(ctx, req, opts...) - if err != nil { - return nil, err - } - if err := stream.Send(in); err != nil { - return nil, err - } - return &storeServiceSync{stream}, nil -} - -type Store_SyncService interface { - SendMsg(interface{}) error - RecvMsg(interface{}) error - Close() error - Recv() (*SyncResponse, error) -} - -type storeServiceSync struct { - stream client.Stream -} - -func (x *storeServiceSync) Close() error { - return x.stream.Close() -} - -func (x *storeServiceSync) SendMsg(m interface{}) error { - return x.stream.Send(m) -} - -func (x *storeServiceSync) RecvMsg(m interface{}) error { - return x.stream.Recv(m) -} - -func (x *storeServiceSync) Recv() (*SyncResponse, error) { - m := new(SyncResponse) - err := x.stream.Recv(m) - if err != nil { - return nil, err - } - return m, nil -} - // Server API for Store service type StoreHandler interface { + List(context.Context, *ListRequest, Store_ListStream) error Read(context.Context, *ReadRequest, *ReadResponse) error Write(context.Context, *WriteRequest, *WriteResponse) error Delete(context.Context, *DeleteRequest, *DeleteResponse) error - Sync(context.Context, *SyncRequest, Store_SyncStream) error } func RegisterStoreHandler(s server.Server, hdlr StoreHandler, opts ...server.HandlerOption) error { type store interface { + List(ctx context.Context, stream server.Stream) error Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error Write(ctx context.Context, in *WriteRequest, out *WriteResponse) error Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error - Sync(ctx context.Context, stream server.Stream) error } type Store struct { store @@ -159,6 +159,41 @@ type storeHandler struct { StoreHandler } +func (h *storeHandler) List(ctx context.Context, stream server.Stream) error { + m := new(ListRequest) + if err := stream.Recv(m); err != nil { + return err + } + return h.StoreHandler.List(ctx, m, &storeListStream{stream}) +} + +type Store_ListStream interface { + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Send(*ListResponse) error +} + +type storeListStream struct { + stream server.Stream +} + +func (x *storeListStream) Close() error { + return x.stream.Close() +} + +func (x *storeListStream) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *storeListStream) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *storeListStream) Send(m *ListResponse) error { + return x.stream.Send(m) +} + func (h *storeHandler) Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error { return h.StoreHandler.Read(ctx, in, out) } @@ -170,38 +205,3 @@ func (h *storeHandler) Write(ctx context.Context, in *WriteRequest, out *WriteRe func (h *storeHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error { return h.StoreHandler.Delete(ctx, in, out) } - -func (h *storeHandler) Sync(ctx context.Context, stream server.Stream) error { - m := new(SyncRequest) - if err := stream.Recv(m); err != nil { - return err - } - return h.StoreHandler.Sync(ctx, m, &storeSyncStream{stream}) -} - -type Store_SyncStream interface { - SendMsg(interface{}) error - RecvMsg(interface{}) error - Close() error - Send(*SyncResponse) error -} - -type storeSyncStream struct { - stream server.Stream -} - -func (x *storeSyncStream) Close() error { - return x.stream.Close() -} - -func (x *storeSyncStream) SendMsg(m interface{}) error { - return x.stream.Send(m) -} - -func (x *storeSyncStream) RecvMsg(m interface{}) error { - return x.stream.Recv(m) -} - -func (x *storeSyncStream) Send(m *SyncResponse) error { - return x.stream.Send(m) -} diff --git a/store/service/proto/store.pb.go b/store/service/proto/store.pb.go index ce166cb7..6b8ddb04 100644 --- a/store/service/proto/store.pb.go +++ b/store/service/proto/store.pb.go @@ -298,7 +298,7 @@ func (m *DeleteResponse) XXX_DiscardUnknown() { var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo -type SyncRequest struct { +type ListRequest struct { // optional key Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -306,71 +306,71 @@ type SyncRequest struct { XXX_sizecache int32 `json:"-"` } -func (m *SyncRequest) Reset() { *m = SyncRequest{} } -func (m *SyncRequest) String() string { return proto.CompactTextString(m) } -func (*SyncRequest) ProtoMessage() {} -func (*SyncRequest) Descriptor() ([]byte, []int) { +func (m *ListRequest) Reset() { *m = ListRequest{} } +func (m *ListRequest) String() string { return proto.CompactTextString(m) } +func (*ListRequest) ProtoMessage() {} +func (*ListRequest) Descriptor() ([]byte, []int) { return fileDescriptor_f84ccc98e143ed3e, []int{7} } -func (m *SyncRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SyncRequest.Unmarshal(m, b) +func (m *ListRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListRequest.Unmarshal(m, b) } -func (m *SyncRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SyncRequest.Marshal(b, m, deterministic) +func (m *ListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListRequest.Marshal(b, m, deterministic) } -func (m *SyncRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_SyncRequest.Merge(m, src) +func (m *ListRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListRequest.Merge(m, src) } -func (m *SyncRequest) XXX_Size() int { - return xxx_messageInfo_SyncRequest.Size(m) +func (m *ListRequest) XXX_Size() int { + return xxx_messageInfo_ListRequest.Size(m) } -func (m *SyncRequest) XXX_DiscardUnknown() { - xxx_messageInfo_SyncRequest.DiscardUnknown(m) +func (m *ListRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListRequest.DiscardUnknown(m) } -var xxx_messageInfo_SyncRequest proto.InternalMessageInfo +var xxx_messageInfo_ListRequest proto.InternalMessageInfo -func (m *SyncRequest) GetKey() string { +func (m *ListRequest) GetKey() string { if m != nil { return m.Key } return "" } -type SyncResponse struct { +type ListResponse struct { Records []*Record `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } -func (m *SyncResponse) Reset() { *m = SyncResponse{} } -func (m *SyncResponse) String() string { return proto.CompactTextString(m) } -func (*SyncResponse) ProtoMessage() {} -func (*SyncResponse) Descriptor() ([]byte, []int) { +func (m *ListResponse) Reset() { *m = ListResponse{} } +func (m *ListResponse) String() string { return proto.CompactTextString(m) } +func (*ListResponse) ProtoMessage() {} +func (*ListResponse) Descriptor() ([]byte, []int) { return fileDescriptor_f84ccc98e143ed3e, []int{8} } -func (m *SyncResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SyncResponse.Unmarshal(m, b) +func (m *ListResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListResponse.Unmarshal(m, b) } -func (m *SyncResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SyncResponse.Marshal(b, m, deterministic) +func (m *ListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListResponse.Marshal(b, m, deterministic) } -func (m *SyncResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_SyncResponse.Merge(m, src) +func (m *ListResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListResponse.Merge(m, src) } -func (m *SyncResponse) XXX_Size() int { - return xxx_messageInfo_SyncResponse.Size(m) +func (m *ListResponse) XXX_Size() int { + return xxx_messageInfo_ListResponse.Size(m) } -func (m *SyncResponse) XXX_DiscardUnknown() { - xxx_messageInfo_SyncResponse.DiscardUnknown(m) +func (m *ListResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListResponse.DiscardUnknown(m) } -var xxx_messageInfo_SyncResponse proto.InternalMessageInfo +var xxx_messageInfo_ListResponse proto.InternalMessageInfo -func (m *SyncResponse) GetRecords() []*Record { +func (m *ListResponse) GetRecords() []*Record { if m != nil { return m.Records } @@ -385,8 +385,8 @@ func init() { proto.RegisterType((*WriteResponse)(nil), "go.micro.store.WriteResponse") proto.RegisterType((*DeleteRequest)(nil), "go.micro.store.DeleteRequest") proto.RegisterType((*DeleteResponse)(nil), "go.micro.store.DeleteResponse") - proto.RegisterType((*SyncRequest)(nil), "go.micro.store.SyncRequest") - proto.RegisterType((*SyncResponse)(nil), "go.micro.store.SyncResponse") + proto.RegisterType((*ListRequest)(nil), "go.micro.store.ListRequest") + proto.RegisterType((*ListResponse)(nil), "go.micro.store.ListResponse") } func init() { @@ -395,27 +395,27 @@ func init() { var fileDescriptor_f84ccc98e143ed3e = []byte{ // 333 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0xcb, 0x6e, 0xf2, 0x30, - 0x10, 0x85, 0x09, 0x81, 0xfc, 0x62, 0xb8, 0xfc, 0x68, 0x54, 0xa1, 0x88, 0xde, 0xd2, 0x74, 0x93, - 0x4d, 0x03, 0xa2, 0x2f, 0x50, 0xa9, 0x17, 0xb5, 0x5b, 0xb3, 0xe8, 0x9a, 0x86, 0x11, 0x8a, 0xa0, - 0x98, 0x3a, 0x01, 0x35, 0x2f, 0xd4, 0xe7, 0xac, 0x6c, 0x27, 0x69, 0x90, 0x41, 0xaa, 0xba, 0x1b, - 0x7b, 0xce, 0x1c, 0x9f, 0xf9, 0x64, 0x08, 0xdf, 0xe3, 0x48, 0xf0, 0xd1, 0x82, 0xdf, 0xe8, 0x22, - 0x49, 0xb9, 0xa0, 0x51, 0x42, 0x62, 0x17, 0x47, 0x34, 0xda, 0x08, 0x9e, 0xe6, 0x77, 0xa1, 0xaa, - 0xb1, 0xb7, 0xe0, 0x7a, 0x24, 0x54, 0xb7, 0xfe, 0x33, 0x38, 0x8c, 0x22, 0x2e, 0xe6, 0xd8, 0x07, - 0x7b, 0x49, 0x99, 0x6b, 0x79, 0x56, 0xd0, 0x62, 0xb2, 0xc4, 0x13, 0x68, 0xee, 0x66, 0xab, 0x2d, - 0xb9, 0x75, 0xcf, 0x0a, 0x3a, 0x4c, 0x1f, 0x70, 0x00, 0x0e, 0x7d, 0x6e, 0x62, 0x91, 0xb9, 0xb6, - 0x67, 0x05, 0x36, 0xcb, 0x4f, 0xfe, 0x15, 0xb4, 0x19, 0xcd, 0xe6, 0x8c, 0x3e, 0xb6, 0x94, 0xa4, - 0x88, 0xd0, 0x58, 0x52, 0x96, 0xb8, 0x96, 0x67, 0x07, 0x2d, 0xa6, 0x6a, 0xff, 0x0e, 0x3a, 0x5a, - 0x92, 0x6c, 0xf8, 0x3a, 0x21, 0x1c, 0xc3, 0x3f, 0xa1, 0x1e, 0xd7, 0xb2, 0xf6, 0x64, 0x10, 0xee, - 0xc7, 0x0b, 0x75, 0x36, 0x56, 0xc8, 0xa4, 0xc3, 0xab, 0x88, 0x53, 0x2a, 0x5e, 0xa9, 0x38, 0xd4, - 0x7f, 0xe7, 0xf0, 0x1f, 0xba, 0xb9, 0x83, 0x0e, 0xe1, 0x5f, 0x43, 0xf7, 0x81, 0x56, 0xf4, 0xe3, - 0x79, 0x28, 0x79, 0x1f, 0x7a, 0x85, 0x28, 0x1f, 0xbb, 0x84, 0xf6, 0x34, 0x5b, 0x47, 0xc5, 0x90, - 0x41, 0x4f, 0x46, 0xd5, 0x82, 0xbf, 0x2e, 0x3b, 0xf9, 0xaa, 0x43, 0x73, 0x2a, 0x3b, 0x78, 0x0f, - 0x0d, 0x09, 0x0e, 0x4f, 0xcd, 0x91, 0x92, 0xf8, 0xf0, 0xec, 0x70, 0x33, 0xcf, 0x5b, 0xc3, 0x27, - 0x68, 0xaa, 0xcd, 0xd1, 0x10, 0x56, 0x91, 0x0e, 0xcf, 0x8f, 0x74, 0x4b, 0x9f, 0x17, 0x70, 0x34, - 0x0b, 0x34, 0xa4, 0x7b, 0x20, 0x87, 0x17, 0xc7, 0xda, 0xa5, 0xd5, 0x23, 0x34, 0x24, 0x23, 0x73, - 0xaf, 0x0a, 0x5a, 0x73, 0xaf, 0x2a, 0x56, 0xbf, 0x36, 0xb6, 0xde, 0x1c, 0xf5, 0xb7, 0x6f, 0xbf, - 0x03, 0x00, 0x00, 0xff, 0xff, 0x30, 0xc8, 0x99, 0x52, 0x0d, 0x03, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0x4d, 0x4f, 0xc2, 0x40, + 0x10, 0x86, 0x59, 0x0a, 0x35, 0x0c, 0x1f, 0x92, 0x89, 0x21, 0x0d, 0x7e, 0xd5, 0x7a, 0xe9, 0xc5, + 0x42, 0xf0, 0x0f, 0x98, 0xf8, 0x11, 0x4d, 0x3c, 0xad, 0x07, 0xcf, 0x08, 0x13, 0xd2, 0x80, 0x2e, + 0xee, 0x16, 0x62, 0xff, 0x90, 0xbf, 0xd3, 0xec, 0x6e, 0xab, 0xc5, 0x42, 0x62, 0xbc, 0xcd, 0xee, + 0xbc, 0xf3, 0xec, 0xdb, 0x79, 0x0b, 0xd1, 0x6b, 0x3c, 0x91, 0x62, 0x30, 0x13, 0x17, 0xb6, 0x50, + 0x89, 0x90, 0x34, 0x50, 0x24, 0xd7, 0xf1, 0x84, 0x06, 0x4b, 0x29, 0x92, 0xec, 0x2e, 0x32, 0x35, + 0x76, 0x66, 0xc2, 0x8e, 0x44, 0xe6, 0x36, 0xb8, 0x07, 0x97, 0xd3, 0x44, 0xc8, 0x29, 0x76, 0xc1, + 0x99, 0x53, 0xea, 0x31, 0x9f, 0x85, 0x0d, 0xae, 0x4b, 0x3c, 0x80, 0xfa, 0x7a, 0xbc, 0x58, 0x91, + 0x57, 0xf5, 0x59, 0xd8, 0xe2, 0xf6, 0x80, 0x3d, 0x70, 0xe9, 0x63, 0x19, 0xcb, 0xd4, 0x73, 0x7c, + 0x16, 0x3a, 0x3c, 0x3b, 0x05, 0x67, 0xd0, 0xe4, 0x34, 0x9e, 0x72, 0x7a, 0x5f, 0x91, 0x4a, 0x10, + 0xa1, 0x36, 0xa7, 0x54, 0x79, 0xcc, 0x77, 0xc2, 0x06, 0x37, 0x75, 0x70, 0x05, 0x2d, 0x2b, 0x51, + 0x4b, 0xf1, 0xa6, 0x08, 0x87, 0xb0, 0x27, 0xcd, 0xe3, 0x56, 0xd6, 0x1c, 0xf5, 0xa2, 0x4d, 0x7b, + 0x91, 0xf5, 0xc6, 0x73, 0x99, 0x26, 0x3c, 0xcb, 0x38, 0xa1, 0xfc, 0x95, 0x02, 0xa1, 0xfa, 0x37, + 0xc2, 0x3e, 0xb4, 0x33, 0x82, 0x35, 0x11, 0x9c, 0x43, 0xfb, 0x86, 0x16, 0xf4, 0xc3, 0xdc, 0xe6, + 0xbc, 0x0b, 0x9d, 0x5c, 0x94, 0x8d, 0x9d, 0x42, 0xf3, 0x31, 0x56, 0x49, 0x3e, 0x54, 0xda, 0x9e, + 0xb6, 0x6a, 0x05, 0xff, 0xfd, 0xd8, 0xd1, 0x67, 0x15, 0xea, 0x4f, 0xba, 0x83, 0xb7, 0x50, 0xd3, + 0x2c, 0x3c, 0xfc, 0x3d, 0x52, 0xb0, 0xd0, 0x3f, 0xda, 0xde, 0xcc, 0xfc, 0x56, 0x86, 0x0c, 0xaf, + 0xa1, 0xa6, 0xf7, 0x5f, 0xc6, 0x14, 0x82, 0x2b, 0x63, 0x8a, 0x91, 0x05, 0x15, 0xbc, 0x83, 0xba, + 0x59, 0x20, 0x96, 0x84, 0xc5, 0x64, 0xfa, 0xc7, 0x3b, 0xba, 0xdf, 0x9c, 0x07, 0x70, 0xed, 0x4a, + 0xb1, 0x24, 0xdd, 0xc8, 0xa3, 0x7f, 0xb2, 0xab, 0x9d, 0xa3, 0x5e, 0x5c, 0xf3, 0x6f, 0x5f, 0x7e, + 0x05, 0x00, 0x00, 0xff, 0xff, 0x30, 0x48, 0x25, 0x2d, 0x0d, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -430,10 +430,10 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type StoreClient interface { + List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (Store_ListClient, error) Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error) Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) - Sync(ctx context.Context, in *SyncRequest, opts ...grpc.CallOption) (Store_SyncClient, error) } type storeClient struct { @@ -444,6 +444,38 @@ func NewStoreClient(cc *grpc.ClientConn) StoreClient { return &storeClient{cc} } +func (c *storeClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (Store_ListClient, error) { + stream, err := c.cc.NewStream(ctx, &_Store_serviceDesc.Streams[0], "/go.micro.store.Store/List", opts...) + if err != nil { + return nil, err + } + x := &storeListClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Store_ListClient interface { + Recv() (*ListResponse, error) + grpc.ClientStream +} + +type storeListClient struct { + grpc.ClientStream +} + +func (x *storeListClient) Recv() (*ListResponse, error) { + m := new(ListResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *storeClient) Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error) { out := new(ReadResponse) err := c.cc.Invoke(ctx, "/go.micro.store.Store/Read", in, out, opts...) @@ -471,50 +503,39 @@ func (c *storeClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grp return out, nil } -func (c *storeClient) Sync(ctx context.Context, in *SyncRequest, opts ...grpc.CallOption) (Store_SyncClient, error) { - stream, err := c.cc.NewStream(ctx, &_Store_serviceDesc.Streams[0], "/go.micro.store.Store/Sync", opts...) - if err != nil { - return nil, err - } - x := &storeSyncClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Store_SyncClient interface { - Recv() (*SyncResponse, error) - grpc.ClientStream -} - -type storeSyncClient struct { - grpc.ClientStream -} - -func (x *storeSyncClient) Recv() (*SyncResponse, error) { - m := new(SyncResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - // StoreServer is the server API for Store service. type StoreServer interface { + List(*ListRequest, Store_ListServer) error Read(context.Context, *ReadRequest) (*ReadResponse, error) Write(context.Context, *WriteRequest) (*WriteResponse, error) Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) - Sync(*SyncRequest, Store_SyncServer) error } func RegisterStoreServer(s *grpc.Server, srv StoreServer) { s.RegisterService(&_Store_serviceDesc, srv) } +func _Store_List_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(StoreServer).List(m, &storeListServer{stream}) +} + +type Store_ListServer interface { + Send(*ListResponse) error + grpc.ServerStream +} + +type storeListServer struct { + grpc.ServerStream +} + +func (x *storeListServer) Send(m *ListResponse) error { + return x.ServerStream.SendMsg(m) +} + func _Store_Read_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ReadRequest) if err := dec(in); err != nil { @@ -569,27 +590,6 @@ func _Store_Delete_Handler(srv interface{}, ctx context.Context, dec func(interf return interceptor(ctx, in, info, handler) } -func _Store_Sync_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SyncRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(StoreServer).Sync(m, &storeSyncServer{stream}) -} - -type Store_SyncServer interface { - Send(*SyncResponse) error - grpc.ServerStream -} - -type storeSyncServer struct { - grpc.ServerStream -} - -func (x *storeSyncServer) Send(m *SyncResponse) error { - return x.ServerStream.SendMsg(m) -} - var _Store_serviceDesc = grpc.ServiceDesc{ ServiceName: "go.micro.store.Store", HandlerType: (*StoreServer)(nil), @@ -609,8 +609,8 @@ var _Store_serviceDesc = grpc.ServiceDesc{ }, Streams: []grpc.StreamDesc{ { - StreamName: "Sync", - Handler: _Store_Sync_Handler, + StreamName: "List", + Handler: _Store_List_Handler, ServerStreams: true, }, }, diff --git a/store/service/proto/store.proto b/store/service/proto/store.proto index a5abe4aa..5f9ea233 100644 --- a/store/service/proto/store.proto +++ b/store/service/proto/store.proto @@ -3,10 +3,10 @@ syntax = "proto3"; package go.micro.store; service Store { + rpc List(ListRequest) returns (stream ListResponse) {}; rpc Read(ReadRequest) returns (ReadResponse) {}; rpc Write(WriteRequest) returns (WriteResponse) {}; rpc Delete(DeleteRequest) returns (DeleteResponse) {}; - rpc Sync(SyncRequest) returns (stream SyncResponse) {}; } message Record { @@ -38,11 +38,11 @@ message DeleteRequest { message DeleteResponse {} -message SyncRequest { +message ListRequest { // optional key string key = 1; } -message SyncResponse { +message ListResponse { repeated Record records = 1; } diff --git a/store/service/service.go b/store/service/service.go index d7cc3805..b3f8ad56 100644 --- a/store/service/service.go +++ b/store/service/service.go @@ -23,8 +23,8 @@ type serviceStore struct { } // Sync all the known records -func (s *serviceStore) Sync() ([]*store.Record, error) { - stream, err := s.Client.Sync(context.Background(), &pb.SyncRequest{}, client.WithAddress(s.Nodes...)) +func (s *serviceStore) List() ([]*store.Record, error) { + stream, err := s.Client.List(context.Background(), &pb.ListRequest{}, client.WithAddress(s.Nodes...)) if err != nil { return nil, err } diff --git a/store/store.go b/store/store.go index e3d8efac..c45712eb 100644 --- a/store/store.go +++ b/store/store.go @@ -4,8 +4,6 @@ package store import ( "errors" "time" - - "github.com/micro/go-micro/config/options" ) var ( @@ -14,16 +12,14 @@ var ( // Store is a data storage interface type Store interface { - // embed options - options.Options - // Sync all the known records - Sync() ([]*Record, error) + // List all the known records + List() ([]*Record, error) // Read a record with key - Read(keys ...string) ([]*Record, error) + Read(key ...string) ([]*Record, error) // Write a record - Write(recs ...*Record) error + Write(rec ...*Record) error // Delete a record with key - Delete(keys ...string) error + Delete(key ...string) error } // Record represents a data record From 3fc04f4dfffa3be42665a666de633953ce9556d5 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 22:15:15 +0100 Subject: [PATCH 134/344] fixup some acme related things --- api/server/acme/certmagic/certmagic.go | 22 +++++++++------------- api/server/acme/certmagic/storage.go | 2 +- api/server/acme/options.go | 12 ++++++------ 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/api/server/acme/certmagic/certmagic.go b/api/server/acme/certmagic/certmagic.go index cde5783d..4a3a464b 100644 --- a/api/server/acme/certmagic/certmagic.go +++ b/api/server/acme/certmagic/certmagic.go @@ -13,7 +13,7 @@ import ( ) type certmagicProvider struct { - opts *acme.Options + opts acme.Options } func (c *certmagicProvider) NewListener(ACMEHosts ...string) (net.Listener, error) { @@ -40,23 +40,19 @@ func (c *certmagicProvider) NewListener(ACMEHosts ...string) (net.Listener, erro // New returns a certmagic provider func New(options ...acme.Option) acme.Provider { - o := &acme.Options{} - if len(options) == 0 { - for _, op := range acme.Default() { - op(o) - } - } else { - for _, op := range options { - op(o) - } + opts := acme.DefaultOptions() + + for _, o := range options { + o(&opts) } - if o.Cache != nil { - if _, ok := o.Cache.(certmagic.Storage); !ok { + + if opts.Cache != nil { + if _, ok := opts.Cache.(certmagic.Storage); !ok { log.Fatal("ACME: cache provided doesn't implement certmagic's Storage interface") } } return &certmagicProvider{ - opts: o, + opts: opts, } } diff --git a/api/server/acme/certmagic/storage.go b/api/server/acme/certmagic/storage.go index b91b5db6..6b8e04fb 100644 --- a/api/server/acme/certmagic/storage.go +++ b/api/server/acme/certmagic/storage.go @@ -89,7 +89,7 @@ func (s *storage) Exists(key string) bool { } func (s *storage) List(prefix string, recursive bool) ([]string, error) { - records, err := s.store.Sync() + records, err := s.store.List() if err != nil { return nil, err } diff --git a/api/server/acme/options.go b/api/server/acme/options.go index cd7f55fd..04811b98 100644 --- a/api/server/acme/options.go +++ b/api/server/acme/options.go @@ -63,11 +63,11 @@ func Cache(c interface{}) Option { } } -// Default uses the Let's Encrypt Production CA, with DNS Challenge disabled. -func Default() []Option { - return []Option{ - AcceptToS(true), - CA(LetsEncryptProductionCA), - OnDemand(true), +// DefaultOptions uses the Let's Encrypt Production CA, with DNS Challenge disabled. +func DefaultOptions() Options { + return Options{ + AcceptToS: true, + CA: LetsEncryptProductionCA, + OnDemand: true, } } From d65658c89003b2ba2a56412d25c10a29e0579c09 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 22:31:36 +0100 Subject: [PATCH 135/344] Update options usage in store/api --- api/server/acme/certmagic/certmagic_test.go | 55 ++++++++++----------- api/server/acme/options.go | 4 +- store/cloudflare/cloudflare.go | 2 +- store/cloudflare/cloudflare_test.go | 9 ++-- store/cloudflare/options.go | 23 +++++++++ 5 files changed, 57 insertions(+), 36 deletions(-) create mode 100644 store/cloudflare/options.go diff --git a/api/server/acme/certmagic/certmagic_test.go b/api/server/acme/certmagic/certmagic_test.go index 8474b0bd..59afe557 100644 --- a/api/server/acme/certmagic/certmagic_test.go +++ b/api/server/acme/certmagic/certmagic_test.go @@ -11,8 +11,7 @@ import ( "github.com/go-acme/lego/v3/providers/dns/cloudflare" "github.com/mholt/certmagic" "github.com/micro/go-micro/api/server/acme" - "github.com/micro/go-micro/config/options" - cloudflarestorage "github.com/micro/go-micro/store/cloudflare" + cfstore "github.com/micro/go-micro/store/cloudflare" "github.com/micro/go-micro/sync/lock/memory" ) @@ -22,7 +21,7 @@ func TestCertMagic(t *testing.T) { } l, err := New().NewListener() if err != nil { - t.Error(err.Error()) + t.Fatal(err.Error()) } l.Close() @@ -34,7 +33,7 @@ func TestCertMagic(t *testing.T) { p, err := cloudflare.NewDNSProviderConfig(c) if err != nil { - t.Error(err.Error()) + t.Fatal(err.Error()) } l, err = New(acme.AcceptToS(true), @@ -43,7 +42,7 @@ func TestCertMagic(t *testing.T) { ).NewListener() if err != nil { - t.Error(err.Error()) + t.Fatal(err.Error()) } l.Close() } @@ -56,10 +55,10 @@ func TestStorageImplementation(t *testing.T) { } var s certmagic.Storage - st, err := cloudflarestorage.New( - options.WithValue("CF_API_TOKEN", apiToken), - options.WithValue("CF_ACCOUNT_ID", accountID), - options.WithValue("KV_NAMESPACE_ID", kvID), + st, err := cfstore.NewStore( + cfstore.ApiToken(apiToken), + cfstore.AccountID(accountID), + cfstore.Namespace(kvID), ) if err != nil { t.Fatalf("Couldn't initialise cloudflare storage: %s\n", err.Error()) @@ -71,12 +70,12 @@ func TestStorageImplementation(t *testing.T) { // Test Lock if err := s.Lock("test"); err != nil { - t.Error(err) + t.Fatal(err) } // Test Unlock if err := s.Unlock("test"); err != nil { - t.Error(err) + t.Fatal(err) } // Test data @@ -107,17 +106,17 @@ func TestStorageImplementation(t *testing.T) { // Test Store for _, d := range testdata { if err := s.Store(d.key, d.value); err != nil { - t.Error(err.Error()) + t.Fatal(err.Error()) } } // Test Load for _, d := range testdata { if value, err := s.Load(d.key); err != nil { - t.Error(err.Error()) + t.Fatal(err.Error()) } else { if !reflect.DeepEqual(value, d.value) { - t.Errorf("Load %s: expected %v, got %v", d.key, d.value, value) + t.Fatalf("Load %s: expected %v, got %v", d.key, d.value, value) } } } @@ -125,13 +124,13 @@ func TestStorageImplementation(t *testing.T) { // Test Exists for _, d := range testdata { if !s.Exists(d.key) { - t.Errorf("%s should exist, but doesn't\n", d.key) + t.Fatalf("%s should exist, but doesn't\n", d.key) } } // Test List if list, err := s.List("/", true); err != nil { - t.Error(err.Error()) + t.Fatal(err.Error()) } else { var expected []string for i, d := range testdata { @@ -143,16 +142,16 @@ func TestStorageImplementation(t *testing.T) { sort.Strings(expected) sort.Strings(list) if !reflect.DeepEqual(expected, list) { - t.Errorf("List: Expected %v, got %v\n", expected, list) + t.Fatalf("List: Expected %v, got %v\n", expected, list) } } if list, err := s.List("/foo", false); err != nil { - t.Error(err.Error()) + t.Fatal(err.Error()) } else { sort.Strings(list) expected := []string{"/foo/a", "/foo/b", "/foo/bar", "/foo/c", "/foo/d"} if !reflect.DeepEqual(expected, list) { - t.Errorf("List: expected %s, got %s\n", expected, list) + t.Fatalf("List: expected %s, got %s\n", expected, list) } } @@ -160,16 +159,16 @@ func TestStorageImplementation(t *testing.T) { for _, d := range testdata { info, err := s.Stat(d.key) if err != nil { - t.Error(err.Error()) + t.Fatal(err.Error()) } else { if info.Key != d.key { - t.Errorf("Stat().Key: expected %s, got %s\n", d.key, info.Key) + t.Fatalf("Stat().Key: expected %s, got %s\n", d.key, info.Key) } if info.Size != int64(len(d.value)) { - t.Errorf("Stat().Size: expected %d, got %d\n", len(d.value), info.Size) + t.Fatalf("Stat().Size: expected %d, got %d\n", len(d.value), info.Size) } if time.Since(info.Modified) > time.Minute { - t.Errorf("Stat().Modified: expected time since last modified to be < 1 minute, got %v\n", time.Since(info.Modified)) + t.Fatalf("Stat().Modified: expected time since last modified to be < 1 minute, got %v\n", time.Since(info.Modified)) } } @@ -178,7 +177,7 @@ func TestStorageImplementation(t *testing.T) { // Test Delete for _, d := range testdata { if err := s.Delete(d.key); err != nil { - t.Error(err.Error()) + t.Fatal(err.Error()) } } @@ -196,10 +195,10 @@ func TestE2e(t *testing.T) { } testLock := memory.NewLock() - testStore, err := cloudflarestorage.New( - options.WithValue("CF_API_TOKEN", apiToken), - options.WithValue("CF_ACCOUNT_ID", accountID), - options.WithValue("KV_NAMESPACE_ID", kvID), + testStore, err := cfstore.NewStore( + cfstore.ApiToken(apiToken), + cfstore.AccountID(accountID), + cfstore.Namespace(kvID), ) if err != nil { t.Fatal(err.Error()) diff --git a/api/server/acme/options.go b/api/server/acme/options.go index 04811b98..decab3d6 100644 --- a/api/server/acme/options.go +++ b/api/server/acme/options.go @@ -67,7 +67,7 @@ func Cache(c interface{}) Option { func DefaultOptions() Options { return Options{ AcceptToS: true, - CA: LetsEncryptProductionCA, - OnDemand: true, + CA: LetsEncryptProductionCA, + OnDemand: true, } } diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index e39d7763..c026ea84 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -32,7 +32,7 @@ type workersKV struct { // Options expects CF_API_TOKEN to a cloudflare API token scoped to Workers KV, // CF_ACCOUNT_ID to contain a string with your cloudflare account ID and // KV_NAMESPACE_ID to contain the namespace UUID for your KV storage. -func New(opts ...options.Option) (store.Store, error) { +func NewStore(opts ...options.Option) (store.Store, error) { // Validate Options options := options.NewOptions(opts...) apiToken, ok := options.Values().Get("CF_API_TOKEN") diff --git a/store/cloudflare/cloudflare_test.go b/store/cloudflare/cloudflare_test.go index e079a106..6b5a6815 100644 --- a/store/cloudflare/cloudflare_test.go +++ b/store/cloudflare/cloudflare_test.go @@ -7,7 +7,6 @@ import ( "testing" "time" - "github.com/micro/go-micro/config/options" "github.com/micro/go-micro/store" ) @@ -21,10 +20,10 @@ func TestCloudflare(t *testing.T) { randomK := strconv.Itoa(rand.Int()) randomV := strconv.Itoa(rand.Int()) - wkv, err := New( - options.WithValue("CF_API_TOKEN", apiToken), - options.WithValue("CF_ACCOUNT_ID", accountID), - options.WithValue("KV_NAMESPACE_ID", kvID), + wkv, err := NewStore( + ApiToken(apiToken), + AccountID(accountID), + Namespace(kvID), ) if err != nil { diff --git a/store/cloudflare/options.go b/store/cloudflare/options.go new file mode 100644 index 00000000..f09df9d6 --- /dev/null +++ b/store/cloudflare/options.go @@ -0,0 +1,23 @@ +package cloudflare + +import ( + "github.com/micro/go-micro/config/options" +) + +// Token sets the cloudflare api token +func ApiToken(t string) options.Option { + // TODO: change to store.cf.api_token + return options.WithValue("CF_API_TOKEN", t) +} + +// AccountID sets the cloudflare account id +func AccountID(id string) options.Option { + // TODO: change to store.cf.account_id + return options.WithValue("CF_ACCOUNT_ID", id) +} + +// Namespace sets the KV namespace +func Namespace(ns string) options.Option { + // TODO: change to store.cf.namespace + return options.WithValue("KV_NAMESPACE_ID", ns) +} From fb3d72968166cd841de94cf6b95c193a893e7460 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 22:35:28 +0100 Subject: [PATCH 136/344] sync map uses store list --- sync/map.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sync/map.go b/sync/map.go index a9611ff0..b19a9c43 100644 --- a/sync/map.go +++ b/sync/map.go @@ -89,7 +89,7 @@ func (m *syncMap) Delete(key interface{}) error { } func (m *syncMap) Iterate(fn func(key, val interface{}) error) error { - keyvals, err := m.opts.Store.Sync() + keyvals, err := m.opts.Store.List() if err != nil { return err } From 3ce71e12ff80504802a55e750f246042376e63fe Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 22:51:08 +0100 Subject: [PATCH 137/344] Don't recall vals everywhere --- store/cloudflare/cloudflare.go | 70 +++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index c026ea84..21e0f686 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -25,6 +25,13 @@ const apiBaseURL = "https://api.cloudflare.com/client/v4/" type workersKV struct { options.Options + // cf account id + account string + // cf api token + token string + // cf kv namespace + namespace string + // http client to use httpClient *http.Client } @@ -35,32 +42,37 @@ type workersKV struct { func NewStore(opts ...options.Option) (store.Store, error) { // Validate Options options := options.NewOptions(opts...) + + var account, token, namespace string + apiToken, ok := options.Values().Get("CF_API_TOKEN") if !ok { log.Fatal("Store: No CF_API_TOKEN passed as an option") } - _, ok = apiToken.(string) - if !ok { + if token, ok = apiToken.(string); !ok { log.Fatal("Store: Option CF_API_TOKEN contains a non-string") } + accountID, ok := options.Values().Get("CF_ACCOUNT_ID") if !ok { log.Fatal("Store: No CF_ACCOUNT_ID passed as an option") } - _, ok = accountID.(string) - if !ok { + if account, ok = accountID.(string); !ok { log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string") } + uuid, ok := options.Values().Get("KV_NAMESPACE_ID") if !ok { log.Fatal("Store: No KV_NAMESPACE_ID passed as an option") } - _, ok = uuid.(string) - if !ok { + if namespace, ok = uuid.(string); !ok { log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string") } return &workersKV{ + account: account, + namespace: namespace, + token: token, Options: options, httpClient: &http.Client{}, }, nil @@ -72,18 +84,18 @@ func (w *workersKV) List() ([]*store.Record, error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID") - kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID") + path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/keys", w.account, w.namespace) - path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/keys", accountID.(string), kvID.(string)) response, _, _, err := w.request(ctx, http.MethodGet, path, nil, make(http.Header)) if err != nil { return nil, err } + a := &apiResponse{} if err := json.Unmarshal(response, a); err != nil { return nil, err } + if !a.Success { messages := "" for _, m := range a.Errors { @@ -93,9 +105,11 @@ func (w *workersKV) List() ([]*store.Record, error) { } var keys []string + for _, r := range a.Result { keys = append(keys, r.Name) } + return w.Read(keys...) } @@ -103,12 +117,10 @@ func (w *workersKV) Read(keys ...string) ([]*store.Record, error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID") - kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID") - var records []*store.Record + for _, k := range keys { - path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", accountID.(string), kvID.(string), url.PathEscape(k)) + path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", w.account, w.namespace, url.PathEscape(k)) response, headers, status, err := w.request(ctx, http.MethodGet, path, nil, make(http.Header)) if err != nil { return records, err @@ -129,6 +141,7 @@ func (w *workersKV) Read(keys ...string) ([]*store.Record, error) { } records = append(records, record) } + return records, nil } @@ -136,25 +149,26 @@ func (w *workersKV) Write(records ...*store.Record) error { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID") - kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID") - for _, r := range records { - path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", accountID.(string), kvID.(string), url.PathEscape(r.Key)) + path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", w.account, w.namespace, url.PathEscape(r.Key)) if r.Expiry != 0 { // Minimum cloudflare TTL is 60 Seconds exp := int(math.Max(60, math.Round(r.Expiry.Seconds()))) path = path + "?expiration_ttl=" + strconv.Itoa(exp) } + headers := make(http.Header) + resp, _, _, err := w.request(ctx, http.MethodPut, path, r.Value, headers) if err != nil { return err } + a := &apiResponse{} if err := json.Unmarshal(resp, a); err != nil { return err } + if !a.Success { messages := "" for _, m := range a.Errors { @@ -163,6 +177,7 @@ func (w *workersKV) Write(records ...*store.Record) error { return errors.New(messages) } } + return nil } @@ -170,11 +185,8 @@ func (w *workersKV) Delete(keys ...string) error { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID") - kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID") - for _, k := range keys { - path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", accountID.(string), kvID.(string), url.PathEscape(k)) + path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", w.account, w.namespace, url.PathEscape(k)) resp, _, _, err := w.request(ctx, http.MethodDelete, path, nil, make(http.Header)) if err != nil { return err @@ -184,6 +196,7 @@ func (w *workersKV) Delete(keys ...string) error { if err := json.Unmarshal(resp, a); err != nil { return err } + if !a.Success { messages := "" for _, m := range a.Errors { @@ -192,6 +205,7 @@ func (w *workersKV) Delete(keys ...string) error { return errors.New(messages) } } + return nil } @@ -211,29 +225,39 @@ func (w *workersKV) request(ctx context.Context, method, path string, body inter } else { jsonBody = nil } + var reqBody io.Reader + if jsonBody != nil { reqBody = bytes.NewReader(jsonBody) } + req, err := http.NewRequestWithContext(ctx, method, apiBaseURL+path, reqBody) for key, value := range headers { req.Header[key] = value } - if token, found := w.Options.Values().Get("CF_API_TOKEN"); found { - req.Header.Set("Authorization", "Bearer "+token.(string)) + + // set token if it exists + if len(w.token) > 0 { + req.Header.Set("Authorization", "Bearer "+w.token) } + + // set the user agent to micro req.Header.Set("User-Agent", "micro/1.0 (https://micro.mu)") // Official cloudflare client does exponential backoff here + // TODO: retry and use util/backoff resp, err := w.httpClient.Do(req) if err != nil { return nil, nil, 0, err } defer resp.Body.Close() + respBody, err := ioutil.ReadAll(resp.Body) if err != nil { return respBody, resp.Header, resp.StatusCode, err } + return respBody, resp.Header, resp.StatusCode, nil } From 70aaca987616b6b975ebe77faea8813b1f57fe32 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 22:54:55 +0100 Subject: [PATCH 138/344] further cleanup --- api/server/acme/certmagic/certmagic_test.go | 10 +-- store/cloudflare/cloudflare.go | 90 +++++++++++---------- store/cloudflare/cloudflare_test.go | 6 +- 3 files changed, 49 insertions(+), 57 deletions(-) diff --git a/api/server/acme/certmagic/certmagic_test.go b/api/server/acme/certmagic/certmagic_test.go index 59afe557..2ff44b83 100644 --- a/api/server/acme/certmagic/certmagic_test.go +++ b/api/server/acme/certmagic/certmagic_test.go @@ -55,14 +55,11 @@ func TestStorageImplementation(t *testing.T) { } var s certmagic.Storage - st, err := cfstore.NewStore( + st := cfstore.NewStore( cfstore.ApiToken(apiToken), cfstore.AccountID(accountID), cfstore.Namespace(kvID), ) - if err != nil { - t.Fatalf("Couldn't initialise cloudflare storage: %s\n", err.Error()) - } s = &storage{ lock: memory.NewLock(), store: st, @@ -195,14 +192,11 @@ func TestE2e(t *testing.T) { } testLock := memory.NewLock() - testStore, err := cfstore.NewStore( + testStore := cfstore.NewStore( cfstore.ApiToken(apiToken), cfstore.AccountID(accountID), cfstore.Namespace(kvID), ) - if err != nil { - t.Fatal(err.Error()) - } testStorage := NewStorage(testLock, testStore) conf := cloudflare.NewDefaultConfig() diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index 21e0f686..2a8e48ec 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -21,7 +21,9 @@ import ( "github.com/pkg/errors" ) -const apiBaseURL = "https://api.cloudflare.com/client/v4/" +const ( + apiBaseURL = "https://api.cloudflare.com/client/v4/" +) type workersKV struct { options.Options @@ -35,49 +37,6 @@ type workersKV struct { httpClient *http.Client } -// New returns a cloudflare Store implementation. -// Options expects CF_API_TOKEN to a cloudflare API token scoped to Workers KV, -// CF_ACCOUNT_ID to contain a string with your cloudflare account ID and -// KV_NAMESPACE_ID to contain the namespace UUID for your KV storage. -func NewStore(opts ...options.Option) (store.Store, error) { - // Validate Options - options := options.NewOptions(opts...) - - var account, token, namespace string - - apiToken, ok := options.Values().Get("CF_API_TOKEN") - if !ok { - log.Fatal("Store: No CF_API_TOKEN passed as an option") - } - if token, ok = apiToken.(string); !ok { - log.Fatal("Store: Option CF_API_TOKEN contains a non-string") - } - - accountID, ok := options.Values().Get("CF_ACCOUNT_ID") - if !ok { - log.Fatal("Store: No CF_ACCOUNT_ID passed as an option") - } - if account, ok = accountID.(string); !ok { - log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string") - } - - uuid, ok := options.Values().Get("KV_NAMESPACE_ID") - if !ok { - log.Fatal("Store: No KV_NAMESPACE_ID passed as an option") - } - if namespace, ok = uuid.(string); !ok { - log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string") - } - - return &workersKV{ - account: account, - namespace: namespace, - token: token, - Options: options, - httpClient: &http.Client{}, - }, nil -} - // In the cloudflare workers KV implemention, List() doesn't guarantee // anything as the workers API is eventually consistent. func (w *workersKV) List() ([]*store.Record, error) { @@ -296,3 +255,46 @@ type apiMessage struct { Code int `json:"code"` Message string `json:"message"` } + +// New returns a cloudflare Store implementation. +// Options expects CF_API_TOKEN to a cloudflare API token scoped to Workers KV, +// CF_ACCOUNT_ID to contain a string with your cloudflare account ID and +// KV_NAMESPACE_ID to contain the namespace UUID for your KV storage. +func NewStore(opts ...options.Option) store.Store { + // Validate Options + options := options.NewOptions(opts...) + + var account, token, namespace string + + apiToken, ok := options.Values().Get("CF_API_TOKEN") + if !ok { + log.Fatal("Store: No CF_API_TOKEN passed as an option") + } + if token, ok = apiToken.(string); !ok { + log.Fatal("Store: Option CF_API_TOKEN contains a non-string") + } + + accountID, ok := options.Values().Get("CF_ACCOUNT_ID") + if !ok { + log.Fatal("Store: No CF_ACCOUNT_ID passed as an option") + } + if account, ok = accountID.(string); !ok { + log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string") + } + + uuid, ok := options.Values().Get("KV_NAMESPACE_ID") + if !ok { + log.Fatal("Store: No KV_NAMESPACE_ID passed as an option") + } + if namespace, ok = uuid.(string); !ok { + log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string") + } + + return &workersKV{ + account: account, + namespace: namespace, + token: token, + Options: options, + httpClient: &http.Client{}, + } +} diff --git a/store/cloudflare/cloudflare_test.go b/store/cloudflare/cloudflare_test.go index 6b5a6815..dd2b1909 100644 --- a/store/cloudflare/cloudflare_test.go +++ b/store/cloudflare/cloudflare_test.go @@ -20,16 +20,12 @@ func TestCloudflare(t *testing.T) { randomK := strconv.Itoa(rand.Int()) randomV := strconv.Itoa(rand.Int()) - wkv, err := NewStore( + wkv := NewStore( ApiToken(apiToken), AccountID(accountID), Namespace(kvID), ) - if err != nil { - t.Fatal(err.Error()) - } - records, err := wkv.List() if err != nil { t.Fatalf("List: %s\n", err.Error()) From 68d0efbeaa54e8b575e4f5634d222db691adecc5 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 22:57:11 +0100 Subject: [PATCH 139/344] Move api types in cf store --- store/cloudflare/cloudflare.go | 72 +++++++++++++++++----------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index 2a8e48ec..ea8240bd 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -37,6 +37,42 @@ type workersKV struct { httpClient *http.Client } +// apiResponse is a cloudflare v4 api response +type apiResponse struct { + Result []struct { + ID string `json:"id"` + Type string `json:"type"` + Name string `json:"name"` + Expiration string `json:"expiration"` + Content string `json:"content"` + Proxiable bool `json:"proxiable"` + Proxied bool `json:"proxied"` + TTL int `json:"ttl"` + Priority int `json:"priority"` + Locked bool `json:"locked"` + ZoneID string `json:"zone_id"` + ZoneName string `json:"zone_name"` + ModifiedOn time.Time `json:"modified_on"` + CreatedOn time.Time `json:"created_on"` + } `json:"result"` + Success bool `json:"success"` + Errors []apiMessage `json:"errors"` + // not sure Messages is ever populated? + Messages []apiMessage `json:"messages"` + ResultInfo struct { + Page int `json:"page"` + PerPage int `json:"per_page"` + Count int `json:"count"` + TotalCount int `json:"total_count"` + } `json:"result_info"` +} + +// apiMessage is a Cloudflare v4 API Error +type apiMessage struct { + Code int `json:"code"` + Message string `json:"message"` +} + // In the cloudflare workers KV implemention, List() doesn't guarantee // anything as the workers API is eventually consistent. func (w *workersKV) List() ([]*store.Record, error) { @@ -220,42 +256,6 @@ func (w *workersKV) request(ctx context.Context, method, path string, body inter return respBody, resp.Header, resp.StatusCode, nil } -// apiResponse is a cloudflare v4 api response -type apiResponse struct { - Result []struct { - ID string `json:"id"` - Type string `json:"type"` - Name string `json:"name"` - Expiration string `json:"expiration"` - Content string `json:"content"` - Proxiable bool `json:"proxiable"` - Proxied bool `json:"proxied"` - TTL int `json:"ttl"` - Priority int `json:"priority"` - Locked bool `json:"locked"` - ZoneID string `json:"zone_id"` - ZoneName string `json:"zone_name"` - ModifiedOn time.Time `json:"modified_on"` - CreatedOn time.Time `json:"created_on"` - } `json:"result"` - Success bool `json:"success"` - Errors []apiMessage `json:"errors"` - // not sure Messages is ever populated? - Messages []apiMessage `json:"messages"` - ResultInfo struct { - Page int `json:"page"` - PerPage int `json:"per_page"` - Count int `json:"count"` - TotalCount int `json:"total_count"` - } `json:"result_info"` -} - -// apiMessage is a Cloudflare v4 API Error -type apiMessage struct { - Code int `json:"code"` - Message string `json:"message"` -} - // New returns a cloudflare Store implementation. // Options expects CF_API_TOKEN to a cloudflare API token scoped to Workers KV, // CF_ACCOUNT_ID to contain a string with your cloudflare account ID and From 232c8ac7a137d31f000368987a0f1c5e5acc0663 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 23:10:44 +0100 Subject: [PATCH 140/344] More cleanup of store cf --- store/cloudflare/cloudflare.go | 77 ++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index ea8240bd..052d0fd2 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -13,6 +13,7 @@ import ( "math" "net/http" "net/url" + "os" "strconv" "time" @@ -73,6 +74,29 @@ type apiMessage struct { Message string `json:"message"` } +// getOptions returns account id, token and namespace +func getOptions() (string, string, string) { + accountID := os.Getenv("CF_ACCOUNT_ID") + apiToken := os.Getenv("CF_API_TOKEN") + namespace := os.Getenv("KV_NAMESPACE_ID") + + return accountID, apiToken, namespace +} + +func validateOptions(account, token, namespace string) { + if len(account) == 0 { + log.Fatal("Store: CF_ACCOUNT_ID is blank") + } + + if len(token) == 0 { + log.Fatal("Store: CF_API_TOKEN is blank") + } + + if len(namespace) == 0 { + log.Fatal("Store: KV_NAMESPACE_ID is blank") + } +} + // In the cloudflare workers KV implemention, List() doesn't guarantee // anything as the workers API is eventually consistent. func (w *workersKV) List() ([]*store.Record, error) { @@ -257,39 +281,48 @@ func (w *workersKV) request(ctx context.Context, method, path string, body inter } // New returns a cloudflare Store implementation. -// Options expects CF_API_TOKEN to a cloudflare API token scoped to Workers KV, -// CF_ACCOUNT_ID to contain a string with your cloudflare account ID and +// Account ID, Token and Namespace must either be passed as options or +// environment variables. If set as env vars we expect the following; +// CF_API_TOKEN to a cloudflare API token scoped to Workers KV. +// CF_ACCOUNT_ID to contain a string with your cloudflare account ID. // KV_NAMESPACE_ID to contain the namespace UUID for your KV storage. func NewStore(opts ...options.Option) store.Store { - // Validate Options + // create new Options options := options.NewOptions(opts...) - var account, token, namespace string + // get values from the environment + account, token, namespace := getOptions() - apiToken, ok := options.Values().Get("CF_API_TOKEN") - if !ok { - log.Fatal("Store: No CF_API_TOKEN passed as an option") - } - if token, ok = apiToken.(string); !ok { - log.Fatal("Store: Option CF_API_TOKEN contains a non-string") + // set api token from options if exists + if apiToken, ok := options.Values().Get("CF_API_TOKEN"); ok { + tk, ok := apiToken.(string) + if !ok { + log.Fatal("Store: Option CF_API_TOKEN contains a non-string") + } + token = tk } - accountID, ok := options.Values().Get("CF_ACCOUNT_ID") - if !ok { - log.Fatal("Store: No CF_ACCOUNT_ID passed as an option") - } - if account, ok = accountID.(string); !ok { - log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string") + // set account id from options if exists + if accountID, ok := options.Values().Get("CF_ACCOUNT_ID"); ok { + id, ok := accountID.(string) + if !ok { + log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string") + } + account = id } - uuid, ok := options.Values().Get("KV_NAMESPACE_ID") - if !ok { - log.Fatal("Store: No KV_NAMESPACE_ID passed as an option") - } - if namespace, ok = uuid.(string); !ok { - log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string") + // set namespace from options if exists + if uuid, ok := options.Values().Get("KV_NAMESPACE_ID"); ok { + ns, ok := uuid.(string) + if !ok { + log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string") + } + namespace = ns } + // validate options are not blank or log.Fatal + validateOptions(account, token, namespace) + return &workersKV{ account: account, namespace: namespace, From 4db1e0979836fddc0a2e72f001b9651332ec1c9c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Oct 2019 23:12:45 +0100 Subject: [PATCH 141/344] change options to be trimmed down --- api/server/acme/certmagic/certmagic_test.go | 8 ++++---- store/cloudflare/cloudflare_test.go | 4 ++-- store/cloudflare/options.go | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/api/server/acme/certmagic/certmagic_test.go b/api/server/acme/certmagic/certmagic_test.go index 2ff44b83..1739f5f2 100644 --- a/api/server/acme/certmagic/certmagic_test.go +++ b/api/server/acme/certmagic/certmagic_test.go @@ -56,8 +56,8 @@ func TestStorageImplementation(t *testing.T) { var s certmagic.Storage st := cfstore.NewStore( - cfstore.ApiToken(apiToken), - cfstore.AccountID(accountID), + cfstore.Token(apiToken), + cfstore.Account(accountID), cfstore.Namespace(kvID), ) s = &storage{ @@ -193,8 +193,8 @@ func TestE2e(t *testing.T) { testLock := memory.NewLock() testStore := cfstore.NewStore( - cfstore.ApiToken(apiToken), - cfstore.AccountID(accountID), + cfstore.Token(apiToken), + cfstore.Account(accountID), cfstore.Namespace(kvID), ) testStorage := NewStorage(testLock, testStore) diff --git a/store/cloudflare/cloudflare_test.go b/store/cloudflare/cloudflare_test.go index dd2b1909..525eeecd 100644 --- a/store/cloudflare/cloudflare_test.go +++ b/store/cloudflare/cloudflare_test.go @@ -21,8 +21,8 @@ func TestCloudflare(t *testing.T) { randomV := strconv.Itoa(rand.Int()) wkv := NewStore( - ApiToken(apiToken), - AccountID(accountID), + Token(apiToken), + Account(accountID), Namespace(kvID), ) diff --git a/store/cloudflare/options.go b/store/cloudflare/options.go index f09df9d6..36dc7c10 100644 --- a/store/cloudflare/options.go +++ b/store/cloudflare/options.go @@ -5,13 +5,13 @@ import ( ) // Token sets the cloudflare api token -func ApiToken(t string) options.Option { +func Token(t string) options.Option { // TODO: change to store.cf.api_token return options.WithValue("CF_API_TOKEN", t) } -// AccountID sets the cloudflare account id -func AccountID(id string) options.Option { +// Account sets the cloudflare account id +func Account(id string) options.Option { // TODO: change to store.cf.account_id return options.WithValue("CF_ACCOUNT_ID", id) } From 494eb135349010cf8c95e9c536d379777d586a5c Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 24 Oct 2019 16:07:31 +0100 Subject: [PATCH 142/344] Make sure we pick some link when Dialling --- tunnel/default.go | 50 ++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index 448fa3f1..0d16ae90 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -984,32 +984,30 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { var measured bool // non multicast so we need to find the link - if id := options.Link; id != "" { - t.RLock() - for _, link := range t.links { - // use the link specified it its available - if link.id != id { - continue - } - - link.RLock() - _, ok := link.channels[channel] - link.RUnlock() - - // we have at least one channel mapping - if ok { - c.discovered = true - links = append(links, link.id) - } - } - t.RUnlock() - // link not found - if len(links) == 0 { - // delete session and return error - t.delSession(c.channel, c.session) - return nil, ErrLinkNotFound + t.RLock() + for _, link := range t.links { + // use the link specified it its available + if id := options.Link; len(id) > 0 && link.id != id { + continue } + link.RLock() + _, ok := link.channels[channel] + link.RUnlock() + + // we have at least one channel mapping + if ok { + c.discovered = true + links = append(links, link.id) + } + } + t.RUnlock() + // link not found + if len(links) == 0 && len(options.Link) > 0 { + // delete session and return error + t.delSession(c.channel, c.session) + log.Debugf("Tunnel deleting session %s %s: %v", c.session, c.channel, ErrLinkNotFound) + return nil, ErrLinkNotFound } // discovered so set the link if not multicast @@ -1038,10 +1036,12 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { select { case <-time.After(after()): t.delSession(c.channel, c.session) + log.Debugf("Tunnel deleting session %s %s: %v", c.session, c.channel, ErrDialTimeout) return nil, ErrDialTimeout case err := <-c.errChan: if err != nil { t.delSession(c.channel, c.session) + log.Debugf("Tunnel deleting session %s %s: %v", c.session, c.channel, err) return nil, err } } @@ -1077,6 +1077,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { // otherwise return an error if err != nil { t.delSession(c.channel, c.session) + log.Debugf("Tunnel deleting session %s %s: %v", c.session, c.channel, err) return nil, err } @@ -1109,6 +1110,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { if err != nil { // delete the session t.delSession(c.channel, c.session) + log.Debugf("Tunnel deleting session %s %s: %v", c.session, c.channel, err) return nil, err } From f26d470db1d7b3be4bb6e3d8b8223eb96999afdf Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 24 Oct 2019 17:51:41 +0100 Subject: [PATCH 143/344] A few changes for the network / tunnel link state --- network/default.go | 28 ++++++++---- proxy/mucp/mucp.go | 3 ++ tunnel/default.go | 11 ++--- tunnel/link.go | 109 +++++++++++++++++++++++++++++++++++++-------- 4 files changed, 119 insertions(+), 32 deletions(-) diff --git a/network/default.go b/network/default.go index 741c4fb8..57fcbc26 100644 --- a/network/default.go +++ b/network/default.go @@ -677,19 +677,19 @@ func (n *network) getHopCount(rtr string) int { // the route origin is our peer if _, ok := n.peers[rtr]; ok { - return 2 + return 10 } // the route origin is the peer of our peer for _, peer := range n.peers { for id := range peer.peers { if rtr == id { - return 3 + return 100 } } } // otherwise we are three hops away - return 4 + return 1000 } // getRouteMetric calculates router metric and returns it @@ -721,11 +721,15 @@ func (n *network) getRouteMetric(router string, gateway string, link string) int // make sure length is non-zero length := link.Length() if length == 0 { - length = 10e10 + log.Debugf("Link length is 0 %v %v", link, link.Length()) + length = 10e9 } - return (delay * length * int64(hops)) / 10e9 + log.Debugf("Network calculated metric %v delay %v length %v distance %v", (delay*length*int64(hops))/10e6, delay, length, hops) + return (delay * length * int64(hops)) / 10e6 } + log.Debugf("Network failed to find a link to gateway: %s", gateway) + return math.MaxInt64 } @@ -783,12 +787,18 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { } // calculate route metric and add to the advertised metric // we need to make sure we do not overflow math.MaxInt64 - log.Debugf("Network metric for router %s and gateway %s", event.Route.Router, event.Route.Gateway) - if metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link); metric != math.MaxInt64 { - route.Metric += metric + metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link) + log.Debugf("Network metric for router %s and gateway %s: %v", event.Route.Router, event.Route.Gateway, metric) + + // check we don't overflow max int 64 + if d := route.Metric + metric; d > math.MaxInt64 || d <= 0 { + // set to max int64 if we overflow + route.Metric = math.MaxInt64 } else { - route.Metric = metric + // set the combined value of metrics otherwise + route.Metric = d } + // create router event e := &router.Event{ Type: router.EventType(event.Type), diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index b336e5f3..06ab676f 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -19,6 +19,7 @@ import ( "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/router" "github.com/micro/go-micro/server" + "github.com/micro/go-micro/util/log" ) // Proxy will transparently proxy requests to an endpoint. @@ -294,6 +295,8 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server continue } + log.Debugf("Proxy using route %+v\n", route) + // set the address to call addresses := toNodes([]router.Route{route}) opts = append(opts, client.WithAddress(addresses...)) diff --git a/tunnel/default.go b/tunnel/default.go index 0d16ae90..a7555eb1 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -746,8 +746,13 @@ func (t *tun) setupLink(node string) (*link, error) { } log.Debugf("Tunnel connected to %s", node) + // create a new link + link := newLink(c) + // set link id to remote side + link.id = c.Remote() + // send the first connect message - if err := c.Send(&transport.Message{ + if err := link.Send(&transport.Message{ Header: map[string]string{ "Micro-Tunnel": "connect", "Micro-Tunnel-Id": t.id, @@ -757,10 +762,6 @@ func (t *tun) setupLink(node string) (*link, error) { return nil, err } - // create a new link - link := newLink(c) - // set link id to remote side - link.id = c.Remote() // we made the outbound connection // and sent the connect message link.connected = true diff --git a/tunnel/link.go b/tunnel/link.go index 26b568fc..5c53c91a 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -1,12 +1,14 @@ package tunnel import ( + "bytes" "io" "sync" "time" "github.com/google/uuid" "github.com/micro/go-micro/transport" + "github.com/micro/go-micro/util/log" ) type link struct { @@ -42,6 +44,9 @@ type link struct { rate float64 // keep an error count on the link errCount int + + // link state channel + state chan *packet } // packet send over link @@ -56,21 +61,49 @@ type packet struct { err error } +var ( + // the 4 byte 0 packet sent to determine the link state + linkRequest = []byte{0, 0, 0, 0} + // the 4 byte 1 filled packet sent to determine link state + linkResponse = []byte{1, 1, 1, 1} +) + func newLink(s transport.Socket) *link { l := &link{ Socket: s, id: uuid.New().String(), lastKeepAlive: time.Now(), closed: make(chan bool), + state: make(chan *packet, 64), channels: make(map[string]time.Time), sendQueue: make(chan *packet, 128), recvQueue: make(chan *packet, 128), } + + // process inbound/outbound packets go l.process() - go l.expiry() + // manage the link state + go l.manage() + return l } +// setRate sets the bits per second rate as a float64 +func (l *link) setRate(bits int64, delta time.Duration) { + // rate of send in bits per nanosecond + rate := float64(bits) / float64(delta.Nanoseconds()) + + // default the rate if its zero + if l.rate == 0 { + // rate per second + l.rate = rate * 1e9 + } else { + // set new rate per second + l.rate = 0.8*l.rate + 0.2*(rate*1e9) + } +} + +// setRTT sets a nanosecond based moving average roundtrip time for the link func (l *link) setRTT(d time.Duration) { l.Lock() defer l.Unlock() @@ -101,8 +134,22 @@ func (l *link) process() { // process new received message + pk := &packet{message: m, err: err} + + // this is our link state packet + if m.Header["Micro-Method"] == "link" { + // process link state message + select { + case l.state <- pk: + default: + } + continue + } + + // process all messages as is + select { - case l.recvQueue <- &packet{message: m, err: err}: + case l.recvQueue <- pk: case <-l.closed: return } @@ -122,15 +169,49 @@ func (l *link) process() { } } -// watches the channel expiry -func (l *link) expiry() { +// manage manages the link state including rtt packets and channel mapping expiry +func (l *link) manage() { + // tick over every minute to expire and fire rtt packets t := time.NewTicker(time.Minute) defer t.Stop() + // used to send link state packets + send := func(b []byte) { + l.Send(&transport.Message{ + Header: map[string]string{ + "Micro-Method": "link", + }, Body: b, + }) + } + + // set time now + now := time.Now() + + // send the initial rtt request packet + send(linkRequest) + for { select { + // exit if closed case <-l.closed: return + // process link state rtt packets + case p := <-l.state: + if p.err != nil { + continue + } + // check the type of message + switch { + case bytes.Compare(p.message.Body, linkRequest) == 0: + log.Tracef("Link %s received link request %v", l.id, p.message.Body) + // send response + send(linkResponse) + case bytes.Compare(p.message.Body, linkResponse) == 0: + // set round trip time + d := time.Since(now) + log.Tracef("Link %s received link response in %v", p.message.Body, d) + l.setRTT(d) + } case <-t.C: // drop any channel mappings older than 2 minutes var kill []string @@ -155,6 +236,10 @@ func (l *link) expiry() { delete(l.channels, ch) } l.Unlock() + + // fire off a link state rtt packet + now = time.Now() + send(linkRequest) } } } @@ -278,23 +363,11 @@ func (l *link) Send(m *transport.Message) error { // calculate based on data if dataSent > 0 { - // measure time taken - delta := time.Since(now) - // bit sent bits := dataSent * 1024 - // rate of send in bits per nanosecond - rate := float64(bits) / float64(delta.Nanoseconds()) - - // default the rate if its zero - if l.rate == 0 { - // rate per second - l.rate = rate * 1e9 - } else { - // set new rate per second - l.rate = 0.8*l.rate + 0.2*(rate*1e9) - } + // set the rate + l.setRate(int64(bits), time.Since(now)) } return nil From 1f658cfbff5ba6d5213e1359e921bb003fb1a06f Mon Sep 17 00:00:00 2001 From: Sumanth Chinthagunta Date: Thu, 24 Oct 2019 17:51:54 -0700 Subject: [PATCH 144/344] adding PatchContext - this will create new context with original + patch metadata --- metadata/metadata.go | 14 ++++++++++++++ metadata/metadata_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/metadata/metadata.go b/metadata/metadata.go index 3ae6ba85..606c1f05 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -28,3 +28,17 @@ func FromContext(ctx context.Context) (Metadata, bool) { func NewContext(ctx context.Context, md Metadata) context.Context { return context.WithValue(ctx, metaKey{}, md) } + +// PatchContext : will add/replace source metadata fields with given patch metadata fields +func PatchContext(ctx context.Context, patchMd Metadata) context.Context { + md, _ := ctx.Value(metaKey{}).(Metadata) + cmd := make(Metadata) + for k, v := range md { + cmd[k] = v + } + for k, v := range patchMd { + cmd[k] = v + } + return context.WithValue(ctx, metaKey{}, cmd) + +} diff --git a/metadata/metadata_test.go b/metadata/metadata_test.go index 9b5545eb..cfd1c1f8 100644 --- a/metadata/metadata_test.go +++ b/metadata/metadata_test.go @@ -40,3 +40,28 @@ func TestMetadataContext(t *testing.T) { t.Errorf("Expected metadata length 1 got %d", i) } } +func TestPatchContext(t *testing.T) { + + original := Metadata{ + "foo": "bar", + } + + patch := Metadata{ + "sumo": "demo", + } + ctx := NewContext(context.TODO(), original) + + patchedCtx := PatchContext(ctx, patch) + + patchedMd, ok := FromContext(patchedCtx) + if !ok { + t.Errorf("Unexpected error retrieving metadata, got %t", ok) + } + + if patchedMd["sumo"] != patch["sumo"] { + t.Errorf("Expected key: %s val: %s, got key: %s val: %s", "sumo", patch["sumo"], "sumo", patchedMd["sumo"]) + } + if patchedMd["foo"] != original["foo"] { + t.Errorf("Expected key: %s val: %s, got key: %s val: %s", "foo", original["foo"], "foo", patchedMd["foo"]) + } +} From 3831199600ad3f889aa536f8240e61b5992892d7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 25 Oct 2019 14:16:22 +0100 Subject: [PATCH 145/344] Use best link in tunnel, loop waiting for announce and accept messages, cleanup some code --- tunnel/default.go | 202 +++++++++++++++++++++++----------------------- tunnel/link.go | 54 ++++++++++--- tunnel/session.go | 127 +++++++++++++++++++++++++---- tunnel/tunnel.go | 4 +- 4 files changed, 256 insertions(+), 131 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index a7555eb1..0b064c36 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -90,6 +90,7 @@ func (t *tun) getSession(channel, session string) (*session, bool) { return s, ok } +// delSession deletes a session if it exists func (t *tun) delSession(channel, session string) { t.Lock() delete(t.sessions, channel+session) @@ -146,6 +147,9 @@ func (t *tun) newSessionId() string { return uuid.New().String() } +// announce will send a message to the link to tell the other side of a channel mapping we have. +// This usually happens if someone calls Dial and sends a discover message but otherwise we +// periodically send these messages to asynchronously manage channel mappings. func (t *tun) announce(channel, session string, link *link) { // create the "announce" response message for a discover request msg := &transport.Message{ @@ -206,7 +210,7 @@ func (t *tun) monitor() { // check the link status and purge dead links for node, link := range t.links { // check link status - switch link.Status() { + switch link.State() { case "closed": delLinks = append(delLinks, node) case "error": @@ -303,8 +307,16 @@ func (t *tun) process() { // build the list of links ot send to for node, link := range t.links { + // get the values we need + link.RLock() + id := link.id + connected := link.connected + loopback := link.loopback + _, exists := link.channels[msg.channel] + link.RUnlock() + // if the link is not connected skip it - if !link.connected { + if !connected { log.Debugf("Link for node %s not connected", node) err = errors.New("link not connected") continue @@ -313,32 +325,29 @@ func (t *tun) process() { // if the link was a loopback accepted connection // and the message is being sent outbound via // a dialled connection don't use this link - if link.loopback && msg.outbound { + if loopback && msg.outbound { err = errors.New("link is loopback") continue } // if the message was being returned by the loopback listener // send it back up the loopback link only - if msg.loopback && !link.loopback { + if msg.loopback && !loopback { err = errors.New("link is not loopback") continue } // check the multicast mappings if msg.mode == Multicast { - link.RLock() - _, ok := link.channels[msg.channel] - link.RUnlock() // channel mapping not found in link - if !ok { + if !exists { continue } } else { // if we're picking the link check the id // this is where we explicitly set the link // in a message received via the listen method - if len(msg.link) > 0 && link.id != msg.link { + if len(msg.link) > 0 && id != msg.link { err = errors.New("link not found") continue } @@ -422,6 +431,12 @@ func (t *tun) listen(link *link) { // let us know if its a loopback var loopback bool + var connected bool + + // set the connected value + link.RLock() + connected = link.connected + link.RUnlock() for { // process anything via the net interface @@ -451,7 +466,7 @@ func (t *tun) listen(link *link) { // if its not connected throw away the link // the first message we process needs to be connect - if !link.connected && mtype != "connect" { + if !connected && mtype != "connect" { log.Debugf("Tunnel link %s not connected", link.id) return } @@ -461,7 +476,8 @@ func (t *tun) listen(link *link) { log.Debugf("Tunnel link %s received connect message", link.Remote()) link.Lock() - // are we connecting to ourselves? + + // check if we're connecting to ourselves? if id == t.id { link.loopback = true loopback = true @@ -471,6 +487,8 @@ func (t *tun) listen(link *link) { link.id = link.Remote() // set as connected link.connected = true + connected = true + link.Unlock() // save the link once connected @@ -494,9 +512,7 @@ func (t *tun) listen(link *link) { // the entire listener was closed so remove it from the mapping if sessionId == "listener" { - link.Lock() - delete(link.channels, channel) - link.Unlock() + link.delChannel(channel) continue } @@ -510,10 +526,8 @@ func (t *tun) listen(link *link) { // otherwise its a session mapping of sorts case "keepalive": log.Debugf("Tunnel link %s received keepalive", link.Remote()) - link.Lock() // save the keepalive - link.lastKeepAlive = time.Now() - link.Unlock() + link.keepalive() continue // a new connection dialled outbound case "open": @@ -540,11 +554,7 @@ func (t *tun) listen(link *link) { channels := strings.Split(channel, ",") // update mapping in the link - link.Lock() - for _, channel := range channels { - link.channels[channel] = time.Now() - } - link.Unlock() + link.setChannel(channels...) // this was an announcement not intended for anything if sessionId == "listener" || sessionId == "" { @@ -904,6 +914,53 @@ func (t *tun) close() error { return t.listener.Close() } +// pickLink will pick the best link based on connectivity, delay, rate and length +func (t *tun) pickLink(links []*link) *link { + var metric float64 + var chosen *link + + // find the best link + for i, link := range links { + // don't use disconnected or errored links + if link.State() != "connected" { + continue + } + + // get the link state info + d := float64(link.Delay()) + l := float64(link.Length()) + r := link.Rate() + + // metric = delay x length x rate + m := d * l * r + + // first link so just and go + if i == 0 { + metric = m + chosen = link + continue + } + + // we found a better metric + if m < metric { + metric = m + chosen = link + } + } + + // if there's no link we're just going to mess around + if chosen == nil { + i := rand.Intn(len(links)) + return links[i] + } + + // we chose the link with; + // the lowest delay e.g least messages queued + // the lowest rate e.g the least messages flowing + // the lowest length e.g the smallest roundtrip time + return chosen +} + func (t *tun) Address() string { t.RLock() defer t.RUnlock() @@ -967,42 +1024,32 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { c.mode = options.Mode // set the dial timeout c.timeout = options.Timeout - // get the current time - now := time.Now() - after := func() time.Duration { - d := time.Since(now) - // dial timeout minus time since - wait := options.Timeout - d - if wait < time.Duration(0) { - return time.Duration(0) - } - return wait - } - - var links []string + var links []*link // did we measure the rtt var measured bool - // non multicast so we need to find the link t.RLock() + + // non multicast so we need to find the link for _, link := range t.links { // use the link specified it its available if id := options.Link; len(id) > 0 && link.id != id { continue } - link.RLock() - _, ok := link.channels[channel] - link.RUnlock() + // get the channel + lastMapped := link.getChannel(channel) // we have at least one channel mapping - if ok { + if !lastMapped.IsZero() { + links = append(links, link) c.discovered = true - links = append(links, link.id) } } + t.RUnlock() + // link not found if len(links) == 0 && len(options.Link) > 0 { // delete session and return error @@ -1015,9 +1062,9 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { // TODO: pick the link efficiently based // on link status and saturation. if c.discovered && c.mode == Unicast { - // set the link - i := rand.Intn(len(links)) - c.link = links[i] + // pickLink will pick the best link + link := t.pickLink(links) + c.link = link.id } // shit fuck @@ -1025,57 +1072,8 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { // piggy back roundtrip nowRTT := time.Now() - // create a new discovery message for this channel - msg := c.newMessage("discover") - msg.mode = Broadcast - msg.outbound = true - msg.link = "" - - // send the discovery message - t.send <- msg - - select { - case <-time.After(after()): - t.delSession(c.channel, c.session) - log.Debugf("Tunnel deleting session %s %s: %v", c.session, c.channel, ErrDialTimeout) - return nil, ErrDialTimeout - case err := <-c.errChan: - if err != nil { - t.delSession(c.channel, c.session) - log.Debugf("Tunnel deleting session %s %s: %v", c.session, c.channel, err) - return nil, err - } - } - - var err error - - // set a dialTimeout - dialTimeout := after() - - // set a shorter delay for multicast - if c.mode != Unicast { - // shorten this - dialTimeout = time.Millisecond * 500 - } - - // wait for announce - select { - case msg := <-c.recv: - if msg.typ != "announce" { - err = ErrDiscoverChan - } - case <-time.After(dialTimeout): - err = ErrDialTimeout - } - - // if its multicast just go ahead because this is best effort - if c.mode != Unicast { - c.discovered = true - c.accepted = true - return c, nil - } - - // otherwise return an error + // attempt to discover the link + err := c.Discover() if err != nil { t.delSession(c.channel, c.session) log.Debugf("Tunnel deleting session %s %s: %v", c.session, c.channel, err) @@ -1096,34 +1094,34 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { // set measured to true measured = true } - - // set discovered to true - c.discovered = true } // a unicast session so we call "open" and wait for an "accept" // reset now in case we use it - now = time.Now() + now := time.Now() // try to open the session - err := c.Open() - if err != nil { + if err := c.Open(); err != nil { // delete the session t.delSession(c.channel, c.session) log.Debugf("Tunnel deleting session %s %s: %v", c.session, c.channel, err) return nil, err } + // set time take to open + d := time.Since(now) + // if we haven't measured the roundtrip do it now if !measured && c.mode == Unicast { // set the link time t.RLock() link, ok := t.links[c.link] t.RUnlock() + if ok { // set the rountrip time - link.setRTT(time.Since(now)) + link.setRTT(d) } } diff --git a/tunnel/link.go b/tunnel/link.go index 5c53c91a..a319c214 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -17,9 +17,11 @@ type link struct { sync.RWMutex // stops the link closed chan bool - // send queue + // link state channel for testing link + state chan *packet + // send queue for sending packets sendQueue chan *packet - // receive queue + // receive queue for receiving packets recvQueue chan *packet // unique id of this link e.g uuid // which we define for ourselves @@ -44,9 +46,6 @@ type link struct { rate float64 // keep an error count on the link errCount int - - // link state channel - state chan *packet } // packet send over link @@ -73,9 +72,9 @@ func newLink(s transport.Socket) *link { Socket: s, id: uuid.New().String(), lastKeepAlive: time.Now(), + channels: make(map[string]time.Time), closed: make(chan bool), state: make(chan *packet, 64), - channels: make(map[string]time.Time), sendQueue: make(chan *packet, 128), recvQueue: make(chan *packet, 128), } @@ -119,6 +118,33 @@ func (l *link) setRTT(d time.Duration) { l.length = int64(length) } +func (l *link) delChannel(ch string) { + l.Lock() + delete(l.channels, ch) + l.Unlock() +} + +func (l *link) setChannel(channels ...string) { + l.Lock() + for _, ch := range channels { + l.channels[ch] = time.Now() + } + l.Unlock() +} + +func (l *link) getChannel(ch string) time.Time { + l.RLock() + defer l.RUnlock() + return l.channels[ch] +} + +// set the keepalive time +func (l *link) keepalive() { + l.Lock() + l.lastKeepAlive = time.Now() + l.Unlock() +} + // process deals with the send queue func (l *link) process() { // receive messages @@ -176,8 +202,8 @@ func (l *link) manage() { defer t.Stop() // used to send link state packets - send := func(b []byte) { - l.Send(&transport.Message{ + send := func(b []byte) error { + return l.Send(&transport.Message{ Header: map[string]string{ "Micro-Method": "link", }, Body: b, @@ -205,7 +231,11 @@ func (l *link) manage() { case bytes.Compare(p.message.Body, linkRequest) == 0: log.Tracef("Link %s received link request %v", l.id, p.message.Body) // send response - send(linkResponse) + if err := send(linkResponse); err != nil { + l.Lock() + l.errCount++ + l.Unlock() + } case bytes.Compare(p.message.Body, linkResponse) == 0: // set round trip time d := time.Since(now) @@ -270,7 +300,6 @@ func (l *link) Delay() int64 { func (l *link) Rate() float64 { l.RLock() defer l.RUnlock() - return l.rate } @@ -279,7 +308,6 @@ func (l *link) Rate() float64 { func (l *link) Length() int64 { l.RLock() defer l.RUnlock() - return l.length } @@ -398,8 +426,8 @@ func (l *link) Recv(m *transport.Message) error { return nil } -// Status can return connected, closed, error -func (l *link) Status() string { +// State can return connected, closed, error +func (l *link) State() string { select { case <-l.closed: return "closed" diff --git a/tunnel/session.go b/tunnel/session.go index a185c3ce..f1e65184 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -106,6 +106,112 @@ func (s *session) newMessage(typ string) *message { } } +// waitFor waits for the message type required until the timeout specified +func (s *session) waitFor(msgType string, timeout time.Duration) error { + now := time.Now() + + after := func() time.Duration { + d := time.Since(now) + // dial timeout minus time since + wait := timeout - d + + if wait < time.Duration(0) { + return time.Duration(0) + } + + return wait + } + + // wait for the message type +loop: + for { + select { + case msg := <-s.recv: + // ignore what we don't want + if msg.typ != msgType { + log.Debugf("Tunnel received non %s message in waiting for %s", msg.typ, msgType) + continue + } + + // got the message + break loop + case <-time.After(after()): + return ErrDialTimeout + case <-s.closed: + return io.EOF + } + } + + return nil +} + +// Discover attempts to discover the link for a specific channel +func (s *session) Discover() error { + // create a new discovery message for this channel + msg := s.newMessage("discover") + msg.mode = Broadcast + msg.outbound = true + msg.link = "" + + // send the discovery message + s.send <- msg + + // set time now + now := time.Now() + + after := func() time.Duration { + d := time.Since(now) + // dial timeout minus time since + wait := s.timeout - d + if wait < time.Duration(0) { + return time.Duration(0) + } + return wait + } + + // wait to hear back about the sent message + select { + case <-time.After(after()): + return ErrDialTimeout + case err := <-s.errChan: + if err != nil { + return err + } + } + + var err error + + // set a new dialTimeout + dialTimeout := after() + + // set a shorter delay for multicast + if s.mode != Unicast { + // shorten this + dialTimeout = time.Millisecond * 500 + } + + // wait for announce + if err := s.waitFor("announce", dialTimeout); err != nil { + return err + } + + // if its multicast just go ahead because this is best effort + if s.mode != Unicast { + s.discovered = true + s.accepted = true + return nil + } + + if err != nil { + return err + } + + // set discovered + s.discovered = true + + return nil +} + // Open will fire the open message for the session. This is called by the dialler. func (s *session) Open() error { // create a new message @@ -131,22 +237,15 @@ func (s *session) Open() error { } // now wait for the accept - select { - case msg = <-s.recv: - if msg.typ != "accept" { - log.Debugf("Received non accept message in Open %s", msg.typ) - return errors.New("failed to connect") - } - // set to accepted - s.accepted = true - // set link - s.link = msg.link - case <-time.After(s.timeout): - return ErrDialTimeout - case <-s.closed: - return io.EOF + if err := s.waitFor("accept", s.timeout); err != nil { + return err } + // set to accepted + s.accepted = true + // set link + s.link = msg.link + return nil } diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 73c937f3..212e07e4 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -63,8 +63,8 @@ type Link interface { Length() int64 // Current transfer rate as bits per second (lower is better) Rate() float64 - // Status of the link e.g connected/closed - Status() string + // State of the link e.g connected/closed + State() string // honours transport socket transport.Socket } From c170189efbcd7f776237f7d2b211f7af16380e0f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 25 Oct 2019 14:22:38 +0100 Subject: [PATCH 146/344] We need the message back to set the link --- tunnel/session.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tunnel/session.go b/tunnel/session.go index f1e65184..1dfe992c 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -107,7 +107,7 @@ func (s *session) newMessage(typ string) *message { } // waitFor waits for the message type required until the timeout specified -func (s *session) waitFor(msgType string, timeout time.Duration) error { +func (s *session) waitFor(msgType string, timeout time.Duration) (*message, error) { now := time.Now() after := func() time.Duration { @@ -123,7 +123,6 @@ func (s *session) waitFor(msgType string, timeout time.Duration) error { } // wait for the message type -loop: for { select { case msg := <-s.recv: @@ -132,17 +131,14 @@ loop: log.Debugf("Tunnel received non %s message in waiting for %s", msg.typ, msgType) continue } - // got the message - break loop + return msg, nil case <-time.After(after()): - return ErrDialTimeout + return nil, ErrDialTimeout case <-s.closed: - return io.EOF + return nil, io.EOF } } - - return nil } // Discover attempts to discover the link for a specific channel @@ -191,7 +187,8 @@ func (s *session) Discover() error { } // wait for announce - if err := s.waitFor("announce", dialTimeout); err != nil { + _, err = s.waitFor("announce", dialTimeout) + if err != nil { return err } @@ -237,7 +234,8 @@ func (s *session) Open() error { } // now wait for the accept - if err := s.waitFor("accept", s.timeout); err != nil { + msg, err := s.waitFor("accept", s.timeout) + if err != nil { return err } From 1c9ada6413eb3564110964d15e4239df6f75d9bc Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 25 Oct 2019 14:24:37 +0100 Subject: [PATCH 147/344] Reorder setChannel method --- tunnel/link.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tunnel/link.go b/tunnel/link.go index a319c214..d135c152 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -124,6 +124,12 @@ func (l *link) delChannel(ch string) { l.Unlock() } +func (l *link) getChannel(ch string) time.Time { + l.RLock() + defer l.RUnlock() + return l.channels[ch] +} + func (l *link) setChannel(channels ...string) { l.Lock() for _, ch := range channels { @@ -132,12 +138,6 @@ func (l *link) setChannel(channels ...string) { l.Unlock() } -func (l *link) getChannel(ch string) time.Time { - l.RLock() - defer l.RUnlock() - return l.channels[ch] -} - // set the keepalive time func (l *link) keepalive() { l.Lock() From 5d7bf53f78859cabd867fcf96b6e3722aed70fc6 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 25 Oct 2019 15:41:37 +0100 Subject: [PATCH 148/344] don't error where the connection is not unicast --- tunnel/session.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tunnel/session.go b/tunnel/session.go index 1dfe992c..0fcab963 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -110,7 +110,7 @@ func (s *session) newMessage(typ string) *message { func (s *session) waitFor(msgType string, timeout time.Duration) (*message, error) { now := time.Now() - after := func() time.Duration { + after := func(timeout time.Duration) time.Duration { d := time.Since(now) // dial timeout minus time since wait := timeout - d @@ -133,7 +133,7 @@ func (s *session) waitFor(msgType string, timeout time.Duration) (*message, erro } // got the message return msg, nil - case <-time.After(after()): + case <-time.After(after(timeout)): return nil, ErrDialTimeout case <-s.closed: return nil, io.EOF @@ -188,9 +188,6 @@ func (s *session) Discover() error { // wait for announce _, err = s.waitFor("announce", dialTimeout) - if err != nil { - return err - } // if its multicast just go ahead because this is best effort if s.mode != Unicast { From 1c6b85e05d546aeb9d3d931c833b53fb78ab456e Mon Sep 17 00:00:00 2001 From: Sumanth Chinthagunta Date: Fri, 25 Oct 2019 08:27:28 -0700 Subject: [PATCH 149/344] AppendContext with overwrite flag --- metadata/metadata.go | 9 ++++--- metadata/metadata_test.go | 55 +++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/metadata/metadata.go b/metadata/metadata.go index 606c1f05..58c70c3d 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -29,15 +29,18 @@ func NewContext(ctx context.Context, md Metadata) context.Context { return context.WithValue(ctx, metaKey{}, md) } -// PatchContext : will add/replace source metadata fields with given patch metadata fields -func PatchContext(ctx context.Context, patchMd Metadata) context.Context { +func AppendContext(ctx context.Context, patchMd Metadata, overwrite bool) context.Context { md, _ := ctx.Value(metaKey{}).(Metadata) cmd := make(Metadata) for k, v := range md { cmd[k] = v } for k, v := range patchMd { - cmd[k] = v + if _, ok := cmd[k]; ok && !overwrite { + // skip + } else { + cmd[k] = v + } } return context.WithValue(ctx, metaKey{}, cmd) diff --git a/metadata/metadata_test.go b/metadata/metadata_test.go index cfd1c1f8..f05e4229 100644 --- a/metadata/metadata_test.go +++ b/metadata/metadata_test.go @@ -2,6 +2,7 @@ package metadata import ( "context" + "reflect" "testing" ) @@ -40,28 +41,42 @@ func TestMetadataContext(t *testing.T) { t.Errorf("Expected metadata length 1 got %d", i) } } -func TestPatchContext(t *testing.T) { - original := Metadata{ - "foo": "bar", +func TestAppendContext(t *testing.T) { + type args struct { + existing Metadata + append Metadata + overwrite bool } - - patch := Metadata{ - "sumo": "demo", + tests := []struct { + name string + args args + want Metadata + }{ + { + name: "matching key, overwrite false", + args: args{ + existing: Metadata{"foo": "bar", "sumo": "demo"}, + append: Metadata{"sumo": "demo2"}, + overwrite: false, + }, + want: Metadata{"foo": "bar", "sumo": "demo"}, + }, + { + name: "matching key, overwrite true", + args: args{ + existing: Metadata{"foo": "bar", "sumo": "demo"}, + append: Metadata{"sumo": "demo2"}, + overwrite: true, + }, + want: Metadata{"foo": "bar", "sumo": "demo2"}, + }, } - ctx := NewContext(context.TODO(), original) - - patchedCtx := PatchContext(ctx, patch) - - patchedMd, ok := FromContext(patchedCtx) - if !ok { - t.Errorf("Unexpected error retrieving metadata, got %t", ok) - } - - if patchedMd["sumo"] != patch["sumo"] { - t.Errorf("Expected key: %s val: %s, got key: %s val: %s", "sumo", patch["sumo"], "sumo", patchedMd["sumo"]) - } - if patchedMd["foo"] != original["foo"] { - t.Errorf("Expected key: %s val: %s, got key: %s val: %s", "foo", original["foo"], "foo", patchedMd["foo"]) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got, _ := FromContext(AppendContext(NewContext(context.TODO(), tt.args.existing), tt.args.append, tt.args.overwrite)); !reflect.DeepEqual(got, tt.want) { + t.Errorf("AppendContext() = %v, want %v", got, tt.want) + } + }) } } From 51922c17632a49ead7e21527b250276d97fd796c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 25 Oct 2019 22:46:43 +0100 Subject: [PATCH 150/344] Refresh route metrics in the proxy --- proxy/mucp/mucp.go | 144 ++++++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 62 deletions(-) diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index 06ab676f..02f28d89 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -43,9 +43,6 @@ type Proxy struct { // A fib of routes service:address sync.RWMutex Routes map[string]map[uint64]router.Route - - // The channel to monitor watcher errors - errChan chan error } // read client request and write to server @@ -96,6 +93,18 @@ func toNodes(routes []router.Route) []string { return nodes } +func toSlice(r map[uint64]router.Route) []router.Route { + var routes []router.Route + for _, v := range r { + routes = append(routes, v) + } + + // sort the routes in order of metric + sort.Slice(routes, func(i, j int) bool { return routes[i].Metric < routes[j].Metric }) + + return routes +} + func (p *Proxy) getLink(r router.Route) (client.Client, error) { if r.Link == "local" || len(p.Links) == 0 { return p.Client, nil @@ -108,27 +117,25 @@ func (p *Proxy) getLink(r router.Route) (client.Client, error) { } func (p *Proxy) getRoute(service string) ([]router.Route, error) { - toSlice := func(r map[uint64]router.Route) []router.Route { - var routes []router.Route - for _, v := range r { - routes = append(routes, v) - } - - // sort the routes in order of metric - sort.Slice(routes, func(i, j int) bool { return routes[i].Metric < routes[j].Metric }) - - return routes - } - // lookup the route cache first p.Lock() - routes, ok := p.Routes[service] + cached, ok := p.Routes[service] if ok { p.Unlock() - return toSlice(routes), nil + return toSlice(cached), nil } p.Unlock() + // cache routes for the service + routes, err := p.cacheRoutes(service) + if err != nil { + return nil, err + } + + return routes, nil +} + +func (p *Proxy) cacheRoutes(service string) ([]router.Route, error) { // lookup the routes in the router results, err := p.Router.Lookup(router.QueryService(service)) if err != nil { @@ -149,18 +156,40 @@ func (p *Proxy) getRoute(service string) ([]router.Route, error) { } p.Routes[service][route.Hash()] = route } - routes = p.Routes[service] + routes := p.Routes[service] p.Unlock() return toSlice(routes), nil } -// manageRouteCache applies action on a given route to Proxy route cache -func (p *Proxy) manageRouteCache(route router.Route, action string) error { +// refreshMetrics will refresh any metrics for our local cached routes. +// we may not receive new watch events for these as they change. +func (p *Proxy) refreshMetrics() { + var services []string + + // get a list of services to update + p.RLock() + for service, _ := range p.Routes { + services = append(services, service) + } + p.RUnlock() + + // get and cache the routes for the service + for _, service := range services { + p.cacheRoutes(service) + } +} + +// manageRoutes applies action on a given route to Proxy route cache +func (p *Proxy) manageRoutes(route router.Route, action string) error { + // we only cache what we are actually concerned with + p.Lock() + defer p.Unlock() + switch action { case "create", "update": if _, ok := p.Routes[route.Service]; !ok { - p.Routes[route.Service] = make(map[uint64]router.Route) + return fmt.Errorf("not called %s", route.Service) } p.Routes[route.Service][route.Hash()] = route case "delete": @@ -174,31 +203,22 @@ func (p *Proxy) manageRouteCache(route router.Route, action string) error { // watchRoutes watches service routes and updates proxy cache func (p *Proxy) watchRoutes() { - // this is safe to do as the only way watchRoutes returns is - // when some error is written into error channel - we want to bail then - defer close(p.errChan) - // route watcher w, err := p.Router.Watch() if err != nil { - p.errChan <- err return } for { event, err := w.Next() if err != nil { - p.errChan <- err return } - p.Lock() - if err := p.manageRouteCache(event.Route, fmt.Sprintf("%s", event.Type)); err != nil { + if err := p.manageRoutes(event.Route, fmt.Sprintf("%s", event.Type)); err != nil { // TODO: should we bail here? - p.Unlock() continue } - p.Unlock() } } @@ -360,39 +380,28 @@ func (p *Proxy) serveRequest(ctx context.Context, link client.Client, service, e // get raw response resp := stream.Response() - // route watcher error - var watchErr error - // create server response write loop for { - select { - case err := <-p.errChan: - if err != nil { - watchErr = err - } - return watchErr - default: - // read backend response body - body, err := resp.Read() - if err == io.EOF { - return nil - } else if err != nil { - return err - } + // read backend response body + body, err := resp.Read() + if err == io.EOF { + return nil + } else if err != nil { + return err + } - // read backend response header - hdr := resp.Header() + // read backend response header + hdr := resp.Header() - // write raw response header to client - rsp.WriteHeader(hdr) + // write raw response header to client + rsp.WriteHeader(hdr) - // write raw response body to client - err = rsp.Write(body) - if err == io.EOF { - return nil - } else if err != nil { - return err - } + // write raw response body to client + err = rsp.Write(body) + if err == io.EOF { + return nil + } else if err != nil { + return err } } @@ -451,9 +460,6 @@ func NewProxy(opts ...options.Option) proxy.Proxy { // routes cache p.Routes = make(map[string]map[uint64]router.Route) - // watch router service routes - p.errChan = make(chan error, 1) - go func() { // continuously attempt to watch routes for { @@ -464,5 +470,19 @@ func NewProxy(opts ...options.Option) proxy.Proxy { } }() + go func() { + t := time.NewTicker(time.Minute) + defer t.Stop() + + // we must refresh route metrics since they do not trigger new events + for { + select { + case <-t.C: + // refresh route metrics + p.refreshMetrics() + } + } + }() + return p } From b42d242ec1de52d0928943821613ec0ca9812b47 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 25 Oct 2019 23:06:49 +0100 Subject: [PATCH 151/344] hash address based on service name + node address --- network/default.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index 57fcbc26..e11c2ead 100644 --- a/network/default.go +++ b/network/default.go @@ -865,7 +865,10 @@ func (n *network) advertise(advertChan <-chan *router.Advert) { if event.Route.Router == advert.Id { // hash the service before advertising it hasher.Reset() - hasher.Write([]byte(event.Route.Address + n.node.id)) + // routes for multiple instances of a service will be collapsed here. + // TODO: once we store labels in the table this may need to change + // to include the labels in case they differ but highly unlikely + hasher.Write([]byte(event.Route.Service + n.node.Address())) address = fmt.Sprintf("%d", hasher.Sum64()) } // calculate route metric to advertise From 92b7d2db3bc9612a7f0feafbb7b801d180b5c3b3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 25 Oct 2019 23:27:59 +0100 Subject: [PATCH 152/344] Rename to Merge --- metadata/metadata.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/metadata/metadata.go b/metadata/metadata.go index 58c70c3d..f7444501 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -12,6 +12,7 @@ type metaKey struct{} // from Transport headers. type Metadata map[string]string +// Copy makes a copy of the metadata func Copy(md Metadata) Metadata { cmd := make(Metadata) for k, v := range md { @@ -20,16 +21,19 @@ func Copy(md Metadata) Metadata { return cmd } +// FromContext returns metadata from the given context func FromContext(ctx context.Context) (Metadata, bool) { md, ok := ctx.Value(metaKey{}).(Metadata) return md, ok } +// NewContext creates a new context with the given metadata func NewContext(ctx context.Context, md Metadata) context.Context { return context.WithValue(ctx, metaKey{}, md) } -func AppendContext(ctx context.Context, patchMd Metadata, overwrite bool) context.Context { +// MergeContext merges metadata to existing metadata, overwriting if specified +func MergeContext(ctx context.Context, patchMd Metadata, overwrite bool) context.Context { md, _ := ctx.Value(metaKey{}).(Metadata) cmd := make(Metadata) for k, v := range md { From 99b410c81b998088d40a27ec759977be67a38dc6 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 25 Oct 2019 23:28:43 +0100 Subject: [PATCH 153/344] fix metadata test --- metadata/metadata_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/metadata/metadata_test.go b/metadata/metadata_test.go index f05e4229..3706d14c 100644 --- a/metadata/metadata_test.go +++ b/metadata/metadata_test.go @@ -42,7 +42,7 @@ func TestMetadataContext(t *testing.T) { } } -func TestAppendContext(t *testing.T) { +func TestMergeContext(t *testing.T) { type args struct { existing Metadata append Metadata @@ -74,8 +74,8 @@ func TestAppendContext(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got, _ := FromContext(AppendContext(NewContext(context.TODO(), tt.args.existing), tt.args.append, tt.args.overwrite)); !reflect.DeepEqual(got, tt.want) { - t.Errorf("AppendContext() = %v, want %v", got, tt.want) + if got, _ := FromContext(MergeContext(NewContext(context.TODO(), tt.args.existing), tt.args.append, tt.args.overwrite)); !reflect.DeepEqual(got, tt.want) { + t.Errorf("MergeContext() = %v, want %v", got, tt.want) } }) } From d89256d8d57b7fcf523b769d9d2e62dea3c0e8ed Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 28 Oct 2019 15:31:46 +0000 Subject: [PATCH 154/344] add network resolver record priority field --- network/resolver/resolver.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network/resolver/resolver.go b/network/resolver/resolver.go index 369269df..a6cd6b12 100644 --- a/network/resolver/resolver.go +++ b/network/resolver/resolver.go @@ -11,5 +11,6 @@ type Resolver interface { // A resolved record type Record struct { - Address string `json:"address"` + Address string `json:"address"` + Priority int64 `json:"priority"` } From dab0f3223f858072b8631d99771c6853c49e4dad Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 29 Oct 2019 12:29:21 +0000 Subject: [PATCH 155/344] Add Update/List endpoints to runtime --- runtime/default.go | 22 ++++++++++++++++++++++ runtime/runtime.go | 12 ++++++++++++ 2 files changed, 34 insertions(+) diff --git a/runtime/default.go b/runtime/default.go index 9ebf7a06..953e83a5 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -252,6 +252,28 @@ func (r *runtime) Delete(s *Service) error { return nil } +func (r *runtime) Update(s *Service) error { + // delete the service + if err := r.Delete(s); err != nil { + return err + } + + // create new service + return r.Create(s) +} + +func (r *runtime) List() ([]*Service, error) { + var services []*Service + r.RLock() + defer r.RUnlock() + + for _, service := range r.services { + services = append(services, service.Service) + } + + return services, nil +} + func (r *runtime) Start() error { r.Lock() defer r.Unlock() diff --git a/runtime/runtime.go b/runtime/runtime.go index 63216867..0cb84802 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -7,6 +7,10 @@ type Runtime interface { Create(*Service, ...CreateOption) error // Remove a service Delete(*Service) error + // Update the service in place + Update(*Service) error + // List the managed services + List() ([]*Service, error) // starts the runtime Start() error // Shutdown the runtime @@ -36,6 +40,14 @@ func Delete(s *Service) error { return DefaultRuntime.Delete(s) } +func Update(s *Service) error { + return DefaultRuntime.Update(s) +} + +func List() ([]*Service, error) { + return DefaultRuntime.List() +} + func Start() error { return DefaultRuntime.Start() } From f9c639af4ed314b31759c8a6972fe310d8049eca Mon Sep 17 00:00:00 2001 From: yandd <982724342@qq.com> Date: Wed, 30 Oct 2019 14:01:51 +0800 Subject: [PATCH 156/344] fix rcache ttl --- registry/cache/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/cache/cache.go b/registry/cache/cache.go index a6068ae8..f8bee4a9 100644 --- a/registry/cache/cache.go +++ b/registry/cache/cache.go @@ -81,7 +81,7 @@ func (c *cache) isValid(services []*registry.Service, ttl time.Time) bool { } // time since ttl is longer than timeout - if time.Since(ttl) > c.opts.TTL { + if time.Since(ttl) > 0 { return false } From cf593e7c50edb7d962242693861eed4590ef8244 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 31 Oct 2019 17:22:38 +0000 Subject: [PATCH 157/344] fix link panic --- tunnel/default.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index 0b064c36..ae7b69fa 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -225,9 +225,10 @@ func (t *tun) monitor() { t.Lock() for _, node := range delLinks { log.Debugf("Tunnel deleting dead link for %s", node) - link := t.links[node] - link.Close() - delete(t.links, node) + if link, ok := t.links[node]; ok { + link.Close() + delete(t.links, node) + } } t.Unlock() } From 967d7ecda77eebebac0418ab9527c22a641df933 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 31 Oct 2019 22:30:21 +0000 Subject: [PATCH 158/344] fix runtime panic --- runtime/default.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/runtime/default.go b/runtime/default.go index 953e83a5..a240e71c 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -113,7 +113,7 @@ func (s *service) Start() error { s.closed = make(chan bool) // TODO: pull source & build binary - log.Debugf("Runtime service %s forking new process\n") + log.Debugf("Runtime service %s forking new process\n", s.Service.Name) p, err := s.Process.Fork(s.Exec) if err != nil { return err @@ -144,6 +144,9 @@ func (s *service) Stop() error { default: close(s.closed) s.running = false + if s.PID == nil { + return nil + } return s.Process.Kill(s.PID) } From 174fbde049959245cb90bdf342df621953024842 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 31 Oct 2019 22:34:06 +0000 Subject: [PATCH 159/344] add ability to filter routes based on headers --- network/default.go | 31 +++++++++++---------- proxy/mucp/mucp.go | 69 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/network/default.go b/network/default.go index e11c2ead..3c395064 100644 --- a/network/default.go +++ b/network/default.go @@ -79,21 +79,6 @@ func newNetwork(opts ...Option) Network { o(&options) } - // init tunnel address to the network bind address - options.Tunnel.Init( - tunnel.Address(options.Address), - ) - - // init router Id to the network id - options.Router.Init( - router.Id(options.Id), - ) - - // create tunnel client with tunnel transport - tunTransport := tun.NewTransport( - tun.WithTunnel(options.Tunnel), - ) - // set the address to a hashed address hasher := fnv.New64() hasher.Write([]byte(options.Address + options.Id)) @@ -111,6 +96,22 @@ func newNetwork(opts ...Option) Network { peerAddress = address } + // init tunnel address to the network bind address + options.Tunnel.Init( + tunnel.Address(options.Address), + ) + + // init router Id to the network id + options.Router.Init( + router.Id(options.Id), + router.Address(peerAddress), + ) + + // create tunnel client with tunnel transport + tunTransport := tun.NewTransport( + tun.WithTunnel(options.Tunnel), + ) + // server is network server server := server.NewServer( server.Id(options.Id), diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index 02f28d89..02ab381c 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -16,6 +16,7 @@ import ( "github.com/micro/go-micro/codec/bytes" "github.com/micro/go-micro/config/options" "github.com/micro/go-micro/errors" + "github.com/micro/go-micro/metadata" "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/router" "github.com/micro/go-micro/server" @@ -105,6 +106,63 @@ func toSlice(r map[uint64]router.Route) []router.Route { return routes } +func (p *Proxy) filterRoutes(ctx context.Context, routes []router.Route) []router.Route { + md, ok := metadata.FromContext(ctx) + if !ok { + return routes + } + + var filteredRoutes []router.Route + + // filter the routes based on our headers + for _, route := range routes { + // process only routes for this id + if id := md["Micro-Router"]; len(id) > 0 { + if route.Router != id { + // skip routes that don't mwatch + continue + } + } + + // only process routes with this network + if net := md["Micro-Network"]; len(net) > 0 { + if route.Network != net { + // skip routes that don't mwatch + continue + } + } + + // process only this gateway + if gw := md["Micro-Gateway"]; len(gw) > 0 { + // if the gateway matches our address + // special case, take the routes with no gateway + // TODO: should we strip the gateway from the context? + if gw == p.Router.Options().Address { + if len(route.Gateway) > 0 && route.Gateway != gw { + continue + } + // otherwise its a local route and we're keeping it + } else { + // gateway does not match our own + if route.Gateway != gw { + continue + } + } + } + + // TODO: address based filtering + // address := md["Micro-Address"] + + // TODO: label based filtering + // requires new field in routing table : route.Labels + + // passed the filter checks + filteredRoutes = append(filteredRoutes, route) + } + + return filteredRoutes +} + func (p *Proxy) getLink(r router.Route) (client.Client, error) { if r.Link == "local" || len(p.Links) == 0 { return p.Client, nil @@ -116,13 +174,14 @@ func (p *Proxy) getLink(r router.Route) (client.Client, error) { return l, nil } -func (p *Proxy) getRoute(service string) ([]router.Route, error) { +func (p *Proxy) getRoute(ctx context.Context, service string) ([]router.Route, error) { // lookup the route cache first p.Lock() cached, ok := p.Routes[service] if ok { p.Unlock() - return toSlice(cached), nil + routes := toSlice(cached) + return p.filterRoutes(ctx, routes), nil } p.Unlock() @@ -132,7 +191,7 @@ func (p *Proxy) getRoute(service string) ([]router.Route, error) { return nil, err } - return routes, nil + return p.filterRoutes(ctx, routes), nil } func (p *Proxy) cacheRoutes(service string) ([]router.Route, error) { @@ -255,7 +314,7 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server addresses = []string{p.Endpoint} } else { // get route for endpoint from router - addr, err := p.getRoute(p.Endpoint) + addr, err := p.getRoute(ctx, p.Endpoint) if err != nil { return err } @@ -267,7 +326,7 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server } else { // no endpoint was specified just lookup the route // get route for endpoint from router - addr, err := p.getRoute(service) + addr, err := p.getRoute(ctx, service) if err != nil { return err } From 0aa01b2ebf9cdfbfc8dcbeaf3e4d4da9d3621907 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 1 Nov 2019 08:33:14 +0000 Subject: [PATCH 160/344] Output the build error in plugin --- plugin/default.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/default.go b/plugin/default.go index bcafbc3b..8fde651a 100644 --- a/plugin/default.go +++ b/plugin/default.go @@ -121,5 +121,7 @@ func (p *plugin) Build(path string, c *Config) error { return fmt.Errorf("Failed to create dir %s: %v", filepath.Dir(path), err) } cmd := exec.Command("go", "build", "-buildmode=plugin", "-o", path+".so", goFile) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr return cmd.Run() } From dee63b2b2cc7c9299070ae8dd58969cbc1a31454 Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Fri, 1 Nov 2019 14:13:21 +0000 Subject: [PATCH 161/344] Implementation of postgres store --- store/options.go | 8 +- store/postgresql/postgresql.go | 244 ++++++++++++++++++++++++++++ store/postgresql/postgresql_test.go | 95 +++++++++++ store/store.go | 7 +- 4 files changed, 350 insertions(+), 4 deletions(-) create mode 100644 store/postgresql/postgresql.go create mode 100644 store/postgresql/postgresql_test.go diff --git a/store/options.go b/store/options.go index cf780a58..99014362 100644 --- a/store/options.go +++ b/store/options.go @@ -4,7 +4,7 @@ import ( "github.com/micro/go-micro/config/options" ) -// Set the nodes used to back the store +// Nodes is a list of nodes used to back the store func Nodes(a ...string) options.Option { return options.WithValue("store.nodes", a) } @@ -13,3 +13,9 @@ func Nodes(a ...string) options.Option { func Prefix(p string) options.Option { return options.WithValue("store.prefix", p) } + +// Namespace offers a way to have multiple isolated +// stores in the same backend, if supported. +func Namespace(n string) options.Option { + return options.WithValue("store.namespace", n) +} diff --git a/store/postgresql/postgresql.go b/store/postgresql/postgresql.go new file mode 100644 index 00000000..7abca6df --- /dev/null +++ b/store/postgresql/postgresql.go @@ -0,0 +1,244 @@ +// Package postgresql implements a micro Store backed by sql +package postgresql + +import ( + "database/sql" + "fmt" + "time" + "unicode" + + "github.com/lib/pq" + "github.com/pkg/errors" + + "github.com/micro/go-micro/config/options" + "github.com/micro/go-micro/store" +) + +// DefaultNamespace is the namespace that the sql store +// will use if no namespace is provided. +const DefaultNamespace = "micro" + +type sqlStore struct { + db *sql.DB + + table string + options.Options +} + +// List all the known records +func (s *sqlStore) List() ([]*store.Record, error) { + q, err := s.db.Prepare(fmt.Sprintf("SELECT key, value, expiry FROM micro.%s;", s.table)) + if err != nil { + return nil, err + } + var records []*store.Record + var timehelper pq.NullTime + rows, err := q.Query() + if err != nil { + if err == sql.ErrNoRows { + return records, nil + } + return nil, err + } + defer rows.Close() + for rows.Next() { + record := &store.Record{} + if err := rows.Scan(&record.Key, &record.Value, &timehelper); err != nil { + return records, err + } + if timehelper.Valid { + if timehelper.Time.Before(time.Now()) { + // record has expired + go s.Delete(record.Key) + } else { + record.Expiry = time.Until(timehelper.Time) + records = append(records, record) + } + } else { + records = append(records, record) + } + + } + rowErr := rows.Close() + if rowErr != nil { + // transaction rollback or something + return records, rowErr + } + if err := rows.Err(); err != nil { + return records, err + } + return records, nil +} + +// Read all records with keys +func (s *sqlStore) Read(keys ...string) ([]*store.Record, error) { + q, err := s.db.Prepare(fmt.Sprintf("SELECT key, value, expiry FROM micro.%s WHERE key = $1;", s.table)) + if err != nil { + return nil, err + } + var records []*store.Record + var timehelper pq.NullTime + for _, key := range keys { + row := q.QueryRow(key) + record := &store.Record{} + if err := row.Scan(&record.Key, &record.Value, &timehelper); err != nil { + if err == sql.ErrNoRows { + return records, store.ErrNotFound + } + return records, err + } + if timehelper.Valid { + if timehelper.Time.Before(time.Now()) { + // record has expired + go s.Delete(key) + return records, store.ErrNotFound + } + record.Expiry = time.Until(timehelper.Time) + records = append(records, record) + } else { + records = append(records, record) + } + } + return records, nil +} + +// Write records +func (s *sqlStore) Write(rec ...*store.Record) error { + q, err := s.db.Prepare(fmt.Sprintf(`INSERT INTO micro.%s(key, value, expiry) + VALUES ($1, $2::bytea, $3) + ON CONFLICT (key) + DO UPDATE + SET value = EXCLUDED.value, expiry = EXCLUDED.expiry;`, s.table)) + if err != nil { + return err + } + for _, r := range rec { + var err error + if r.Expiry != 0 { + _, err = q.Exec(r.Key, r.Value, time.Now().Add(r.Expiry)) + } else { + _, err = q.Exec(r.Key, r.Value, nil) + } + if err != nil { + return errors.Wrap(err, "Couldn't insert record "+r.Key) + } + } + + return nil +} + +// Delete records with keys +func (s *sqlStore) Delete(keys ...string) error { + q, err := s.db.Prepare(fmt.Sprintf("DELETE FROM micro.%s WHERE key = $1;", s.table)) + if err != nil { + return err + } + for _, key := range keys { + result, err := q.Exec(key) + if err != nil { + return err + } + _, err = result.RowsAffected() + if err != nil { + return err + } + } + return nil +} + +func (s *sqlStore) initDB(options options.Options) error { + // Get the store.namespace option, or use sql.DefaultNamespace + namespaceOpt, found := options.Values().Get("store.namespace") + if !found { + s.table = DefaultNamespace + } else { + if namespace, ok := namespaceOpt.(string); ok { + s.table = namespace + } else { + return errors.New("store.namespace option must be a string") + } + } + + // Create "micro" schema + schema, err := s.db.Prepare("CREATE SCHEMA IF NOT EXISTS micro ;") + if err != nil { + return err + } + _, err = schema.Exec() + if err != nil { + return errors.Wrap(err, "Couldn't create Schema") + } + + // Create a table for the Store namespace + tableq, err := s.db.Prepare(fmt.Sprintf(`CREATE TABLE IF NOT EXISTS micro.%s + ( + key text COLLATE "default" NOT NULL, + value bytea, + expiry timestamp with time zone, + CONSTRAINT %s_pkey PRIMARY KEY (key) + );`, s.table, s.table)) + _, err = tableq.Exec() + if err != nil { + return errors.Wrap(err, "Couldn't create table") + } + + return nil +} + +// New returns a new micro Store backed by sql +func New(opts ...options.Option) (store.Store, error) { + options := options.NewOptions(opts...) + driver, dataSourceName, err := validateOptions(options) + if err != nil { + return nil, err + } + db, err := sql.Open(driver, dataSourceName) + if err != nil { + return nil, err + } + if err := db.Ping(); err != nil { + return nil, err + } + s := &sqlStore{ + db: db, + } + + return s, s.initDB(options) +} + +// validateOptions checks whether the provided options are valid, then returns the driver +// and data source name. +func validateOptions(options options.Options) (driver, dataSourceName string, err error) { + driverOpt, found := options.Values().Get("store.sql.driver") + if !found { + return "", "", errors.New("No store.sql.driver option specified") + } + nodesOpt, found := options.Values().Get("store.nodes") + if !found { + return "", "", errors.New("No store.nodes option specified (expected a database connection string)") + } + driver, ok := driverOpt.(string) + if !ok { + return "", "", errors.New("store.sql.driver option must be a string") + } + nodes, ok := nodesOpt.([]string) + if !ok { + return "", "", errors.New("store.nodes option must be a []string") + } + if len(nodes) != 1 { + return "", "", errors.New("expected only 1 store.nodes option") + } + namespaceOpt, found := options.Values().Get("store.namespace") + if found { + namespace, ok := namespaceOpt.(string) + if !ok { + return "", "", errors.New("store.namespace must me a string") + } + for _, r := range namespace { + if !unicode.IsLetter(r) { + return "", "", errors.New("store.namespace must only contain letters") + } + } + } + return driver, nodes[0], nil +} diff --git a/store/postgresql/postgresql_test.go b/store/postgresql/postgresql_test.go new file mode 100644 index 00000000..65d97e78 --- /dev/null +++ b/store/postgresql/postgresql_test.go @@ -0,0 +1,95 @@ +package postgresql + +import ( + "database/sql" + "fmt" + "testing" + "time" + + "github.com/kr/pretty" + "github.com/micro/go-micro/store" +) + +func TestSQL(t *testing.T) { + connection := fmt.Sprintf( + "host=%s port=%d user=%s sslmode=disable dbname=%s", + "localhost", + 5432, + "jake", + "test", + ) + db, err := sql.Open("postgres", connection) + if err != nil { + t.Fatal(err) + } + if err := db.Ping(); err != nil { + t.Skip(err) + } + db.Close() + + sqlStore, err := New( + store.Namespace("testsql"), + store.Nodes(connection), + ) + if err != nil { + t.Fatal(err.Error()) + } + + records, err := sqlStore.List() + if err != nil { + t.Error(err) + } else { + t.Logf("%# v\n", pretty.Formatter(records)) + } + + err = sqlStore.Write( + &store.Record{ + Key: "test", + Value: []byte("foo"), + }, + &store.Record{ + Key: "bar", + Value: []byte("baz"), + }, + &store.Record{ + Key: "qux", + Value: []byte("aasad"), + }, + ) + if err != nil { + t.Error(err) + } + err = sqlStore.Delete("qux") + if err != nil { + t.Error(err) + } + + err = sqlStore.Write(&store.Record{ + Key: "test", + Value: []byte("bar"), + Expiry: time.Minute, + }) + if err != nil { + t.Error(err) + } + + records, err = sqlStore.Read("test") + if err != nil { + t.Error(err) + } else { + t.Logf("%# v\n", pretty.Formatter(records)) + if string(records[0].Value) != "bar" { + t.Error("Expected bar, got ", string(records[0].Value)) + } + } + + time.Sleep(61 * time.Second) + records, err = sqlStore.Read("test") + if err == nil { + t.Error("Key test should have expired") + } else { + if err != store.ErrNotFound { + t.Error(err) + } + } +} diff --git a/store/store.go b/store/store.go index c45712eb..9d265500 100644 --- a/store/store.go +++ b/store/store.go @@ -7,6 +7,7 @@ import ( ) var ( + // ErrNotFound is returned when a Read key doesn't exist ErrNotFound = errors.New("not found") ) @@ -14,11 +15,11 @@ var ( type Store interface { // List all the known records List() ([]*Record, error) - // Read a record with key + // Read records with keys Read(key ...string) ([]*Record, error) - // Write a record + // Write records Write(rec ...*Record) error - // Delete a record with key + // Delete records with keys Delete(key ...string) error } From ee35fe61af23b51fab3e19a0cfbec0ef9481ad5c Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Fri, 1 Nov 2019 14:13:47 +0000 Subject: [PATCH 162/344] update go.mod for postgres --- go.mod | 2 ++ go.sum | 2 ++ 2 files changed, 4 insertions(+) diff --git a/go.mod b/go.mod index a08ccfe0..12808717 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,9 @@ require ( github.com/jonboulle/clockwork v0.1.0 // indirect github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 github.com/json-iterator/go v1.1.7 + github.com/kr/pretty v0.1.0 github.com/leodido/go-urn v1.1.0 // indirect + github.com/lib/pq v1.2.0 github.com/lucas-clemente/quic-go v0.12.1 github.com/mholt/certmagic v0.7.5 github.com/micro/cli v0.2.0 diff --git a/go.sum b/go.sum index 6970348f..fd44a28e 100644 --- a/go.sum +++ b/go.sum @@ -228,6 +228,8 @@ github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HK github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= +github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= github.com/lucas-clemente/quic-go v0.12.1 h1:BPITli+6KnKogtTxBk2aS4okr5dUHz2LtIDAP1b8UL4= From f88518d99446431ec6d8ec04cc21f201538a0060 Mon Sep 17 00:00:00 2001 From: tegk Date: Fri, 1 Nov 2019 15:07:53 +0000 Subject: [PATCH 163/344] used gofmt with -s flag on whole project --- api/handler/api/util_test.go | 2 +- api/handler/http/http_test.go | 2 +- broker/common_test.go | 2 +- broker/http_broker_test.go | 2 +- client/common_test.go | 2 +- client/grpc/grpc_test.go | 2 +- client/rpc_client_test.go | 2 +- client/selector/common_test.go | 2 +- client/selector/dns/dns.go | 2 +- client/selector/filter_test.go | 40 +++++++++++++++---------------- client/selector/strategy_test.go | 12 +++++----- common_test.go | 2 +- config/reader/json/values_test.go | 2 +- errors/errors_test.go | 2 +- monitor/default.go | 8 +++---- proxy/http/http.go | 2 +- proxy/mucp/mucp.go | 2 +- registry/encoding_test.go | 4 ++-- registry/mdns_test.go | 12 +++++----- registry/memory/memory_test.go | 4 ++-- registry/watcher_test.go | 12 +++++----- router/service/service.go | 2 +- server/grpc/grpc.go | 2 +- server/rpc_server.go | 2 +- tunnel/default.go | 2 +- web/service.go | 2 +- 26 files changed, 65 insertions(+), 65 deletions(-) diff --git a/api/handler/api/util_test.go b/api/handler/api/util_test.go index 0a82a03d..9350bcde 100644 --- a/api/handler/api/util_test.go +++ b/api/handler/api/util_test.go @@ -8,7 +8,7 @@ import ( func TestRequestToProto(t *testing.T) { testData := []*http.Request{ - &http.Request{ + { Method: "GET", Header: http.Header{ "Header": []string{"test"}, diff --git a/api/handler/http/http_test.go b/api/handler/http/http_test.go index 31847221..9812535c 100644 --- a/api/handler/http/http_test.go +++ b/api/handler/http/http_test.go @@ -27,7 +27,7 @@ func testHttp(t *testing.T, path, service, ns string) { s := ®istry.Service{ Name: service, Nodes: []*registry.Node{ - ®istry.Node{ + { Id: service + "-1", Address: l.Addr().String(), }, diff --git a/broker/common_test.go b/broker/common_test.go index 262a77eb..c01d42c7 100644 --- a/broker/common_test.go +++ b/broker/common_test.go @@ -7,7 +7,7 @@ import ( var ( // mock data testData = map[string][]*registry.Service{ - "foo": []*registry.Service{ + "foo": { { Name: "foo", Version: "1.0.0", diff --git a/broker/http_broker_test.go b/broker/http_broker_test.go index 4695033e..c3849ac6 100644 --- a/broker/http_broker_test.go +++ b/broker/http_broker_test.go @@ -125,7 +125,7 @@ func pub(be *testing.B, c int) { for i := 0; i < c; i++ { go func() { - for _ = range ch { + for range ch { if err := b.Publish(topic, msg); err != nil { be.Fatalf("Unexpected publish error: %v", err) } diff --git a/client/common_test.go b/client/common_test.go index 15ddc158..42d1ed87 100644 --- a/client/common_test.go +++ b/client/common_test.go @@ -7,7 +7,7 @@ import ( var ( // mock data testData = map[string][]*registry.Service{ - "foo": []*registry.Service{ + "foo": { { Name: "foo", Version: "1.0.0", diff --git a/client/grpc/grpc_test.go b/client/grpc/grpc_test.go index 5696a267..e437c0ef 100644 --- a/client/grpc/grpc_test.go +++ b/client/grpc/grpc_test.go @@ -42,7 +42,7 @@ func TestGRPCClient(t *testing.T) { Name: "helloworld", Version: "test", Nodes: []*registry.Node{ - ®istry.Node{ + { Id: "test-1", Address: l.Addr().String(), }, diff --git a/client/rpc_client_test.go b/client/rpc_client_test.go index 14547e9f..88cd08d8 100644 --- a/client/rpc_client_test.go +++ b/client/rpc_client_test.go @@ -143,7 +143,7 @@ func TestCallWrapper(t *testing.T) { Name: service, Version: "latest", Nodes: []*registry.Node{ - ®istry.Node{ + { Id: id, Address: address, }, diff --git a/client/selector/common_test.go b/client/selector/common_test.go index 7aba0542..1af55c1c 100644 --- a/client/selector/common_test.go +++ b/client/selector/common_test.go @@ -7,7 +7,7 @@ import ( var ( // mock data testData = map[string][]*registry.Service{ - "foo": []*registry.Service{ + "foo": { { Name: "foo", Version: "1.0.0", diff --git a/client/selector/dns/dns.go b/client/selector/dns/dns.go index df6c209f..4248fe3d 100644 --- a/client/selector/dns/dns.go +++ b/client/selector/dns/dns.go @@ -72,7 +72,7 @@ func (d *dnsSelector) Select(service string, opts ...selector.SelectOption) (sel } services := []*registry.Service{ - ®istry.Service{ + { Name: service, Nodes: nodes, }, diff --git a/client/selector/filter_test.go b/client/selector/filter_test.go index 5a3e9c0d..035feed3 100644 --- a/client/selector/filter_test.go +++ b/client/selector/filter_test.go @@ -14,20 +14,20 @@ func TestFilterEndpoint(t *testing.T) { }{ { services: []*registry.Service{ - ®istry.Service{ + { Name: "test", Version: "1.0.0", Endpoints: []*registry.Endpoint{ - ®istry.Endpoint{ + { Name: "Foo.Bar", }, }, }, - ®istry.Service{ + { Name: "test", Version: "1.1.0", Endpoints: []*registry.Endpoint{ - ®istry.Endpoint{ + { Name: "Baz.Bar", }, }, @@ -38,20 +38,20 @@ func TestFilterEndpoint(t *testing.T) { }, { services: []*registry.Service{ - ®istry.Service{ + { Name: "test", Version: "1.0.0", Endpoints: []*registry.Endpoint{ - ®istry.Endpoint{ + { Name: "Foo.Bar", }, }, }, - ®istry.Service{ + { Name: "test", Version: "1.1.0", Endpoints: []*registry.Endpoint{ - ®istry.Endpoint{ + { Name: "Foo.Bar", }, }, @@ -95,11 +95,11 @@ func TestFilterLabel(t *testing.T) { }{ { services: []*registry.Service{ - ®istry.Service{ + { Name: "test", Version: "1.0.0", Nodes: []*registry.Node{ - ®istry.Node{ + { Id: "test-1", Address: "localhost", Metadata: map[string]string{ @@ -108,11 +108,11 @@ func TestFilterLabel(t *testing.T) { }, }, }, - ®istry.Service{ + { Name: "test", Version: "1.1.0", Nodes: []*registry.Node{ - ®istry.Node{ + { Id: "test-2", Address: "localhost", Metadata: map[string]string{ @@ -127,21 +127,21 @@ func TestFilterLabel(t *testing.T) { }, { services: []*registry.Service{ - ®istry.Service{ + { Name: "test", Version: "1.0.0", Nodes: []*registry.Node{ - ®istry.Node{ + { Id: "test-1", Address: "localhost", }, }, }, - ®istry.Service{ + { Name: "test", Version: "1.1.0", Nodes: []*registry.Node{ - ®istry.Node{ + { Id: "test-2", Address: "localhost", }, @@ -187,11 +187,11 @@ func TestFilterVersion(t *testing.T) { }{ { services: []*registry.Service{ - ®istry.Service{ + { Name: "test", Version: "1.0.0", }, - ®istry.Service{ + { Name: "test", Version: "1.1.0", }, @@ -201,11 +201,11 @@ func TestFilterVersion(t *testing.T) { }, { services: []*registry.Service{ - ®istry.Service{ + { Name: "test", Version: "1.0.0", }, - ®istry.Service{ + { Name: "test", Version: "1.1.0", }, diff --git a/client/selector/strategy_test.go b/client/selector/strategy_test.go index 8ea9376a..2529a6b7 100644 --- a/client/selector/strategy_test.go +++ b/client/selector/strategy_test.go @@ -8,29 +8,29 @@ import ( func TestStrategies(t *testing.T) { testData := []*registry.Service{ - ®istry.Service{ + { Name: "test1", Version: "latest", Nodes: []*registry.Node{ - ®istry.Node{ + { Id: "test1-1", Address: "10.0.0.1:1001", }, - ®istry.Node{ + { Id: "test1-2", Address: "10.0.0.2:1002", }, }, }, - ®istry.Service{ + { Name: "test1", Version: "default", Nodes: []*registry.Node{ - ®istry.Node{ + { Id: "test1-3", Address: "10.0.0.3:1003", }, - ®istry.Node{ + { Id: "test1-4", Address: "10.0.0.4:1004", }, diff --git a/common_test.go b/common_test.go index d4fd4bfb..6a1ed2d8 100644 --- a/common_test.go +++ b/common_test.go @@ -7,7 +7,7 @@ import ( var ( // mock data testData = map[string][]*registry.Service{ - "foo": []*registry.Service{ + "foo": { { Name: "foo", Version: "1.0.0", diff --git a/config/reader/json/values_test.go b/config/reader/json/values_test.go index 97aec68a..166d9ae0 100644 --- a/config/reader/json/values_test.go +++ b/config/reader/json/values_test.go @@ -62,7 +62,7 @@ func TestStructArray(t *testing.T) { { []byte(`[{"foo": "bar"}]`), emptyTSlice, - []T{T{Foo: "bar"}}, + []T{{Foo: "bar"}}, }, } diff --git a/errors/errors_test.go b/errors/errors_test.go index 5df084d2..757d275d 100644 --- a/errors/errors_test.go +++ b/errors/errors_test.go @@ -7,7 +7,7 @@ import ( func TestErrors(t *testing.T) { testData := []*Error{ - &Error{ + { Id: "test", Code: 500, Detail: "Internal server error", diff --git a/monitor/default.go b/monitor/default.go index a03a0b31..050f8335 100644 --- a/monitor/default.go +++ b/monitor/default.go @@ -140,7 +140,7 @@ func (m *monitor) reap() { defer m.Unlock() // range over our watched services - for service, _ := range m.services { + for service := range m.services { // check if the service exists in the registry if !serviceMap[service] { // if not, delete it in our status map @@ -195,14 +195,14 @@ func (m *monitor) run() { serviceMap := make(map[string]bool) m.RLock() - for service, _ := range m.services { + for service := range m.services { serviceMap[service] = true } m.RUnlock() go func() { // check the status of all watched services - for service, _ := range serviceMap { + for service := range serviceMap { select { case <-m.exit: return @@ -307,7 +307,7 @@ func (m *monitor) Stop() error { return nil default: close(m.exit) - for s, _ := range m.services { + for s := range m.services { delete(m.services, s) } m.registry.Stop() diff --git a/proxy/http/http.go b/proxy/http/http.go index 37ef1f87..0df61927 100644 --- a/proxy/http/http.go +++ b/proxy/http/http.go @@ -113,7 +113,7 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server // set response headers hdr = map[string]string{} - for k, _ := range hrsp.Header { + for k := range hrsp.Header { hdr[k] = hrsp.Header.Get(k) } // write the header diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index 02ab381c..91c40bc0 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -228,7 +228,7 @@ func (p *Proxy) refreshMetrics() { // get a list of services to update p.RLock() - for service, _ := range p.Routes { + for service := range p.Routes { services = append(services, service) } p.RUnlock() diff --git a/registry/encoding_test.go b/registry/encoding_test.go index 89acd980..ff9ae97e 100644 --- a/registry/encoding_test.go +++ b/registry/encoding_test.go @@ -6,13 +6,13 @@ import ( func TestEncoding(t *testing.T) { testData := []*mdnsTxt{ - &mdnsTxt{ + { Version: "1.0.0", Metadata: map[string]string{ "foo": "bar", }, Endpoints: []*Endpoint{ - &Endpoint{ + { Name: "endpoint1", Request: &Value{ Name: "request", diff --git a/registry/mdns_test.go b/registry/mdns_test.go index e9813c69..bd544df9 100644 --- a/registry/mdns_test.go +++ b/registry/mdns_test.go @@ -7,11 +7,11 @@ import ( func TestMDNS(t *testing.T) { testData := []*Service{ - &Service{ + { Name: "test1", Version: "1.0.1", Nodes: []*Node{ - &Node{ + { Id: "test1-1", Address: "10.0.0.1:10001", Metadata: map[string]string{ @@ -20,11 +20,11 @@ func TestMDNS(t *testing.T) { }, }, }, - &Service{ + { Name: "test2", Version: "1.0.2", Nodes: []*Node{ - &Node{ + { Id: "test2-1", Address: "10.0.0.2:10002", Metadata: map[string]string{ @@ -33,11 +33,11 @@ func TestMDNS(t *testing.T) { }, }, }, - &Service{ + { Name: "test3", Version: "1.0.3", Nodes: []*Node{ - &Node{ + { Id: "test3-1", Address: "10.0.0.3:10003", Metadata: map[string]string{ diff --git a/registry/memory/memory_test.go b/registry/memory/memory_test.go index fa8b53f1..593122bf 100644 --- a/registry/memory/memory_test.go +++ b/registry/memory/memory_test.go @@ -8,7 +8,7 @@ import ( var ( testData = map[string][]*registry.Service{ - "foo": []*registry.Service{ + "foo": { { Name: "foo", Version: "1.0.0", @@ -44,7 +44,7 @@ var ( }, }, }, - "bar": []*registry.Service{ + "bar": { { Name: "bar", Version: "default", diff --git a/registry/watcher_test.go b/registry/watcher_test.go index 94c8c275..a564bcda 100644 --- a/registry/watcher_test.go +++ b/registry/watcher_test.go @@ -6,11 +6,11 @@ import ( func TestWatcher(t *testing.T) { testData := []*Service{ - &Service{ + { Name: "test1", Version: "1.0.1", Nodes: []*Node{ - &Node{ + { Id: "test1-1", Address: "10.0.0.1:10001", Metadata: map[string]string{ @@ -19,11 +19,11 @@ func TestWatcher(t *testing.T) { }, }, }, - &Service{ + { Name: "test2", Version: "1.0.2", Nodes: []*Node{ - &Node{ + { Id: "test2-1", Address: "10.0.0.2:10002", Metadata: map[string]string{ @@ -32,11 +32,11 @@ func TestWatcher(t *testing.T) { }, }, }, - &Service{ + { Name: "test3", Version: "1.0.3", Nodes: []*Node{ - &Node{ + { Id: "test3-1", Address: "10.0.0.3:10003", Metadata: map[string]string{ diff --git a/router/service/service.go b/router/service/service.go index 4f9dcb9b..3d95ab5b 100644 --- a/router/service/service.go +++ b/router/service/service.go @@ -230,7 +230,7 @@ func (s *svc) Solicit() error { // build events to advertise events := make([]*router.Event, len(routes)) - for i, _ := range events { + for i := range events { events[i] = &router.Event{ Type: router.Update, Timestamp: time.Now(), diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index 8da88b97..e037a0d1 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -621,7 +621,7 @@ func (g *grpcServer) Register() error { g.registered = true - for sb, _ := range g.subscribers { + for sb := range g.subscribers { handler := g.createSubHandler(sb, g.opts) var opts []broker.SubscribeOption if queue := sb.Options().Queue; len(queue) > 0 { diff --git a/server/rpc_server.go b/server/rpc_server.go index 89d60f9e..76687e30 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -531,7 +531,7 @@ func (s *rpcServer) Register() error { s.registered = true - for sb, _ := range s.subscribers { + for sb := range s.subscribers { handler := s.createSubHandler(sb, s.opts) var opts []broker.SubscribeOption if queue := sb.Options().Queue; len(queue) > 0 { diff --git a/tunnel/default.go b/tunnel/default.go index ae7b69fa..314ee908 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -590,7 +590,7 @@ func (t *tun) listen(link *link) { } // strip tunnel message header - for k, _ := range msg.Header { + for k := range msg.Header { if strings.HasPrefix(k, "Micro-Tunnel") { delete(msg.Header, k) } diff --git a/web/service.go b/web/service.go index 65359a2b..e0a7014e 100644 --- a/web/service.go +++ b/web/service.go @@ -82,7 +82,7 @@ func (s *service) genSrv() *registry.Service { return ®istry.Service{ Name: s.opts.Name, Version: s.opts.Version, - Nodes: []*registry.Node{®istry.Node{ + Nodes: []*registry.Node{{ Id: s.opts.Id, Address: fmt.Sprintf("%s:%d", addr, port), Metadata: s.opts.Metadata, From e9dfccc61632aafeb7ee79de29df397e2430b409 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 1 Nov 2019 15:08:01 +0000 Subject: [PATCH 164/344] Fix panic caused when ctrl+c a non started service --- runtime/default.go | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/default.go b/runtime/default.go index a240e71c..797ec107 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -85,6 +85,7 @@ func newService(s *Service, c CreateOptions) *service { Env: c.Env, Args: args, }, + closed: make(chan bool), output: c.Output, } } From 15e3b9b4c0cd41678ea8d1fe7e2d6cc553f35f6c Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Fri, 1 Nov 2019 15:16:05 +0000 Subject: [PATCH 165/344] Let people connect with just a hostname --- store/postgresql/postgresql.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/store/postgresql/postgresql.go b/store/postgresql/postgresql.go index 7abca6df..a574c5ed 100644 --- a/store/postgresql/postgresql.go +++ b/store/postgresql/postgresql.go @@ -4,6 +4,7 @@ package postgresql import ( "database/sql" "fmt" + "strings" "time" "unicode" @@ -192,6 +193,9 @@ func New(opts ...options.Option) (store.Store, error) { if err != nil { return nil, err } + if !strings.Contains(dataSourceName, " ") { + dataSourceName = fmt.Sprintf("host=%s", dataSourceName) + } db, err := sql.Open(driver, dataSourceName) if err != nil { return nil, err From e8d2f207d8b23e800d0a84f587c6481be44f5127 Mon Sep 17 00:00:00 2001 From: Hobo86 Date: Sat, 2 Nov 2019 16:39:56 +0800 Subject: [PATCH 166/344] fix-907 web service need modify registry service nodes while register interval --- web/service.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/web/service.go b/web/service.go index e0a7014e..da78d6c8 100644 --- a/web/service.go +++ b/web/service.go @@ -118,6 +118,11 @@ func (s *service) register() error { if s.opts.Registry != nil { r = s.opts.Registry } + + // service node need modify, node address maybe changed + srv := s.genSrv() + srv.Endpoints = s.srv.Endpoints + s.srv = srv return r.Register(s.srv, registry.RegisterTTL(s.opts.RegisterTTL)) } From 6f7702a093d9defd8b5f5710f7a511b44824cfea Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Sat, 2 Nov 2019 13:25:10 +0000 Subject: [PATCH 167/344] [WIP] K8s update and runtime package changes (#895) * First commit: outline of K8s runtime package * Added poller. Added auto-updater into default runtime * Added build and updated Poller interface * Added comments and NewRuntime that accepts Options * DefaultPoller; Runtime options * First commit to add Kubernetes cruft * Add comments * Add micro- prefix to K8s runtime service names * Get rid of import cycles. Move K8s runtime into main runtime package * Major refactoring: Poller replaced by Notifier POller has been replaced by Notifier which returns a channel of events that can be consumed and acted upon. * Added runtime configuration options * K8s runtime is now Kubernetes runtime in dedicated pkg. Naming kung-fu. * Fix typo in command. * Fixed typo * Dont Delete service when runtime stops. runtime.Stop stops services; no need to double-stop * Track runtime services * Parse Unix timestamps properly * Added deployments into K8s client. Debug logging --- config/cmd/cmd.go | 28 ++ config/cmd/options.go | 10 + runtime/default.go | 251 ++++++--------- runtime/kubernetes/client/api/request.go | 223 ++++++++++++++ runtime/kubernetes/client/api/response.go | 94 ++++++ runtime/kubernetes/client/client.go | 102 ++++++ runtime/kubernetes/client/kubernetes.go | 12 + runtime/kubernetes/client/utils.go | 74 +++++ runtime/kubernetes/client/watch/body.go | 92 ++++++ runtime/kubernetes/client/watch/watch.go | 26 ++ runtime/kubernetes/client/watch/watch_test.go | 71 +++++ runtime/kubernetes/kubernetes.go | 290 ++++++++++++++++++ runtime/options.go | 18 +- runtime/runtime.go | 92 ++++-- runtime/service.go | 158 ++++++++++ 15 files changed, 1357 insertions(+), 184 deletions(-) create mode 100644 runtime/kubernetes/client/api/request.go create mode 100644 runtime/kubernetes/client/api/response.go create mode 100644 runtime/kubernetes/client/client.go create mode 100644 runtime/kubernetes/client/kubernetes.go create mode 100644 runtime/kubernetes/client/utils.go create mode 100644 runtime/kubernetes/client/watch/body.go create mode 100644 runtime/kubernetes/client/watch/watch.go create mode 100644 runtime/kubernetes/client/watch/watch_test.go create mode 100644 runtime/kubernetes/kubernetes.go create mode 100644 runtime/service.go diff --git a/config/cmd/cmd.go b/config/cmd/cmd.go index a99557d2..e66836c1 100644 --- a/config/cmd/cmd.go +++ b/config/cmd/cmd.go @@ -44,6 +44,10 @@ import ( thttp "github.com/micro/go-micro/transport/http" tmem "github.com/micro/go-micro/transport/memory" "github.com/micro/go-micro/transport/quic" + + // runtimes + "github.com/micro/go-micro/runtime" + "github.com/micro/go-micro/runtime/kubernetes" ) type Cmd interface { @@ -67,6 +71,12 @@ var ( DefaultCmd = newCmd() DefaultFlags = []cli.Flag{ + cli.StringFlag{ + Name: "runtime", + Usage: "Micro runtime", + EnvVar: "MICRO_RUNTIME", + Value: "local", + }, cli.StringFlag{ Name: "client", EnvVar: "MICRO_CLIENT", @@ -221,6 +231,11 @@ var ( "quic": quic.NewTransport, } + DefaultRuntimes = map[string]func(...runtime.Option) runtime.Runtime{ + "local": runtime.NewRuntime, + "kubernetes": kubernetes.NewRuntime, + } + // used for default selection as the fall back defaultClient = "rpc" defaultServer = "rpc" @@ -228,6 +243,7 @@ var ( defaultRegistry = "mdns" defaultSelector = "registry" defaultTransport = "http" + defaultRuntime = "local" ) func init() { @@ -247,6 +263,7 @@ func newCmd(opts ...Option) Cmd { Server: &server.DefaultServer, Selector: &selector.DefaultSelector, Transport: &transport.DefaultTransport, + Runtime: &runtime.DefaultRuntime, Brokers: DefaultBrokers, Clients: DefaultClients, @@ -254,6 +271,7 @@ func newCmd(opts ...Option) Cmd { Selectors: DefaultSelectors, Servers: DefaultServers, Transports: DefaultTransports, + Runtimes: DefaultRuntimes, } for _, o := range opts { @@ -294,6 +312,16 @@ func (c *cmd) Before(ctx *cli.Context) error { var serverOpts []server.Option var clientOpts []client.Option + // Set the runtime + if name := ctx.String("runtime"); len(name) > 0 { + r, ok := c.opts.Runtimes[name] + if !ok { + return fmt.Errorf("Unsupported runtime: %s", name) + } + + *c.opts.Runtime = r() + } + // Set the client if name := ctx.String("client"); len(name) > 0 { // only change if we have the client and type differs diff --git a/config/cmd/options.go b/config/cmd/options.go index 1f221f35..be831fe1 100644 --- a/config/cmd/options.go +++ b/config/cmd/options.go @@ -7,6 +7,7 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/client/selector" "github.com/micro/go-micro/registry" + "github.com/micro/go-micro/runtime" "github.com/micro/go-micro/server" "github.com/micro/go-micro/transport" ) @@ -24,6 +25,7 @@ type Options struct { Transport *transport.Transport Client *client.Client Server *server.Server + Runtime *runtime.Runtime Brokers map[string]func(...broker.Option) broker.Broker Clients map[string]func(...client.Option) client.Client @@ -31,6 +33,7 @@ type Options struct { Selectors map[string]func(...selector.Option) selector.Selector Servers map[string]func(...server.Option) server.Server Transports map[string]func(...transport.Option) transport.Transport + Runtimes map[string]func(...runtime.Option) runtime.Runtime // Other options for implementations of the interface // can be stored in a context @@ -135,3 +138,10 @@ func NewTransport(name string, t func(...transport.Option) transport.Transport) o.Transports[name] = t } } + +// New runtime func +func NewRuntime(name string, r func(...runtime.Option) runtime.Runtime) Option { + return func(o *Options) { + o.Runtimes[name] = r + } +} diff --git a/runtime/default.go b/runtime/default.go index 797ec107..1785c2f5 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -2,19 +2,18 @@ package runtime import ( "errors" - "io" - "strings" + "fmt" + "strconv" "sync" "time" - "github.com/micro/go-micro/runtime/package" - "github.com/micro/go-micro/runtime/process" - proc "github.com/micro/go-micro/runtime/process/os" "github.com/micro/go-micro/util/log" ) type runtime struct { sync.RWMutex + // options configure runtime + options Options // used to stop the runtime closed chan bool // used to start new services @@ -25,162 +24,38 @@ type runtime struct { services map[string]*service } -type service struct { - sync.RWMutex +// NewRuntime creates new local runtime and returns it +func NewRuntime(opts ...Option) Runtime { + // get default options + options := Options{} - running bool - closed chan bool - err error + // apply requested options + for _, o := range opts { + o(&options) + } - // output for logs - output io.Writer - - // service to manage - *Service - // process creator - Process *proc.Process - // Exec - Exec *process.Executable - // process pid - PID *process.PID -} - -func newRuntime() *runtime { return &runtime{ + options: options, closed: make(chan bool), start: make(chan *service, 128), services: make(map[string]*service), } } -func newService(s *Service, c CreateOptions) *service { - var exec string - var args []string +// Init initializes runtime options +func (r *runtime) Init(opts ...Option) error { + r.Lock() + defer r.Unlock() - if len(s.Exec) > 0 { - parts := strings.Split(s.Exec, " ") - exec = parts[0] - args = []string{} - - if len(parts) > 1 { - args = parts[1:] - } - } else { - // set command - exec = c.Command[0] - // set args - if len(c.Command) > 1 { - args = c.Command[1:] - } - } - - return &service{ - Service: s, - Process: new(proc.Process), - Exec: &process.Executable{ - Binary: &packager.Binary{ - Name: s.Name, - Path: exec, - }, - Env: c.Env, - Args: args, - }, - closed: make(chan bool), - output: c.Output, - } -} - -func (s *service) streamOutput() { - go io.Copy(s.output, s.PID.Output) - go io.Copy(s.output, s.PID.Error) -} - -func (s *service) Running() bool { - s.RLock() - defer s.RUnlock() - return s.running -} - -func (s *service) Start() error { - s.Lock() - defer s.Unlock() - - if s.running { - return nil - } - - // reset - s.err = nil - s.closed = make(chan bool) - - // TODO: pull source & build binary - log.Debugf("Runtime service %s forking new process\n", s.Service.Name) - p, err := s.Process.Fork(s.Exec) - if err != nil { - return err - } - - // set the pid - s.PID = p - // set to running - s.running = true - - if s.output != nil { - s.streamOutput() - } - - // wait and watch - go s.Wait() - - return nil -} - -func (s *service) Stop() error { - s.Lock() - defer s.Unlock() - - select { - case <-s.closed: - return nil - default: - close(s.closed) - s.running = false - if s.PID == nil { - return nil - } - return s.Process.Kill(s.PID) + for _, o := range opts { + o(&r.options) } return nil } -func (s *service) Error() error { - s.RLock() - defer s.RUnlock() - return s.err -} - -func (s *service) Wait() { - // wait for process to exit - err := s.Process.Wait(s.PID) - - s.Lock() - defer s.Unlock() - - // save the error - if err != nil { - s.err = err - } - - // no longer running - s.running = false -} - -func (r *runtime) run() { - r.RLock() - closed := r.closed - r.RUnlock() - +// run runs the runtime management loop +func (r *runtime) run(events <-chan Event) { t := time.NewTicker(time.Second * 5) defer t.Stop() @@ -205,19 +80,67 @@ func (r *runtime) run() { if service.Running() { continue } - // TODO: check service error - log.Debugf("Starting %s", service.Name) + log.Debugf("Runtime starting service %s", service.Name) if err := service.Start(); err != nil { - log.Debugf("Runtime error starting %s: %v", service.Name, err) + log.Debugf("Runtime error starting service %s: %v", service.Name, err) } - case <-closed: - // TODO: stop all the things + case event := <-events: + log.Debugf("Runtime received notification event: %v", event) + // NOTE: we only handle Update events for now + switch event.Type { + case Update: + // parse returned response to timestamp + updateTimeStamp, err := strconv.ParseInt(event.Version, 10, 64) + if err != nil { + log.Debugf("Runtime error parsing update build time: %v", err) + continue + } + buildTime := time.Unix(updateTimeStamp, 0) + processEvent := func(event Event, service *Service) error { + buildTimeStamp, err := strconv.ParseInt(service.Version, 10, 64) + if err != nil { + return err + } + muBuild := time.Unix(buildTimeStamp, 0) + if buildTime.After(muBuild) { + if err := r.Update(service); err != nil { + return err + } + service.Version = fmt.Sprintf("%d", buildTime.Unix()) + } + return nil + } + r.Lock() + if len(event.Service) > 0 { + service, ok := r.services[event.Service] + if !ok { + log.Debugf("Runtime unknown service: %s", event.Service) + r.Unlock() + continue + } + if err := processEvent(event, service.Service); err != nil { + log.Debugf("Runtime error updating service %s: %v", event.Service, err) + } + r.Unlock() + continue + } + // if blank service was received we update all services + for _, service := range r.services { + if err := processEvent(event, service.Service); err != nil { + log.Debugf("Runtime error updating service %s: %v", service.Name, err) + } + } + r.Unlock() + } + case <-r.closed: + log.Debugf("Runtime stopped.") return } } } +// Create creates a new service which is then started by runtime func (r *runtime) Create(s *Service, opts ...CreateOption) error { r.Lock() defer r.Unlock() @@ -244,6 +167,7 @@ func (r *runtime) Create(s *Service, opts ...CreateOption) error { return nil } +// Delete removes the service from the runtime and stops it func (r *runtime) Delete(s *Service) error { r.Lock() defer r.Unlock() @@ -256,6 +180,7 @@ func (r *runtime) Delete(s *Service) error { return nil } +// Update attemps to update the service func (r *runtime) Update(s *Service) error { // delete the service if err := r.Delete(s); err != nil { @@ -266,6 +191,7 @@ func (r *runtime) Update(s *Service) error { return r.Create(s) } +// List returns a slice of all services tracked by the runtime func (r *runtime) List() ([]*Service, error) { var services []*Service r.RLock() @@ -278,6 +204,7 @@ func (r *runtime) List() ([]*Service, error) { return services, nil } +// Start starts the runtime func (r *runtime) Start() error { r.Lock() defer r.Unlock() @@ -291,11 +218,22 @@ func (r *runtime) Start() error { r.running = true r.closed = make(chan bool) - go r.run() + var events <-chan Event + if r.options.Notifier != nil { + var err error + events, err = r.options.Notifier.Notify() + if err != nil { + // TODO: should we bail here? + log.Debugf("Runtime failed to start update notifier") + } + } + + go r.run(events) return nil } +// Stop stops the runtime func (r *runtime) Stop() error { r.Lock() defer r.Unlock() @@ -318,7 +256,16 @@ func (r *runtime) Stop() error { log.Debugf("Runtime stopping %s", service.Name) service.Stop() } + // stop the notifier too + if r.options.Notifier != nil { + return r.options.Notifier.Close() + } } return nil } + +// String implements stringer interface +func (r *runtime) String() string { + return "local" +} diff --git a/runtime/kubernetes/client/api/request.go b/runtime/kubernetes/client/api/request.go new file mode 100644 index 00000000..b40ed72a --- /dev/null +++ b/runtime/kubernetes/client/api/request.go @@ -0,0 +1,223 @@ +package api + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + + "github.com/micro/go-micro/runtime/kubernetes/client/watch" + "github.com/micro/go-micro/util/log" +) + +// Request is used to construct a http request for the k8s API. +type Request struct { + client *http.Client + header http.Header + params url.Values + method string + host string + namespace string + + resource string + resourceName *string + body io.Reader + + err error +} + +// Params is the object to pass in to set paramaters +// on a request. +type Params struct { + LabelSelector map[string]string + Annotations map[string]string + Watch bool +} + +// verb sets method +func (r *Request) verb(method string) *Request { + r.method = method + return r +} + +// Get request +func (r *Request) Get() *Request { + return r.verb("GET") +} + +// Post request +func (r *Request) Post() *Request { + return r.verb("POST") +} + +// Put request +func (r *Request) Put() *Request { + return r.verb("PUT") +} + +// Patch request +// https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md#patch-operations +func (r *Request) Patch() *Request { + return r.verb("PATCH").SetHeader("Content-Type", "application/strategic-merge-patch+json") +} + +// Delete request +func (r *Request) Delete() *Request { + return r.verb("DELETE") +} + +// Namespace is to set the namespace to operate on +func (r *Request) Namespace(s string) *Request { + r.namespace = s + return r +} + +// Resource is the type of resource the operation is +// for, such as "services", "endpoints" or "pods" +func (r *Request) Resource(s string) *Request { + r.resource = s + return r +} + +// Name is for targeting a specific resource by id +func (r *Request) Name(s string) *Request { + r.resourceName = &s + return r +} + +// Body pass in a body to set, this is for POST, PUT +// and PATCH requests +func (r *Request) Body(in interface{}) *Request { + b := new(bytes.Buffer) + if err := json.NewEncoder(b).Encode(&in); err != nil { + r.err = err + return r + } + log.Debugf("Patch body: %v", b) + r.body = b + return r +} + +// Params isused to set paramters on a request +func (r *Request) Params(p *Params) *Request { + for k, v := range p.LabelSelector { + r.params.Add("labelSelectors", k+"="+v) + } + + return r +} + +// SetHeader sets a header on a request with +// a `key` and `value` +func (r *Request) SetHeader(key, value string) *Request { + r.header.Add(key, value) + return r +} + +// request builds the http.Request from the options +func (r *Request) request() (*http.Request, error) { + var url string + switch r.resource { + case "pods": + // /api/v1/namespaces/{namespace}/pods + url = fmt.Sprintf("%s/api/v1/namespaces/%s/%s/", r.host, r.namespace, r.resource) + case "deployments": + // /apis/apps/v1/namespaces/{namespace}/deployments/{name} + url = fmt.Sprintf("%s/apis/apps/v1/namespaces/%s/%s/", r.host, r.namespace, r.resource) + } + + // append resourceName if it is present + if r.resourceName != nil { + url += *r.resourceName + } + + // append any query params + if len(r.params) > 0 { + url += "?" + r.params.Encode() + } + + // build request + req, err := http.NewRequest(r.method, url, r.body) + if err != nil { + return nil, err + } + + // set headers on request + req.Header = r.header + return req, nil +} + +// Do builds and triggers the request +func (r *Request) Do() *Response { + if r.err != nil { + return &Response{ + err: r.err, + } + } + + req, err := r.request() + if err != nil { + return &Response{ + err: err, + } + } + + log.Debugf("kubernetes api request: %v", req) + + res, err := r.client.Do(req) + if err != nil { + return &Response{ + err: err, + } + } + + log.Debugf("kubernetes api response: %v", res) + + // return res, err + return newResponse(res, err) +} + +// Watch builds and triggers the request, but +// will watch instead of return an object +func (r *Request) Watch() (watch.Watch, error) { + if r.err != nil { + return nil, r.err + } + + r.params.Set("watch", "true") + + req, err := r.request() + if err != nil { + return nil, err + } + + w, err := watch.NewBodyWatcher(req, r.client) + return w, err +} + +// Options ... +type Options struct { + Host string + Namespace string + BearerToken *string + Client *http.Client +} + +// NewRequest creates a k8s api request +func NewRequest(opts *Options) *Request { + req := &Request{ + header: make(http.Header), + params: make(url.Values), + client: opts.Client, + namespace: opts.Namespace, + host: opts.Host, + } + + if opts.BearerToken != nil { + req.SetHeader("Authorization", "Bearer "+*opts.BearerToken) + } + + return req +} diff --git a/runtime/kubernetes/client/api/response.go b/runtime/kubernetes/client/api/response.go new file mode 100644 index 00000000..8700115f --- /dev/null +++ b/runtime/kubernetes/client/api/response.go @@ -0,0 +1,94 @@ +package api + +import ( + "encoding/json" + "errors" + "io/ioutil" + "net/http" + + "github.com/micro/go-micro/util/log" +) + +// Errors ... +var ( + ErrNotFound = errors.New("kubernetes: not found") + ErrDecode = errors.New("kubernetes: error decoding") + ErrOther = errors.New("kubernetes: unknown error") +) + +// Status is an object that is returned when a request +// failed or delete succeeded. +// type Status struct { +// Kind string `json:"kind"` +// Status string `json:"status"` +// Message string `json:"message"` +// Reason string `json:"reason"` +// Code int `json:"code"` +// } + +// Response ... +type Response struct { + res *http.Response + err error + + body []byte +} + +// Error returns an error +func (r *Response) Error() error { + return r.err +} + +// StatusCode returns status code for response +func (r *Response) StatusCode() int { + return r.res.StatusCode +} + +// Into decode body into `data` +func (r *Response) Into(data interface{}) error { + if r.err != nil { + return r.err + } + + defer r.res.Body.Close() + decoder := json.NewDecoder(r.res.Body) + err := decoder.Decode(&data) + if err != nil { + return ErrDecode + } + + return r.err +} + +func newResponse(res *http.Response, err error) *Response { + r := &Response{ + res: res, + err: err, + } + + if err != nil { + return r + } + + if r.res.StatusCode == http.StatusOK || + r.res.StatusCode == http.StatusCreated || + r.res.StatusCode == http.StatusNoContent { + // Non error status code + return r + } + + if r.res.StatusCode == http.StatusNotFound { + r.err = ErrNotFound + return r + } + + log.Logf("kubernetes: request failed with code %v", r.res.StatusCode) + + b, err := ioutil.ReadAll(r.res.Body) + if err == nil { + log.Log("kubernetes: request failed with body:") + log.Log(string(b)) + } + r.err = ErrOther + return r +} diff --git a/runtime/kubernetes/client/client.go b/runtime/kubernetes/client/client.go new file mode 100644 index 00000000..695ecd65 --- /dev/null +++ b/runtime/kubernetes/client/client.go @@ -0,0 +1,102 @@ +package client + +import ( + "crypto/tls" + "errors" + "io/ioutil" + "net/http" + "os" + "path" + + "github.com/micro/go-micro/runtime/kubernetes/client/api" + "github.com/micro/go-micro/util/log" +) + +var ( + serviceAccountPath = "/var/run/secrets/kubernetes.io/serviceaccount" + // ErrReadNamespace is returned when the names could not be read from service account + ErrReadNamespace = errors.New("Could not read namespace from service account secret") +) + +// Client ... +type client struct { + opts *api.Options +} + +// NewClientInCluster should work similarily to the official api +// NewInClient by setting up a client configuration for use within +// a k8s pod. +func NewClientInCluster() *client { + host := "https://" + os.Getenv("KUBERNETES_SERVICE_HOST") + ":" + os.Getenv("KUBERNETES_SERVICE_PORT") + + s, err := os.Stat(serviceAccountPath) + if err != nil { + log.Fatal(err) + } + if s == nil || !s.IsDir() { + log.Fatal(errors.New("no k8s service account found")) + } + + token, err := ioutil.ReadFile(path.Join(serviceAccountPath, "token")) + if err != nil { + log.Fatal(err) + } + t := string(token) + + ns, err := detectNamespace() + if err != nil { + log.Fatal(err) + } + + crt, err := CertPoolFromFile(path.Join(serviceAccountPath, "ca.crt")) + if err != nil { + log.Fatal(err) + } + + c := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: crt, + }, + DisableCompression: true, + }, + } + + return &client{ + opts: &api.Options{ + Client: c, + Host: host, + Namespace: ns, + BearerToken: &t, + }, + } +} + +func detectNamespace() (string, error) { + nsPath := path.Join(serviceAccountPath, "namespace") + + // Make sure it's a file and we can read it + if s, e := os.Stat(nsPath); e != nil { + return "", e + } else if s.IsDir() { + return "", ErrReadNamespace + } + + // Read the file, and cast to a string + if ns, e := ioutil.ReadFile(nsPath); e != nil { + return string(ns), e + } else { + return string(ns), nil + } +} + +// UpdateDeployment +func (c *client) UpdateDeployment(name string, body interface{}) error { + return api.NewRequest(c.opts). + Patch(). + Resource("deployments"). + Name(name). + Body(body). + Do(). + Error() +} diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go new file mode 100644 index 00000000..565d2243 --- /dev/null +++ b/runtime/kubernetes/client/kubernetes.go @@ -0,0 +1,12 @@ +package client + +// Kubernetes client +type Kubernetes interface { + // UpdateDeployment patches deployment annotations with new metadata + UpdateDeployment(string, interface{}) error +} + +// Metadata defines api request metadata +type Metadata struct { + Annotations map[string]string `json:"annotations,omitempty"` +} diff --git a/runtime/kubernetes/client/utils.go b/runtime/kubernetes/client/utils.go new file mode 100644 index 00000000..ec250aca --- /dev/null +++ b/runtime/kubernetes/client/utils.go @@ -0,0 +1,74 @@ +package client + +import ( + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "io/ioutil" +) + +// COPIED FROM +// https://github.com/kubernetes/kubernetes/blob/7a725418af4661067b56506faabc2d44c6d7703a/pkg/util/crypto/crypto.go + +// CertPoolFromFile returns an x509.CertPool containing the certificates in the given PEM-encoded file. +// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates +func CertPoolFromFile(filename string) (*x509.CertPool, error) { + certs, err := certificatesFromFile(filename) + if err != nil { + return nil, err + } + pool := x509.NewCertPool() + for _, cert := range certs { + pool.AddCert(cert) + } + return pool, nil +} + +// certificatesFromFile returns the x509.Certificates contained in the given PEM-encoded file. +// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates +func certificatesFromFile(file string) ([]*x509.Certificate, error) { + if len(file) == 0 { + return nil, errors.New("error reading certificates from an empty filename") + } + pemBlock, err := ioutil.ReadFile(file) + if err != nil { + return nil, err + } + certs, err := CertsFromPEM(pemBlock) + if err != nil { + return nil, fmt.Errorf("error reading %s: %s", file, err) + } + return certs, nil +} + +// CertsFromPEM returns the x509.Certificates contained in the given PEM-encoded byte array +// Returns an error if a certificate could not be parsed, or if the data does not contain any certificates +func CertsFromPEM(pemCerts []byte) ([]*x509.Certificate, error) { + ok := false + certs := []*x509.Certificate{} + for len(pemCerts) > 0 { + var block *pem.Block + block, pemCerts = pem.Decode(pemCerts) + if block == nil { + break + } + // Only use PEM "CERTIFICATE" blocks without extra headers + if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { + continue + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return certs, err + } + + certs = append(certs, cert) + ok = true + } + + if !ok { + return certs, errors.New("could not read any certificates") + } + return certs, nil +} diff --git a/runtime/kubernetes/client/watch/body.go b/runtime/kubernetes/client/watch/body.go new file mode 100644 index 00000000..5f939655 --- /dev/null +++ b/runtime/kubernetes/client/watch/body.go @@ -0,0 +1,92 @@ +package watch + +import ( + "bufio" + "encoding/json" + "net/http" + "time" +) + +// bodyWatcher scans the body of a request for chunks +type bodyWatcher struct { + results chan Event + stop chan struct{} + res *http.Response + req *http.Request +} + +// Changes returns the results channel +func (wr *bodyWatcher) ResultChan() <-chan Event { + return wr.results +} + +// Stop cancels the request +func (wr *bodyWatcher) Stop() { + select { + case <-wr.stop: + return + default: + close(wr.stop) + close(wr.results) + } +} + +func (wr *bodyWatcher) stream() { + reader := bufio.NewReader(wr.res.Body) + + // ignore first few messages from stream, + // as they are usually old. + ignore := true + + go func() { + <-time.After(time.Second) + ignore = false + }() + + go func() { + // stop the watcher + defer wr.Stop() + + for { + // read a line + b, err := reader.ReadBytes('\n') + if err != nil { + return + } + + // ignore for the first second + if ignore { + continue + } + + // send the event + var event Event + if err := json.Unmarshal(b, &event); err != nil { + continue + } + wr.results <- event + } + }() +} + +// NewBodyWatcher creates a k8s body watcher for +// a given http request +func NewBodyWatcher(req *http.Request, client *http.Client) (Watch, error) { + stop := make(chan struct{}) + req.Cancel = stop + + res, err := client.Do(req) + if err != nil { + return nil, err + } + + wr := &bodyWatcher{ + results: make(chan Event), + stop: stop, + req: req, + res: res, + } + + go wr.stream() + return wr, nil +} diff --git a/runtime/kubernetes/client/watch/watch.go b/runtime/kubernetes/client/watch/watch.go new file mode 100644 index 00000000..f8a178b8 --- /dev/null +++ b/runtime/kubernetes/client/watch/watch.go @@ -0,0 +1,26 @@ +package watch + +import "encoding/json" + +// Watch ... +type Watch interface { + Stop() + ResultChan() <-chan Event +} + +// EventType defines the possible types of events. +type EventType string + +// EventTypes used +const ( + Added EventType = "ADDED" + Modified EventType = "MODIFIED" + Deleted EventType = "DELETED" + Error EventType = "ERROR" +) + +// Event represents a single event to a watched resource. +type Event struct { + Type EventType `json:"type"` + Object json.RawMessage `json:"object"` +} diff --git a/runtime/kubernetes/client/watch/watch_test.go b/runtime/kubernetes/client/watch/watch_test.go new file mode 100644 index 00000000..d34918c4 --- /dev/null +++ b/runtime/kubernetes/client/watch/watch_test.go @@ -0,0 +1,71 @@ +package watch + +import ( + "fmt" + "net/http" + "net/http/httptest" + "testing" + "time" +) + +var actions = []string{ + `{"type": "create", "object":{"foo": "bar"}}`, + `{"type": "delete", INVALID}`, + `{"type": "update", "object":{"foo": {"foo": "bar"}}}`, + `{"type": "delete", "object":null}`, +} + +func TestBodyWatcher(t *testing.T) { + // set up server with handler to flush strings from ch. + ch := make(chan string) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + flusher, ok := w.(http.Flusher) + if !ok { + t.Fatal("expected ResponseWriter to be a flusher") + } + + fmt.Fprintf(w, "\n") + flusher.Flush() + + for v := range ch { + fmt.Fprintf(w, "%s\n", v) + flusher.Flush() + time.Sleep(10 * time.Millisecond) + } + })) + defer ts.Close() + + req, err := http.NewRequest("GET", ts.URL, nil) + if err != nil { + t.Fatalf("did not expect NewRequest to return err: %v", err) + } + + // setup body watcher + w, err := NewBodyWatcher(req, http.DefaultClient) + if err != nil { + t.Fatalf("did not expect NewBodyWatcher to return %v", err) + } + + <-time.After(time.Second) + + // send action strings in, and expect result back + ch <- actions[0] + if r := <-w.ResultChan(); r.Type != "create" { + t.Fatalf("expected result to be create") + } + + ch <- actions[1] // should be ignored as its invalid json + ch <- actions[2] + if r := <-w.ResultChan(); r.Type != "update" { + t.Fatalf("expected result to be update") + } + + ch <- actions[3] + if r := <-w.ResultChan(); r.Type != "delete" { + t.Fatalf("expected result to be delete") + } + + // stop should clean up all channels. + w.Stop() + close(ch) +} diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go new file mode 100644 index 00000000..49666f37 --- /dev/null +++ b/runtime/kubernetes/kubernetes.go @@ -0,0 +1,290 @@ +// Package kubernetes implements kubernetes micro runtime +package kubernetes + +import ( + "errors" + "fmt" + "strconv" + "strings" + "sync" + "time" + + "github.com/micro/go-micro/runtime" + "github.com/micro/go-micro/runtime/kubernetes/client" + "github.com/micro/go-micro/util/log" +) + +type kubernetes struct { + sync.RWMutex + // options configure runtime + options runtime.Options + // indicates if we're running + running bool + // used to start new services + start chan *runtime.Service + // used to stop the runtime + closed chan bool + // service tracks deployed services + services map[string]*runtime.Service + // client is kubernetes client + client client.Kubernetes +} + +// NewRuntime creates new kubernetes runtime +func NewRuntime(opts ...runtime.Option) runtime.Runtime { + // get default options + options := runtime.Options{} + + // apply requested options + for _, o := range opts { + o(&options) + } + + // kubernetes client + client := client.NewClientInCluster() + + return &kubernetes{ + options: options, + closed: make(chan bool), + start: make(chan *runtime.Service, 128), + services: make(map[string]*runtime.Service), + client: client, + } +} + +// Init initializes runtime options +func (k *kubernetes) Init(opts ...runtime.Option) error { + k.Lock() + defer k.Unlock() + + for _, o := range opts { + o(&k.options) + } + + return nil +} + +// Registers a service +func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) error { + k.Lock() + defer k.Unlock() + + // TODO: + // * create service + // * create deployment + + // NOTE: our services have micro- prefix + muName := strings.Split(s.Name, ".") + s.Name = "micro-" + muName[len(muName)-1] + + // NOTE: we are tracking this in memory for now + if _, ok := k.services[s.Name]; ok { + return errors.New("service already registered") + } + + var options runtime.CreateOptions + for _, o := range opts { + o(&options) + } + + // save service + k.services[s.Name] = s + // push into start queue + k.start <- k.services[s.Name] + + return nil +} + +// Remove a service +func (k *kubernetes) Delete(s *runtime.Service) error { + k.Lock() + defer k.Unlock() + + // TODO: + // * delete service + // * delete dpeloyment + + // NOTE: we are tracking this in memory for now + if s, ok := k.services[s.Name]; ok { + delete(k.services, s.Name) + return nil + } + + return nil +} + +// Update the service in place +func (k *kubernetes) Update(s *runtime.Service) error { + type body struct { + Metadata *client.Metadata `json:"metadata"` + } + // parse version into human readable timestamp + updateTimeStamp, err := strconv.ParseInt(s.Version, 10, 64) + if err != nil { + return err + } + unixTimeUTC := time.Unix(updateTimeStamp, 0) + // metada which we will PATCH deployment with + reqBody := body{ + Metadata: &client.Metadata{ + Annotations: map[string]string{ + "build": unixTimeUTC.Format(time.RFC3339), + }, + }, + } + return k.client.UpdateDeployment(s.Name, reqBody) +} + +// List the managed services +func (k *kubernetes) List() ([]*runtime.Service, error) { + // TODO: this should list the k8s deployments + // but for now we return in-memory tracked services + var services []*runtime.Service + k.RLock() + defer k.RUnlock() + + for _, service := range k.services { + services = append(services, service) + } + + return services, nil +} + +// run runs the runtime management loop +func (k *kubernetes) run(events <-chan runtime.Event) { + t := time.NewTicker(time.Second * 5) + defer t.Stop() + + for { + select { + case <-t.C: + // TODO: noop for now + // check running services + // * deployments exist + // * service is exposed + case service := <-k.start: + // TODO: following might have to be done + // * create a deployment + // * expose a service + log.Debugf("Runtime starting service: %s", service.Name) + case event := <-events: + // NOTE: we only handle Update events for now + log.Debugf("Runtime received notification event: %v", event) + switch event.Type { + case runtime.Update: + // parse returned response to timestamp + updateTimeStamp, err := strconv.ParseInt(event.Version, 10, 64) + if err != nil { + log.Debugf("Runtime error parsing update build time: %v", err) + continue + } + buildTime := time.Unix(updateTimeStamp, 0) + processEvent := func(event runtime.Event, service *runtime.Service) error { + buildTimeStamp, err := strconv.ParseInt(service.Version, 10, 64) + if err != nil { + return err + } + muBuild := time.Unix(buildTimeStamp, 0) + if buildTime.After(muBuild) { + version := fmt.Sprintf("%d", buildTime.Unix()) + muService := &runtime.Service{ + Name: service.Name, + Source: service.Source, + Path: service.Path, + Exec: service.Exec, + Version: version, + } + if err := k.Update(muService); err != nil { + return err + } + service.Version = version + } + return nil + } + k.Lock() + if len(event.Service) > 0 { + service, ok := k.services[event.Service] + if !ok { + log.Debugf("Runtime unknown service: %s", event.Service) + k.Unlock() + continue + } + if err := processEvent(event, service); err != nil { + log.Debugf("Runtime error updating service %s: %v", event.Service, err) + } + k.Unlock() + continue + } + // if blank service was received we update all services + for _, service := range k.services { + if err := processEvent(event, service); err != nil { + log.Debugf("Runtime error updating service %s: %v", service.Name, err) + } + } + k.Unlock() + } + case <-k.closed: + log.Debugf("Runtime stopped") + return + } + } +} + +// starts the runtime +func (k *kubernetes) Start() error { + k.Lock() + defer k.Unlock() + + // already running + if k.running { + return nil + } + + // set running + k.running = true + k.closed = make(chan bool) + + var events <-chan runtime.Event + if k.options.Notifier != nil { + var err error + events, err = k.options.Notifier.Notify() + if err != nil { + // TODO: should we bail here? + log.Debugf("Runtime failed to start update notifier") + } + } + + go k.run(events) + + return nil +} + +// Shutdown the runtime +func (k *kubernetes) Stop() error { + k.Lock() + defer k.Unlock() + + if !k.running { + return nil + } + + select { + case <-k.closed: + return nil + default: + close(k.closed) + // set not running + k.running = false + // stop the notifier too + if k.options.Notifier != nil { + return k.options.Notifier.Close() + } + } + + return nil +} + +// String implements stringer interface +func (k *kubernetes) String() string { + return "kubernetes" +} diff --git a/runtime/options.go b/runtime/options.go index 64221c9e..82284b36 100644 --- a/runtime/options.go +++ b/runtime/options.go @@ -4,8 +4,24 @@ import ( "io" ) +type Option func(o *Options) + +// Options configure runtime +type Options struct { + // Notifier for updates + Notifier Notifier +} + +// AutoUpdate enables micro auto-updates +func WithNotifier(n Notifier) Option { + return func(o *Options) { + o.Notifier = n + } +} + type CreateOption func(o *CreateOptions) +// CreateOptions configure runtime services type CreateOptions struct { // command to execute including args Command []string @@ -25,7 +41,7 @@ func WithCommand(c string, args ...string) CreateOption { } } -// WithEnv sets the created service env +// WithEnv sets the created service environment func WithEnv(env []string) CreateOption { return func(o *CreateOptions) { o.Env = env diff --git a/runtime/runtime.go b/runtime/runtime.go index 0cb84802..ca5762bb 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -1,8 +1,17 @@ // Package runtime is a service runtime manager package runtime +import "time" + +var ( + // DefaultRuntime is default micro runtime + DefaultRuntime Runtime = NewRuntime() +) + // Runtime is a service runtime manager type Runtime interface { + // Init initializes runtime + Init(...Option) error // Registers a service Create(*Service, ...CreateOption) error // Remove a service @@ -17,41 +26,62 @@ type Runtime interface { Stop() error } +// Notifier is an update notifier +type Notifier interface { + // Notify publishes notification events + Notify() (<-chan Event, error) + // Close stops the notifier + Close() error +} + +// EventType defines notification event +type EventType int + +const ( + // Create is emitted when a new build has been craeted + Create EventType = iota + // Update is emitted when a new update become available + Update + // Delete is emitted when a build has been deleted + Delete +) + +// String returns human readable event type +func (t EventType) String() string { + switch t { + case Create: + return "create" + case Delete: + return "delete" + case Update: + return "update" + default: + return "unknown" + } +} + +// Event is notification event +type Event struct { + // Type is event type + Type EventType + // Timestamp is event timestamp + Timestamp time.Time + // Service is the name of the service + Service string + // Version of the build + Version string +} + +// Service is runtime service type Service struct { - // name of the service + // Name of the service Name string // url location of source Source string - // path to store source + // Path to store source Path string - // exec command + // Exec command Exec string -} - -var ( - DefaultRuntime = newRuntime() -) - -func Create(s *Service, opts ...CreateOption) error { - return DefaultRuntime.Create(s, opts...) -} - -func Delete(s *Service) error { - return DefaultRuntime.Delete(s) -} - -func Update(s *Service) error { - return DefaultRuntime.Update(s) -} - -func List() ([]*Service, error) { - return DefaultRuntime.List() -} - -func Start() error { - return DefaultRuntime.Start() -} - -func Stop() error { - return DefaultRuntime.Stop() + // Version of the service + Version string } diff --git a/runtime/service.go b/runtime/service.go new file mode 100644 index 00000000..cb0d3bb9 --- /dev/null +++ b/runtime/service.go @@ -0,0 +1,158 @@ +package runtime + +import ( + "io" + "strings" + "sync" + + packager "github.com/micro/go-micro/runtime/package" + "github.com/micro/go-micro/runtime/process" + proc "github.com/micro/go-micro/runtime/process/os" + "github.com/micro/go-micro/util/log" +) + +type service struct { + sync.RWMutex + + running bool + closed chan bool + err error + + // output for logs + output io.Writer + + // service to manage + *Service + // process creator + Process *proc.Process + // Exec + Exec *process.Executable + // process pid + PID *process.PID +} + +func newService(s *Service, c CreateOptions) *service { + var exec string + var args []string + + if len(s.Exec) > 0 { + parts := strings.Split(s.Exec, " ") + exec = parts[0] + args = []string{} + + if len(parts) > 1 { + args = parts[1:] + } + } else { + // set command + exec = c.Command[0] + // set args + if len(c.Command) > 1 { + args = c.Command[1:] + } + } + + return &service{ + Service: s, + Process: new(proc.Process), + Exec: &process.Executable{ + Binary: &packager.Binary{ + Name: s.Name, + Path: exec, + }, + Env: c.Env, + Args: args, + }, + closed: make(chan bool), + output: c.Output, + } +} + +func (s *service) streamOutput() { + go io.Copy(s.output, s.PID.Output) + go io.Copy(s.output, s.PID.Error) +} + +// Running returns true is the service is running +func (s *service) Running() bool { + s.RLock() + defer s.RUnlock() + return s.running +} + +// Start stars the service +func (s *service) Start() error { + s.Lock() + defer s.Unlock() + + if s.running { + return nil + } + + // reset + s.err = nil + s.closed = make(chan bool) + + // TODO: pull source & build binary + log.Debugf("Runtime service %s forking new process", s.Service.Name) + p, err := s.Process.Fork(s.Exec) + if err != nil { + return err + } + + // set the pid + s.PID = p + // set to running + s.running = true + + if s.output != nil { + s.streamOutput() + } + + // wait and watch + go s.Wait() + + return nil +} + +// Stop stops the service +func (s *service) Stop() error { + s.Lock() + defer s.Unlock() + + select { + case <-s.closed: + return nil + default: + close(s.closed) + s.running = false + if s.PID == nil { + return nil + } + return s.Process.Kill(s.PID) + } +} + +// Error returns the last error service has returned +func (s *service) Error() error { + s.RLock() + defer s.RUnlock() + return s.err +} + +// Wait waits for the service to finish running +func (s *service) Wait() { + // wait for process to exit + err := s.Process.Wait(s.PID) + + s.Lock() + defer s.Unlock() + + // save the error + if err != nil { + s.err = err + } + + // no longer running + s.running = false +} From 292da408861df29017198ae8e6ae69a21d837180 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 2 Nov 2019 22:54:35 +0000 Subject: [PATCH 168/344] runtime handler/proto placeholder --- runtime/service/handler/handler.go | 91 ++++ runtime/service/proto/runtime.micro.go | 142 ++++++ runtime/service/proto/runtime.pb.go | 661 +++++++++++++++++++++++++ runtime/service/proto/runtime.proto | 57 +++ 4 files changed, 951 insertions(+) create mode 100644 runtime/service/handler/handler.go create mode 100644 runtime/service/proto/runtime.micro.go create mode 100644 runtime/service/proto/runtime.pb.go create mode 100644 runtime/service/proto/runtime.proto diff --git a/runtime/service/handler/handler.go b/runtime/service/handler/handler.go new file mode 100644 index 00000000..8f9abc38 --- /dev/null +++ b/runtime/service/handler/handler.go @@ -0,0 +1,91 @@ +package handler + +import ( + "context" + + "github.com/micro/go-micro/errors" + "github.com/micro/go-micro/runtime" + pb "github.com/micro/go-micro/runtime/service/proto" +) + +type Runtime struct { + Runtime runtime.Runtime +} + +func toProto(s *runtime.Service) *pb.Service { + return &pb.Service{ + Name: s.Name, + Version: s.Version, + Source: s.Source, + Path: s.Path, + Exec: s.Exec, + } +} + +func toService(s *pb.Service) *runtime.Service { + return &runtime.Service{ + Name: s.Name, + Version: s.Version, + Source: s.Source, + Path: s.Path, + Exec: s.Exec, + } +} + +func (r *Runtime) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error { + if req.Service == nil { + return errors.BadRequest("go.micro.runtime", "blank service") + } + + // TODO: add opts + service := toService(req.Service) + err := r.Runtime.Create(service) + if err != nil { + return errors.InternalServerError("go.micro.runtime", err.Error()) + } + + return nil +} + +func (r *Runtime) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error { + if req.Service == nil { + return errors.BadRequest("go.micro.runtime", "blank service") + } + + // TODO: add opts + service := toService(req.Service) + err := r.Runtime.Update(service) + if err != nil { + return errors.InternalServerError("go.micro.runtime", err.Error()) + } + + return nil +} + +func (r *Runtime) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.DeleteResponse) error { + if req.Service == nil { + return errors.BadRequest("go.micro.runtime", "blank service") + } + + // TODO: add opts + service := toService(req.Service) + err := r.Runtime.Delete(service) + if err != nil { + return errors.InternalServerError("go.micro.runtime", err.Error()) + } + + return nil +} + +func (r *Runtime) List(ctx context.Context, req *pb.ListRequest, rsp *pb.ListResponse) error { + services, err := r.Runtime.List() + if err != nil { + return errors.InternalServerError("go.micro.runtime", err.Error()) + } + + for _, service := range services { + rsp.Services = append(rsp.Services, toProto(service)) + } + + return nil +} diff --git a/runtime/service/proto/runtime.micro.go b/runtime/service/proto/runtime.micro.go new file mode 100644 index 00000000..86c00c21 --- /dev/null +++ b/runtime/service/proto/runtime.micro.go @@ -0,0 +1,142 @@ +// Code generated by protoc-gen-micro. DO NOT EDIT. +// source: micro/go-micro/runtime/service/proto/runtime.proto + +package go_micro_runtime + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +import ( + context "context" + client "github.com/micro/go-micro/client" + server "github.com/micro/go-micro/server" +) + +// 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.ProtoPackageIsVersion3 // please upgrade the proto package + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ client.Option +var _ server.Option + +// Client API for Runtime service + +type RuntimeService interface { + Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) + Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) + Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) + List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) +} + +type runtimeService struct { + c client.Client + name string +} + +func NewRuntimeService(name string, c client.Client) RuntimeService { + if c == nil { + c = client.NewClient() + } + if len(name) == 0 { + name = "go.micro.runtime" + } + return &runtimeService{ + c: c, + name: name, + } +} + +func (c *runtimeService) Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) { + req := c.c.NewRequest(c.name, "Runtime.Create", in) + out := new(CreateResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) { + req := c.c.NewRequest(c.name, "Runtime.Delete", in) + out := new(DeleteResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeService) Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) { + req := c.c.NewRequest(c.name, "Runtime.Update", in) + out := new(UpdateResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeService) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) { + req := c.c.NewRequest(c.name, "Runtime.List", in) + out := new(ListResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Runtime service + +type RuntimeHandler interface { + Create(context.Context, *CreateRequest, *CreateResponse) error + Delete(context.Context, *DeleteRequest, *DeleteResponse) error + Update(context.Context, *UpdateRequest, *UpdateResponse) error + List(context.Context, *ListRequest, *ListResponse) error +} + +func RegisterRuntimeHandler(s server.Server, hdlr RuntimeHandler, opts ...server.HandlerOption) error { + type runtime interface { + Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error + Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error + Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error + List(ctx context.Context, in *ListRequest, out *ListResponse) error + } + type Runtime struct { + runtime + } + h := &runtimeHandler{hdlr} + return s.Handle(s.NewHandler(&Runtime{h}, opts...)) +} + +type runtimeHandler struct { + RuntimeHandler +} + +func (h *runtimeHandler) Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error { + return h.RuntimeHandler.Create(ctx, in, out) +} + +func (h *runtimeHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error { + return h.RuntimeHandler.Delete(ctx, in, out) +} + +func (h *runtimeHandler) Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error { + return h.RuntimeHandler.Update(ctx, in, out) +} + +func (h *runtimeHandler) List(ctx context.Context, in *ListRequest, out *ListResponse) error { + return h.RuntimeHandler.List(ctx, in, out) +} diff --git a/runtime/service/proto/runtime.pb.go b/runtime/service/proto/runtime.pb.go new file mode 100644 index 00000000..2ff2cae8 --- /dev/null +++ b/runtime/service/proto/runtime.pb.go @@ -0,0 +1,661 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: micro/go-micro/runtime/service/proto/runtime.proto + +package go_micro_runtime + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + 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.ProtoPackageIsVersion3 // please upgrade the proto package + +type Service struct { + // name of the service + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // version of the service + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + // git url of the source + Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` + // local path of the source + Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` + // command to execute + Exec string `protobuf:"bytes,5,opt,name=exec,proto3" json:"exec,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Service) Reset() { *m = Service{} } +func (m *Service) String() string { return proto.CompactTextString(m) } +func (*Service) ProtoMessage() {} +func (*Service) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{0} +} + +func (m *Service) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Service.Unmarshal(m, b) +} +func (m *Service) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Service.Marshal(b, m, deterministic) +} +func (m *Service) XXX_Merge(src proto.Message) { + xxx_messageInfo_Service.Merge(m, src) +} +func (m *Service) XXX_Size() int { + return xxx_messageInfo_Service.Size(m) +} +func (m *Service) XXX_DiscardUnknown() { + xxx_messageInfo_Service.DiscardUnknown(m) +} + +var xxx_messageInfo_Service proto.InternalMessageInfo + +func (m *Service) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Service) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + +func (m *Service) GetSource() string { + if m != nil { + return m.Source + } + return "" +} + +func (m *Service) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *Service) GetExec() string { + if m != nil { + return m.Exec + } + return "" +} + +type Options struct { + // command to pass in + Command string `protobuf:"bytes,1,opt,name=command,proto3" json:"command,omitempty"` + // environment to pass in + Env []string `protobuf:"bytes,2,rep,name=env,proto3" json:"env,omitempty"` + // output to send to + Output string `protobuf:"bytes,3,opt,name=output,proto3" json:"output,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Options) Reset() { *m = Options{} } +func (m *Options) String() string { return proto.CompactTextString(m) } +func (*Options) ProtoMessage() {} +func (*Options) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{1} +} + +func (m *Options) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Options.Unmarshal(m, b) +} +func (m *Options) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Options.Marshal(b, m, deterministic) +} +func (m *Options) XXX_Merge(src proto.Message) { + xxx_messageInfo_Options.Merge(m, src) +} +func (m *Options) XXX_Size() int { + return xxx_messageInfo_Options.Size(m) +} +func (m *Options) XXX_DiscardUnknown() { + xxx_messageInfo_Options.DiscardUnknown(m) +} + +var xxx_messageInfo_Options proto.InternalMessageInfo + +func (m *Options) GetCommand() string { + if m != nil { + return m.Command + } + return "" +} + +func (m *Options) GetEnv() []string { + if m != nil { + return m.Env + } + return nil +} + +func (m *Options) GetOutput() string { + if m != nil { + return m.Output + } + return "" +} + +type CreateRequest struct { + Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` + Options *Options `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CreateRequest) Reset() { *m = CreateRequest{} } +func (m *CreateRequest) String() string { return proto.CompactTextString(m) } +func (*CreateRequest) ProtoMessage() {} +func (*CreateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{2} +} + +func (m *CreateRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CreateRequest.Unmarshal(m, b) +} +func (m *CreateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CreateRequest.Marshal(b, m, deterministic) +} +func (m *CreateRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateRequest.Merge(m, src) +} +func (m *CreateRequest) XXX_Size() int { + return xxx_messageInfo_CreateRequest.Size(m) +} +func (m *CreateRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CreateRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_CreateRequest proto.InternalMessageInfo + +func (m *CreateRequest) GetService() *Service { + if m != nil { + return m.Service + } + return nil +} + +func (m *CreateRequest) GetOptions() *Options { + if m != nil { + return m.Options + } + return nil +} + +type CreateResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CreateResponse) Reset() { *m = CreateResponse{} } +func (m *CreateResponse) String() string { return proto.CompactTextString(m) } +func (*CreateResponse) ProtoMessage() {} +func (*CreateResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{3} +} + +func (m *CreateResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CreateResponse.Unmarshal(m, b) +} +func (m *CreateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CreateResponse.Marshal(b, m, deterministic) +} +func (m *CreateResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateResponse.Merge(m, src) +} +func (m *CreateResponse) XXX_Size() int { + return xxx_messageInfo_CreateResponse.Size(m) +} +func (m *CreateResponse) XXX_DiscardUnknown() { + xxx_messageInfo_CreateResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_CreateResponse proto.InternalMessageInfo + +type DeleteRequest struct { + Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } +func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteRequest) ProtoMessage() {} +func (*DeleteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{4} +} + +func (m *DeleteRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteRequest.Unmarshal(m, b) +} +func (m *DeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteRequest.Marshal(b, m, deterministic) +} +func (m *DeleteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteRequest.Merge(m, src) +} +func (m *DeleteRequest) XXX_Size() int { + return xxx_messageInfo_DeleteRequest.Size(m) +} +func (m *DeleteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteRequest proto.InternalMessageInfo + +func (m *DeleteRequest) GetService() *Service { + if m != nil { + return m.Service + } + return nil +} + +type DeleteResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } +func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteResponse) ProtoMessage() {} +func (*DeleteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{5} +} + +func (m *DeleteResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteResponse.Unmarshal(m, b) +} +func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteResponse.Marshal(b, m, deterministic) +} +func (m *DeleteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteResponse.Merge(m, src) +} +func (m *DeleteResponse) XXX_Size() int { + return xxx_messageInfo_DeleteResponse.Size(m) +} +func (m *DeleteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo + +type UpdateRequest struct { + Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UpdateRequest) Reset() { *m = UpdateRequest{} } +func (m *UpdateRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateRequest) ProtoMessage() {} +func (*UpdateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{6} +} + +func (m *UpdateRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UpdateRequest.Unmarshal(m, b) +} +func (m *UpdateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UpdateRequest.Marshal(b, m, deterministic) +} +func (m *UpdateRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_UpdateRequest.Merge(m, src) +} +func (m *UpdateRequest) XXX_Size() int { + return xxx_messageInfo_UpdateRequest.Size(m) +} +func (m *UpdateRequest) XXX_DiscardUnknown() { + xxx_messageInfo_UpdateRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_UpdateRequest proto.InternalMessageInfo + +func (m *UpdateRequest) GetService() *Service { + if m != nil { + return m.Service + } + return nil +} + +type UpdateResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UpdateResponse) Reset() { *m = UpdateResponse{} } +func (m *UpdateResponse) String() string { return proto.CompactTextString(m) } +func (*UpdateResponse) ProtoMessage() {} +func (*UpdateResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{7} +} + +func (m *UpdateResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UpdateResponse.Unmarshal(m, b) +} +func (m *UpdateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UpdateResponse.Marshal(b, m, deterministic) +} +func (m *UpdateResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_UpdateResponse.Merge(m, src) +} +func (m *UpdateResponse) XXX_Size() int { + return xxx_messageInfo_UpdateResponse.Size(m) +} +func (m *UpdateResponse) XXX_DiscardUnknown() { + xxx_messageInfo_UpdateResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_UpdateResponse proto.InternalMessageInfo + +type ListRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListRequest) Reset() { *m = ListRequest{} } +func (m *ListRequest) String() string { return proto.CompactTextString(m) } +func (*ListRequest) ProtoMessage() {} +func (*ListRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{8} +} + +func (m *ListRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListRequest.Unmarshal(m, b) +} +func (m *ListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListRequest.Marshal(b, m, deterministic) +} +func (m *ListRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListRequest.Merge(m, src) +} +func (m *ListRequest) XXX_Size() int { + return xxx_messageInfo_ListRequest.Size(m) +} +func (m *ListRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListRequest proto.InternalMessageInfo + +type ListResponse struct { + Services []*Service `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListResponse) Reset() { *m = ListResponse{} } +func (m *ListResponse) String() string { return proto.CompactTextString(m) } +func (*ListResponse) ProtoMessage() {} +func (*ListResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{9} +} + +func (m *ListResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListResponse.Unmarshal(m, b) +} +func (m *ListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListResponse.Marshal(b, m, deterministic) +} +func (m *ListResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListResponse.Merge(m, src) +} +func (m *ListResponse) XXX_Size() int { + return xxx_messageInfo_ListResponse.Size(m) +} +func (m *ListResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ListResponse proto.InternalMessageInfo + +func (m *ListResponse) GetServices() []*Service { + if m != nil { + return m.Services + } + return nil +} + +func init() { + proto.RegisterType((*Service)(nil), "go.micro.runtime.Service") + proto.RegisterType((*Options)(nil), "go.micro.runtime.Options") + proto.RegisterType((*CreateRequest)(nil), "go.micro.runtime.CreateRequest") + proto.RegisterType((*CreateResponse)(nil), "go.micro.runtime.CreateResponse") + proto.RegisterType((*DeleteRequest)(nil), "go.micro.runtime.DeleteRequest") + proto.RegisterType((*DeleteResponse)(nil), "go.micro.runtime.DeleteResponse") + proto.RegisterType((*UpdateRequest)(nil), "go.micro.runtime.UpdateRequest") + proto.RegisterType((*UpdateResponse)(nil), "go.micro.runtime.UpdateResponse") + proto.RegisterType((*ListRequest)(nil), "go.micro.runtime.ListRequest") + proto.RegisterType((*ListResponse)(nil), "go.micro.runtime.ListResponse") +} + +func init() { + proto.RegisterFile("micro/go-micro/runtime/service/proto/runtime.proto", fileDescriptor_4bc91a8efec81434) +} + +var fileDescriptor_4bc91a8efec81434 = []byte{ + // 379 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0xcb, 0x4e, 0xc2, 0x40, + 0x14, 0x86, 0x81, 0x22, 0x95, 0x83, 0x18, 0x32, 0x0b, 0x33, 0x92, 0xa8, 0x4d, 0x57, 0x6c, 0x2c, + 0x09, 0xc4, 0x27, 0x10, 0xe3, 0x46, 0x62, 0x52, 0xe3, 0x03, 0xd4, 0x72, 0x82, 0x4d, 0x6c, 0xa7, + 0xce, 0x4c, 0x51, 0x9f, 0xce, 0x57, 0x33, 0x73, 0x43, 0x81, 0xe2, 0x86, 0xdd, 0xb9, 0x7e, 0xff, + 0x99, 0xbf, 0x29, 0x4c, 0xf2, 0x2c, 0xe5, 0x6c, 0xbc, 0x64, 0xd7, 0x26, 0xe0, 0x55, 0x21, 0xb3, + 0x1c, 0xc7, 0x02, 0xf9, 0x2a, 0x4b, 0x71, 0x5c, 0x72, 0x26, 0xd7, 0xd5, 0x48, 0x67, 0x64, 0xb0, + 0x64, 0x91, 0x9e, 0x8e, 0x6c, 0x3d, 0xfc, 0x00, 0xff, 0xc9, 0x2c, 0x10, 0x02, 0xed, 0x22, 0xc9, + 0x91, 0x36, 0x83, 0xe6, 0xa8, 0x1b, 0xeb, 0x98, 0x50, 0xf0, 0x57, 0xc8, 0x45, 0xc6, 0x0a, 0xda, + 0xd2, 0x65, 0x97, 0x92, 0x33, 0xe8, 0x08, 0x56, 0xf1, 0x14, 0xa9, 0xa7, 0x1b, 0x36, 0x53, 0x94, + 0x32, 0x91, 0xaf, 0xb4, 0x6d, 0x28, 0x2a, 0x56, 0x35, 0xfc, 0xc4, 0x94, 0x1e, 0x99, 0x9a, 0x8a, + 0xc3, 0x39, 0xf8, 0x8f, 0xa5, 0xcc, 0x58, 0x21, 0x94, 0x48, 0xca, 0xf2, 0x3c, 0x29, 0x16, 0x56, + 0xdb, 0xa5, 0x64, 0x00, 0x1e, 0x16, 0x2b, 0xda, 0x0a, 0xbc, 0x51, 0x37, 0x56, 0xa1, 0x92, 0x65, + 0x95, 0x2c, 0x2b, 0xe9, 0x64, 0x4d, 0x16, 0x7e, 0x41, 0xff, 0x96, 0x63, 0x22, 0x31, 0xc6, 0xf7, + 0x0a, 0x85, 0x24, 0x53, 0xf0, 0xad, 0x13, 0x1a, 0xda, 0x9b, 0x9c, 0x47, 0xdb, 0x8f, 0x8f, 0xec, + 0xcb, 0x63, 0x37, 0xa9, 0x96, 0x98, 0x39, 0x4a, 0x3f, 0xb7, 0x76, 0xc9, 0x5e, 0x1d, 0xbb, 0xc9, + 0x70, 0x00, 0xa7, 0x4e, 0x5a, 0x94, 0xac, 0x10, 0x18, 0xce, 0xa0, 0x3f, 0xc3, 0x37, 0x3c, 0xec, + 0x18, 0xc5, 0x75, 0x94, 0x5f, 0xee, 0x73, 0xb9, 0x48, 0x0e, 0xe7, 0x3a, 0x8a, 0xe5, 0xf6, 0xa1, + 0xf7, 0x90, 0x09, 0x69, 0xa9, 0xe1, 0x1d, 0x9c, 0x98, 0xd4, 0xb4, 0xc9, 0x0d, 0x1c, 0xdb, 0x5d, + 0x41, 0x9b, 0x81, 0xf7, 0xbf, 0xcc, 0x7a, 0x74, 0xf2, 0xdd, 0x02, 0x3f, 0x36, 0x5d, 0x32, 0x87, + 0x8e, 0xf1, 0x88, 0x5c, 0xed, 0xae, 0x6e, 0x7c, 0xb8, 0x61, 0xb0, 0x7f, 0xc0, 0x9e, 0xdb, 0x50, + 0x38, 0x63, 0x4d, 0x1d, 0x6e, 0xc3, 0xfa, 0x3a, 0xdc, 0x96, 0xab, 0x1a, 0x67, 0x1c, 0xa9, 0xc3, + 0x6d, 0x38, 0x5e, 0x87, 0xdb, 0x32, 0xb3, 0x41, 0xee, 0xa1, 0xad, 0xfc, 0x23, 0x17, 0xbb, 0xb3, + 0x7f, 0x6c, 0x1e, 0x5e, 0xee, 0x6b, 0x3b, 0xd0, 0x4b, 0x47, 0xff, 0xb5, 0xd3, 0x9f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x69, 0x49, 0x0f, 0xe1, 0xeb, 0x03, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// RuntimeClient is the client API for Runtime service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type RuntimeClient interface { + Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) + Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) + Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) + List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) +} + +type runtimeClient struct { + cc *grpc.ClientConn +} + +func NewRuntimeClient(cc *grpc.ClientConn) RuntimeClient { + return &runtimeClient{cc} +} + +func (c *runtimeClient) Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) { + out := new(CreateResponse) + err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Create", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) { + out := new(DeleteResponse) + err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Delete", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) { + out := new(UpdateResponse) + err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Update", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { + out := new(ListResponse) + err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/List", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// RuntimeServer is the server API for Runtime service. +type RuntimeServer interface { + Create(context.Context, *CreateRequest) (*CreateResponse, error) + Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) + Update(context.Context, *UpdateRequest) (*UpdateResponse, error) + List(context.Context, *ListRequest) (*ListResponse, error) +} + +func RegisterRuntimeServer(s *grpc.Server, srv RuntimeServer) { + s.RegisterService(&_Runtime_serviceDesc, srv) +} + +func _Runtime_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServer).Create(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.runtime.Runtime/Create", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServer).Create(ctx, req.(*CreateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Runtime_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServer).Delete(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.runtime.Runtime/Delete", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServer).Delete(ctx, req.(*DeleteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Runtime_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServer).Update(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.runtime.Runtime/Update", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServer).Update(ctx, req.(*UpdateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Runtime_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServer).List(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/go.micro.runtime.Runtime/List", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServer).List(ctx, req.(*ListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Runtime_serviceDesc = grpc.ServiceDesc{ + ServiceName: "go.micro.runtime.Runtime", + HandlerType: (*RuntimeServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Create", + Handler: _Runtime_Create_Handler, + }, + { + MethodName: "Delete", + Handler: _Runtime_Delete_Handler, + }, + { + MethodName: "Update", + Handler: _Runtime_Update_Handler, + }, + { + MethodName: "List", + Handler: _Runtime_List_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "micro/go-micro/runtime/service/proto/runtime.proto", +} diff --git a/runtime/service/proto/runtime.proto b/runtime/service/proto/runtime.proto new file mode 100644 index 00000000..eb5bb128 --- /dev/null +++ b/runtime/service/proto/runtime.proto @@ -0,0 +1,57 @@ +syntax = "proto3"; + +package go.micro.runtime; + +service Runtime { + rpc Create(CreateRequest) returns (CreateResponse) {}; + rpc Delete(DeleteRequest) returns (DeleteResponse) {}; + rpc Update(UpdateRequest) returns (UpdateResponse) {}; + rpc List(ListRequest) returns (ListResponse) {}; +} + +message Service { + // name of the service + string name = 1; + // version of the service + string version = 2; + // git url of the source + string source = 3; + // local path of the source + string path = 4; + // command to execute + string exec = 5; +} + +message Options { + // command to pass in + string command = 1; + // environment to pass in + repeated string env = 2; + // output to send to + string output = 3; +} + +message CreateRequest { + Service service = 1; + Options options = 2; +} + +message CreateResponse {} + +message DeleteRequest { + Service service = 1; +} + +message DeleteResponse {} + +message UpdateRequest { + Service service = 1; +} + +message UpdateResponse {} + +message ListRequest {} + +message ListResponse { + repeated Service services = 1; +} From c14bf5dc4e62f3d07059282ed76c89485d027928 Mon Sep 17 00:00:00 2001 From: Yang Shi Date: Sun, 3 Nov 2019 07:08:54 +0800 Subject: [PATCH 169/344] improve the log of panic recovering (#906) --- server/grpc/grpc.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index e037a0d1..9b66428e 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -7,6 +7,7 @@ import ( "fmt" "net" "reflect" + "runtime/debug" "sort" "strconv" "strings" @@ -340,7 +341,8 @@ func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service, fn := func(ctx context.Context, req server.Request, rsp interface{}) error { defer func() { if r := recover(); r != nil { - log.Logf("handler %s panic recovered, err: %s", mtype.method.Name, r) + log.Log("panic recovered: ", r) + log.Logf(string(debug.Stack())) } }() returnValues = function.Call([]reflect.Value{service.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(argv.Interface()), reflect.ValueOf(rsp)}) From c45ea62ea8636093fdca1ea15f4df17bfca7718d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 2 Nov 2019 23:13:01 +0000 Subject: [PATCH 170/344] Do not deregister services in the monitor unless Reap is called --- monitor/default.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/monitor/default.go b/monitor/default.go index 050f8335..4aec0d47 100644 --- a/monitor/default.go +++ b/monitor/default.go @@ -78,13 +78,6 @@ func (m *monitor) check(service string) (*Status, error) { client.WithRetries(3), ) if err != nil { - // reap the dead node - m.registry.Deregister(®istry.Service{ - Name: service.Name, - Version: service.Version, - Nodes: []*registry.Node{node}, - }) - // save the error gerr = err continue From bd37e6783952314bdf90e876001115396c579069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E6=B3=BD=E8=BD=A9?= Date: Sun, 3 Nov 2019 16:17:01 +0800 Subject: [PATCH 171/344] fix a typo in sync/lock/memory package (#910) --- sync/lock/memory/memory.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sync/lock/memory/memory.go b/sync/lock/memory/memory.go index 0812cee6..84e0ca73 100644 --- a/sync/lock/memory/memory.go +++ b/sync/lock/memory/memory.go @@ -1,4 +1,4 @@ -// Package memoy provides a sync.Mutex implementation of the lock for local use +// Package memory provides a sync.Mutex implementation of the lock for local use package memory import ( From 8579c8b321cf9bcda08fa7d581d669cfc9adfd17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E6=B3=BD=E8=BD=A9?= Date: Sun, 3 Nov 2019 16:18:48 +0800 Subject: [PATCH 172/344] avoid deadlock in syncMap.Iterate (#909) Previously, when syncMap iterates a list of records which have the same content in different order, a deadlock might happen. By enforcing a certain order, the deadlock can be avoided. --- sync/map.go | 5 +++++ sync/map_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 sync/map_test.go diff --git a/sync/map.go b/sync/map.go index b19a9c43..2515d57c 100644 --- a/sync/map.go +++ b/sync/map.go @@ -5,6 +5,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "sort" "github.com/micro/go-micro/store" ckv "github.com/micro/go-micro/store/etcd" @@ -94,6 +95,10 @@ func (m *syncMap) Iterate(fn func(key, val interface{}) error) error { return err } + sort.Slice(keyvals, func(i, j int) bool { + return keyvals[i].Key < keyvals[j].Key + }) + for _, keyval := range keyvals { // lock if err := m.opts.Lock.Acquire(keyval.Key); err != nil { diff --git a/sync/map_test.go b/sync/map_test.go new file mode 100644 index 00000000..8e3e0574 --- /dev/null +++ b/sync/map_test.go @@ -0,0 +1,39 @@ +package sync + +import ( + "testing" + "time" + + store "github.com/micro/go-micro/store" + mem_store "github.com/micro/go-micro/store/memory" + mem_lock "github.com/micro/go-micro/sync/lock/memory" +) + +func TestIterate(t *testing.T) { + s1 := mem_store.NewStore() + s2 := mem_store.NewStore() + recA := &store.Record{ + Key: "A", + Value: nil, + } + recB := &store.Record{ + Key: "B", + Value: nil, + } + s1.Write(recA) + s1.Write(recB) + s2.Write(recB) + s2.Write(recA) + + f := func(key, val interface{}) error { + time.Sleep(1 * time.Millisecond) + return nil + } + l := mem_lock.NewLock() + m1 := NewMap(WithStore(s1), WithLock(l)) + m2 := NewMap(WithStore(s2), WithLock(l)) + go func() { + m2.Iterate(f) + }() + m1.Iterate(f) +} From 45cd14c4b728f92525d4a9fafa4c871e1d684989 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 3 Nov 2019 16:12:17 +0000 Subject: [PATCH 173/344] Suppress log messages --- network/default.go | 20 +++++++++----------- tunnel/default.go | 4 ++-- tunnel/session.go | 4 ++-- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/network/default.go b/network/default.go index 3c395064..7c37517d 100644 --- a/network/default.go +++ b/network/default.go @@ -309,7 +309,7 @@ func (n *network) acceptNetConn(l tunnel.Listener, recv chan *message) { func (n *network) updatePeerLinks(peerAddr string, linkId string) error { n.Lock() defer n.Unlock() - log.Debugf("Network looking up link %s in the peer links", linkId) + log.Tracef("Network looking up link %s in the peer links", linkId) // lookup the peer link var peerLink tunnel.Link for _, link := range n.tunnel.Links() { @@ -322,7 +322,7 @@ func (n *network) updatePeerLinks(peerAddr string, linkId string) error { return ErrPeerLinkNotFound } // if the peerLink is found in the returned links update peerLinks - log.Debugf("Network updating peer links for peer %s", peerAddr) + log.Tracef("Network updating peer links for peer %s", peerAddr) // add peerLink to the peerLinks map if link, ok := n.peerLinks[peerAddr]; ok { // if the existing has better Length then the new, replace it @@ -369,7 +369,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { lastSeen: now, } // update peer links - log.Debugf("Network updating peer link %s for peer: %s", m.session.Link(), pbNetConnect.Node.Address) + log.Tracef("Network updating peer link %s for peer: %s", m.session.Link(), pbNetConnect.Node.Address) if err := n.updatePeerLinks(pbNetConnect.Node.Address, m.session.Link()); err != nil { log.Debugf("Network failed updating peer links: %s", err) } @@ -412,7 +412,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { lastSeen: now, } // update peer links - log.Debugf("Network updating peer link %s for peer: %s", m.session.Link(), pbNetPeer.Node.Address) + log.Tracef("Network updating peer link %s for peer: %s", m.session.Link(), pbNetPeer.Node.Address) if err := n.updatePeerLinks(pbNetPeer.Node.Address, m.session.Link()); err != nil { log.Debugf("Network failed updating peer links: %s", err) } @@ -439,7 +439,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { // NOTE: we don't unpack MaxDepth toplogy peer = UnpackPeerTopology(pbNetPeer, now, MaxDepth-1) - log.Debugf("Network updating topology of node: %s", n.node.id) + log.Tracef("Network updating topology of node: %s", n.node.id) if err := n.node.UpdatePeer(peer); err != nil { log.Debugf("Network failed to update peers: %v", err) } @@ -701,16 +701,14 @@ func (n *network) getRouteMetric(router string, gateway string, link string) int defer n.RUnlock() if link == "local" && gateway == "" { - log.Debugf("Network link: %s, gateway: blank", link) return 1 } if link == "local" && gateway != "" { - log.Debugf("Network link: %s, gateway: %s", link, gateway) return 2 } - log.Debugf("Network looking up %s link to gateway: %s", link, gateway) + log.Tracef("Network looking up %s link to gateway: %s", link, gateway) if link, ok := n.peerLinks[gateway]; ok { // maka sure delay is non-zero delay := link.Delay() @@ -725,7 +723,7 @@ func (n *network) getRouteMetric(router string, gateway string, link string) int log.Debugf("Link length is 0 %v %v", link, link.Length()) length = 10e9 } - log.Debugf("Network calculated metric %v delay %v length %v distance %v", (delay*length*int64(hops))/10e6, delay, length, hops) + log.Tracef("Network calculated metric %v delay %v length %v distance %v", (delay*length*int64(hops))/10e6, delay, length, hops) return (delay * length * int64(hops)) / 10e6 } @@ -789,7 +787,7 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { // calculate route metric and add to the advertised metric // we need to make sure we do not overflow math.MaxInt64 metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link) - log.Debugf("Network metric for router %s and gateway %s: %v", event.Route.Router, event.Route.Gateway, metric) + log.Tracef("Network metric for router %s and gateway %s: %v", event.Route.Router, event.Route.Gateway, metric) // check we don't overflow max int 64 if d := route.Metric + metric; d > math.MaxInt64 || d <= 0 { @@ -810,7 +808,7 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { } // if no events are eligible for processing continue if len(events) == 0 { - log.Debugf("Network no events to be processed by router: %s", n.options.Id) + log.Tracef("Network no events to be processed by router: %s", n.options.Id) continue } // create an advert and process it diff --git a/tunnel/default.go b/tunnel/default.go index 314ee908..d78e5bea 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -363,7 +363,7 @@ func (t *tun) process() { // send the message for _, link := range sendTo { // send the message via the current link - log.Debugf("Sending %+v to %s", newMsg.Header, link.Remote()) + log.Tracef("Sending %+v to %s", newMsg.Header, link.Remote()) if errr := link.Send(newMsg); errr != nil { log.Debugf("Tunnel error sending %+v to %s: %v", newMsg.Header, link.Remote(), errr) @@ -548,7 +548,7 @@ func (t *tun) listen(link *link) { // a continued session case "session": // process message - log.Debugf("Received %+v from %s", msg.Header, link.Remote()) + log.Tracef("Received %+v from %s", msg.Header, link.Remote()) // an announcement of a channel listener case "announce": // process the announcement diff --git a/tunnel/session.go b/tunnel/session.go index 0fcab963..59cbdb5e 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -321,7 +321,7 @@ func (s *session) Send(m *transport.Message) error { msg.link = "" } - log.Debugf("Appending %+v to send backlog", msg) + log.Tracef("Appending %+v to send backlog", msg) // send the actual message s.send <- msg @@ -352,7 +352,7 @@ func (s *session) Recv(m *transport.Message) error { default: } - log.Debugf("Received %+v from recv backlog", msg) + log.Tracef("Received %+v from recv backlog", msg) // set message *m = *msg.data // return nil From c1b0a968ae93ebf5e8100dfc7ce2628d06be0d1e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 3 Nov 2019 16:29:10 +0000 Subject: [PATCH 174/344] Augment the router penalty and decay as a hack fix (#912) * Augment the router penalty and decay as a hack fix * increase recovery cost --- router/default.go | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/router/default.go b/router/default.go index 48cdb230..ec486536 100644 --- a/router/default.go +++ b/router/default.go @@ -23,15 +23,13 @@ const ( // AdvertSuppress is advert suppression threshold AdvertSuppress = 2000.0 // AdvertRecover is advert recovery threshold - AdvertRecover = 750.0 + AdvertRecover = 1000.0 // DefaultAdvertTTL is default advertisement TTL DefaultAdvertTTL = 1 * time.Minute - // DeletePenalty penalises route deletion - DeletePenalty = 1000.0 - // UpdatePenalty penalises route updates - UpdatePenalty = 500.0 + // Penalty for routes processed multiple times + Penalty = 2000.0 // PenaltyHalfLife is the time the advert penalty decays to half its value - PenaltyHalfLife = 2.0 + PenaltyHalfLife = 2.5 // MaxSuppressTime defines time after which the suppressed advert is deleted MaxSuppressTime = 5 * time.Minute ) @@ -385,15 +383,16 @@ func (r *router) advertiseEvents() error { // decay the event penalty delta := time.Since(advert.lastUpdate).Seconds() advert.penalty = advert.penalty * math.Exp(-delta*PenaltyDecay) - + service := advert.event.Route.Service + address := advert.event.Route.Address // suppress/recover the event based on its penalty level switch { case advert.penalty > AdvertSuppress && !advert.isSuppressed: - log.Debugf("Router supressing advert %d for route %s", key, advert.event.Route.Address) + log.Debugf("Router suppressing advert %d %.2f for route %s %s", key, advert.penalty, service, address) advert.isSuppressed = true advert.suppressTime = time.Now() case advert.penalty < AdvertRecover && advert.isSuppressed: - log.Debugf("Router recovering advert %d for route %s", key, advert.event.Route.Address) + log.Debugf("Router recovering advert %d %.2f for route %s %s", key, advert.penalty, service, address) advert.isSuppressed = false } @@ -425,15 +424,11 @@ func (r *router) advertiseEvents() error { if e == nil { continue } - log.Debugf("Router processing table event %s for service %s", e.Type, e.Route.Address) + log.Debugf("Router processing table event %s for service %s %s", e.Type, e.Route.Service, e.Route.Address) + // determine the event penalty - var penalty float64 - switch e.Type { - case Update: - penalty = UpdatePenalty - case Delete: - penalty = DeletePenalty - } + // TODO: should there be any difference in penalty for different event types + penalty := Penalty // check if we have already registered the route hash := e.Route.Hash() @@ -456,7 +451,7 @@ func (r *router) advertiseEvents() error { // update event penalty and timestamp advert.lastUpdate = time.Now() advert.penalty += penalty - log.Debugf("Router advert %d for route %s event penalty: %f", hash, advert.event.Route.Address, advert.penalty) + log.Debugf("Router advert %d for route %s %s event penalty: %f", hash, advert.event.Route.Service, advert.event.Route.Address, advert.penalty) case <-r.exit: // first wait for the advertiser to finish r.advertWg.Wait() @@ -665,7 +660,7 @@ func (r *router) Process(a *Advert) error { // create a copy of the route route := event.Route action := event.Type - log.Debugf("Router %s applying %s from router %s for address: %s", r.options.Id, action, route.Router, route.Address) + log.Debugf("Router %s applying %s from router %s for service %s %s", r.options.Id, action, route.Router, route.Service, route.Address) if err := r.manageRoute(route, fmt.Sprintf("%s", action)); err != nil { return fmt.Errorf("failed applying action %s to routing table: %s", action, err) } From 2f3c251b00548f80c2387a05bc28ab18888f986b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 3 Nov 2019 17:10:00 +0000 Subject: [PATCH 175/344] Recovery should be < 500 --- router/default.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/default.go b/router/default.go index ec486536..9aca4ec0 100644 --- a/router/default.go +++ b/router/default.go @@ -23,7 +23,7 @@ const ( // AdvertSuppress is advert suppression threshold AdvertSuppress = 2000.0 // AdvertRecover is advert recovery threshold - AdvertRecover = 1000.0 + AdvertRecover = 500.0 // DefaultAdvertTTL is default advertisement TTL DefaultAdvertTTL = 1 * time.Minute // Penalty for routes processed multiple times From 24b8d2a31594291236b100f79d56bdc1a5f6cb88 Mon Sep 17 00:00:00 2001 From: Till Knuesting Date: Mon, 4 Nov 2019 10:33:53 +0000 Subject: [PATCH 176/344] preallocating slices (#904) * preallocated some slices when size is known * gofmt * gofmt --- network/service/handler/handler.go | 2 +- proxy/mucp/mucp.go | 4 ++-- registry/service/service.go | 4 ++-- store/cloudflare/cloudflare.go | 2 +- store/etcd/etcd.go | 2 +- tunnel/default.go | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/network/service/handler/handler.go b/network/service/handler/handler.go index 54f449f9..c47c0b30 100644 --- a/network/service/handler/handler.go +++ b/network/service/handler/handler.go @@ -171,7 +171,7 @@ func (n *Network) Routes(ctx context.Context, req *pbNet.RoutesRequest, resp *pb return errors.InternalServerError("go.micro.network", "failed to list routes: %s", err) } - var respRoutes []*pbRtr.Route + respRoutes := make([]*pbRtr.Route, 0, len(routes)) for _, route := range routes { respRoute := &pbRtr.Route{ Service: route.Service, diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index 91c40bc0..d0738358 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -95,7 +95,7 @@ func toNodes(routes []router.Route) []string { } func toSlice(r map[uint64]router.Route) []router.Route { - var routes []router.Route + routes := make([]router.Route, 0, len(r)) for _, v := range r { routes = append(routes, v) } @@ -224,7 +224,7 @@ func (p *Proxy) cacheRoutes(service string) ([]router.Route, error) { // refreshMetrics will refresh any metrics for our local cached routes. // we may not receive new watch events for these as they change. func (p *Proxy) refreshMetrics() { - var services []string + services := make([]string, 0, len(p.Routes)) // get a list of services to update p.RLock() diff --git a/registry/service/service.go b/registry/service/service.go index fefc9e77..86f1becc 100644 --- a/registry/service/service.go +++ b/registry/service/service.go @@ -89,7 +89,7 @@ func (s *serviceRegistry) GetService(name string) ([]*registry.Service, error) { return nil, err } - var services []*registry.Service + services := make([]*registry.Service, 0, len(rsp.Services)) for _, service := range rsp.Services { services = append(services, ToService(service)) } @@ -102,7 +102,7 @@ func (s *serviceRegistry) ListServices() ([]*registry.Service, error) { return nil, err } - var services []*registry.Service + services := make([]*registry.Service, 0, len(rsp.Services)) for _, service := range rsp.Services { services = append(services, ToService(service)) } diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index 052d0fd2..d0fa6925 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -123,7 +123,7 @@ func (w *workersKV) List() ([]*store.Record, error) { return nil, errors.New(messages) } - var keys []string + keys := make([]string, 0, len(a.Result)) for _, r := range a.Result { keys = append(keys, r.Name) diff --git a/store/etcd/etcd.go b/store/etcd/etcd.go index 82b62902..e45ce2d1 100644 --- a/store/etcd/etcd.go +++ b/store/etcd/etcd.go @@ -32,7 +32,7 @@ func (e *ekv) Read(keys ...string) ([]*store.Record, error) { values = append(values, keyval.Kvs...) } - var records []*store.Record + records := make([]*store.Record, 0, len(values)) for _, kv := range values { records = append(records, &store.Record{ diff --git a/tunnel/default.go b/tunnel/default.go index d78e5bea..adf4bb6d 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -1186,7 +1186,7 @@ func (t *tun) Links() []Link { t.RLock() defer t.RUnlock() - var links []Link + links := make([]Link, 0, len(t.links)) for _, link := range t.links { links = append(links, link) From 4a694c9d02eac9c4de6c5ddbfc532912e4deb8d5 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Mon, 4 Nov 2019 19:01:52 +0000 Subject: [PATCH 177/344] Change flap detection configuration (#914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change flap detection configuration * Make PenaltyHalfLife a float, not int 🤦‍♂️ * Lower event suppression to 200 --- router/default.go | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/router/default.go b/router/default.go index 9aca4ec0..579c2af7 100644 --- a/router/default.go +++ b/router/default.go @@ -21,15 +21,15 @@ const ( // AdvertiseFlushTick is time the yet unconsumed advertisements are flush i.e. discarded AdvertiseFlushTick = 15 * time.Second // AdvertSuppress is advert suppression threshold - AdvertSuppress = 2000.0 + AdvertSuppress = 200.0 // AdvertRecover is advert recovery threshold - AdvertRecover = 500.0 + AdvertRecover = 120.0 // DefaultAdvertTTL is default advertisement TTL DefaultAdvertTTL = 1 * time.Minute // Penalty for routes processed multiple times - Penalty = 2000.0 + Penalty = 100.0 // PenaltyHalfLife is the time the advert penalty decays to half its value - PenaltyHalfLife = 2.5 + PenaltyHalfLife = 30.0 // MaxSuppressTime defines time after which the suppressed advert is deleted MaxSuppressTime = 5 * time.Minute ) @@ -396,21 +396,24 @@ func (r *router) advertiseEvents() error { advert.isSuppressed = false } - // max suppression time threshold has been reached, delete the advert if advert.isSuppressed { + // max suppression time threshold has been reached, delete the advert if time.Since(advert.suppressTime) > MaxSuppressTime { delete(advertMap, key) continue } + // process next advert + continue } - if !advert.isSuppressed { - e := new(Event) - *e = *(advert.event) - events = append(events, e) - // delete the advert from the advertMap - delete(advertMap, key) - } + // copy the event and append + e := new(Event) + // this is ok, because router.Event only contains builtin types + // and no references so this creates a deep struct copy of Event + *e = *(advert.event) + events = append(events, e) + // delete the advert from the advertMap + delete(advertMap, key) } // advertise all Update events to subscribers From f67c5e779f07cf2df788836193ce707a7d3fec6f Mon Sep 17 00:00:00 2001 From: Till Knuesting Date: Tue, 5 Nov 2019 17:43:12 +0000 Subject: [PATCH 178/344] preallocated slices (#917) --- client/selector/router/router.go | 2 +- client/selector/strategy.go | 2 +- config/source/etcd/etcd.go | 2 +- network/node.go | 2 +- registry/service/util.go | 2 +- router/handler/router.go | 2 +- router/service/service.go | 2 +- router/table.go | 2 +- runtime/kubernetes/kubernetes.go | 2 +- server/rpc_server.go | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/selector/router/router.go b/client/selector/router/router.go index 015bc1e3..4a6ad671 100644 --- a/client/selector/router/router.go +++ b/client/selector/router/router.go @@ -101,7 +101,7 @@ func (r *routerSelector) getRoutes(service string) ([]router.Route, error) { return nil, selector.ErrNoneAvailable } - var routes []router.Route + routes := make([]router.Route, 0, len(pbRoutes.Routes)) // convert from pb to []*router.Route for _, r := range pbRoutes.Routes { diff --git a/client/selector/strategy.go b/client/selector/strategy.go index 9455d3f3..559ed030 100644 --- a/client/selector/strategy.go +++ b/client/selector/strategy.go @@ -14,7 +14,7 @@ func init() { // Random is a random strategy algorithm for node selection func Random(services []*registry.Service) Next { - var nodes []*registry.Node + nodes := make([]*registry.Node, 0, len(services)) for _, service := range services { nodes = append(nodes, service.Nodes...) diff --git a/config/source/etcd/etcd.go b/config/source/etcd/etcd.go index 5cbe1286..7c8edba9 100644 --- a/config/source/etcd/etcd.go +++ b/config/source/etcd/etcd.go @@ -38,7 +38,7 @@ func (c *etcd) Read() (*source.ChangeSet, error) { return nil, fmt.Errorf("source not found: %s", c.prefix) } - var kvs []*mvccpb.KeyValue + kvs := make([]*mvccpb.KeyValue, 0, len(rsp.Kvs)) for _, v := range rsp.Kvs { kvs = append(kvs, (*mvccpb.KeyValue)(v)) } diff --git a/network/node.go b/network/node.go index e8632ccc..167f5e43 100644 --- a/network/node.go +++ b/network/node.go @@ -282,7 +282,7 @@ func (n *node) Peers() []Node { n.RLock() defer n.RUnlock() - var peers []Node + peers := make([]Node, 0, len(n.peers)) for _, nodePeer := range n.peers { peer := nodePeer.getTopology(MaxDepth) peers = append(peers, peer) diff --git a/registry/service/util.go b/registry/service/util.go index 5b6a1de5..04519db3 100644 --- a/registry/service/util.go +++ b/registry/service/util.go @@ -38,7 +38,7 @@ func toValues(v []*pb.Value) []*registry.Value { } func ToProto(s *registry.Service) *pb.Service { - var endpoints []*pb.Endpoint + endpoints := make([]*pb.Endpoint, 0, len(s.Endpoints)) for _, ep := range s.Endpoints { var request, response *pb.Value diff --git a/router/handler/router.go b/router/handler/router.go index 6b71f70f..90039871 100644 --- a/router/handler/router.go +++ b/router/handler/router.go @@ -22,7 +22,7 @@ func (r *Router) Lookup(ctx context.Context, req *pb.LookupRequest, resp *pb.Loo return errors.InternalServerError("go.micro.router", "failed to lookup routes: %v", err) } - var respRoutes []*pb.Route + respRoutes := make([]*pb.Route, 0, len(routes)) for _, route := range routes { respRoute := &pb.Route{ Service: route.Service, diff --git a/router/service/service.go b/router/service/service.go index 3d95ab5b..15a0ae37 100644 --- a/router/service/service.go +++ b/router/service/service.go @@ -188,7 +188,7 @@ func (s *svc) Advertise() (<-chan *router.Advert, error) { // Process processes incoming adverts func (s *svc) Process(advert *router.Advert) error { - var events []*pb.Event + events := make([]*pb.Event, 0, len(advert.Events)) for _, event := range advert.Events { route := &pb.Route{ Service: event.Route.Service, diff --git a/router/table.go b/router/table.go index 6701c05f..2b05ada0 100644 --- a/router/table.go +++ b/router/table.go @@ -194,7 +194,7 @@ func (t *table) Query(q ...QueryOption) ([]Route, error) { return findRoutes(t.routes[opts.Service], opts.Address, opts.Gateway, opts.Network, opts.Router), nil } - var results []Route + results := make([]Route, 0, len(t.routes)) // search through all destinations for _, routes := range t.routes { results = append(results, findRoutes(routes, opts.Address, opts.Gateway, opts.Network, opts.Router)...) diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 49666f37..15f0fcb1 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -139,7 +139,7 @@ func (k *kubernetes) Update(s *runtime.Service) error { func (k *kubernetes) List() ([]*runtime.Service, error) { // TODO: this should list the k8s deployments // but for now we return in-memory tracked services - var services []*runtime.Service + services := make([]*runtime.Service, 0, len(k.services)) k.RLock() defer k.RUnlock() diff --git a/server/rpc_server.go b/server/rpc_server.go index 76687e30..9e4828c6 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -490,7 +490,7 @@ func (s *rpcServer) Register() error { return subscriberList[i].topic > subscriberList[j].topic }) - var endpoints []*registry.Endpoint + endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList)) for _, n := range handlerList { endpoints = append(endpoints, s.handlers[n].Endpoints()...) } From b84134581c75eff905a7dcab0b26e2e7f0ebd4e8 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 5 Nov 2019 17:44:24 +0000 Subject: [PATCH 179/344] Flap detection vol2 (#915) * We now purge flapping routes before regular tick processes them * Updated comments * Record the timestamp as soon as you receive the event * Set route Address to routing table test * Fixed a bunch of deadlocks. Added basic Router tests. --- router/default.go | 207 +++++++++++++++++++++++++---------------- router/default_test.go | 127 +++++++++++++++++++++++++ router/table_test.go | 1 + 3 files changed, 254 insertions(+), 81 deletions(-) create mode 100644 router/default_test.go diff --git a/router/default.go b/router/default.go index 579c2af7..49f0ff1f 100644 --- a/router/default.go +++ b/router/default.go @@ -13,28 +13,25 @@ import ( "github.com/micro/go-micro/util/log" ) -const ( +var ( // AdvertiseEventsTick is time interval in which the router advertises route updates AdvertiseEventsTick = 5 * time.Second // AdvertiseTableTick is time interval in which router advertises all routes found in routing table AdvertiseTableTick = 1 * time.Minute // AdvertiseFlushTick is time the yet unconsumed advertisements are flush i.e. discarded AdvertiseFlushTick = 15 * time.Second + // DefaultAdvertTTL is default advertisement TTL + DefaultAdvertTTL = 1 * time.Minute // AdvertSuppress is advert suppression threshold AdvertSuppress = 200.0 // AdvertRecover is advert recovery threshold AdvertRecover = 120.0 - // DefaultAdvertTTL is default advertisement TTL - DefaultAdvertTTL = 1 * time.Minute // Penalty for routes processed multiple times Penalty = 100.0 // PenaltyHalfLife is the time the advert penalty decays to half its value PenaltyHalfLife = 30.0 // MaxSuppressTime defines time after which the suppressed advert is deleted MaxSuppressTime = 5 * time.Minute -) - -var ( // PenaltyDecay is a coefficient which controls the speed the advert penalty decays PenaltyDecay = math.Log(2) / PenaltyHalfLife ) @@ -52,6 +49,7 @@ type router struct { wg *sync.WaitGroup // advert subscribers + sub sync.RWMutex subscribers map[string]chan *Advert } @@ -189,7 +187,6 @@ func (r *router) watchRegistry(w registry.Watcher) error { defer func() { // close the exit channel when the go routine finishes close(exit) - r.wg.Done() }() // wait in the background for the router to stop @@ -197,6 +194,7 @@ func (r *router) watchRegistry(w registry.Watcher) error { r.wg.Add(1) go func() { defer w.Stop() + defer r.wg.Done() select { case <-r.exit: @@ -233,7 +231,6 @@ func (r *router) watchTable(w Watcher) error { defer func() { // close the exit channel when the go routine finishes close(exit) - r.wg.Done() }() // wait in the background for the router to stop @@ -241,6 +238,7 @@ func (r *router) watchTable(w Watcher) error { r.wg.Add(1) go func() { defer w.Stop() + defer r.wg.Done() select { case <-r.exit: @@ -276,10 +274,7 @@ func (r *router) watchTable(w Watcher) error { } // publishAdvert publishes router advert to advert channel -// NOTE: this might cease to be a dedicated method in the future func (r *router) publishAdvert(advType AdvertType, events []*Event) { - defer r.advertWg.Done() - a := &Advert{ Id: r.options.Id, Type: advType, @@ -288,24 +283,17 @@ func (r *router) publishAdvert(advType AdvertType, events []*Event) { Events: events, } - log.Debugf("Router publishing advert; %+v", a) - r.RLock() + r.sub.RLock() for _, sub := range r.subscribers { - // check the exit chan first - select { - case <-r.exit: - r.RUnlock() - return - default: - } - // now send the message select { case sub <- a: - default: + case <-r.exit: + r.sub.RUnlock() + return } } - r.RUnlock() + r.sub.RUnlock() } // advertiseTable advertises the whole routing table to the network @@ -327,7 +315,10 @@ func (r *router) advertiseTable() error { if len(events) > 0 { log.Debugf("Router flushing table with %d events: %s", len(events), r.options.Id) r.advertWg.Add(1) - go r.publishAdvert(RouteUpdate, events) + go func() { + defer r.advertWg.Done() + r.publishAdvert(RouteUpdate, events) + }() } case <-r.exit: return nil @@ -335,12 +326,12 @@ func (r *router) advertiseTable() error { } } -// routeAdvert contains a route event to be advertised -type routeAdvert struct { +// advert contains a route event to be advertised +type advert struct { // event received from routing table event *Event - // lastUpdate records the time of the last advert update - lastUpdate time.Time + // lastSeen records the time of the last advert update + lastSeen time.Time // penalty is current advert penalty penalty float64 // isSuppressed flags the advert suppression @@ -349,6 +340,51 @@ type routeAdvert struct { suppressTime time.Time } +// adverts maintains a map of router adverts +type adverts map[uint64]*advert + +// process processes advert +// It updates advert timestamp, increments its penalty and +// marks upresses or recovers it if it reaches configured thresholds +func (m adverts) process(a *advert) error { + // lookup advert in adverts + hash := a.event.Route.Hash() + a, ok := m[hash] + if !ok { + return fmt.Errorf("advert not found") + } + + // decay the event penalty + delta := time.Since(a.lastSeen).Seconds() + + // decay advert penalty + a.penalty = a.penalty * math.Exp(-delta*PenaltyDecay) + service := a.event.Route.Service + address := a.event.Route.Address + + // suppress/recover the event based on its penalty level + switch { + case a.penalty > AdvertSuppress && !a.isSuppressed: + log.Debugf("Router suppressing advert %d %.2f for route %s %s", hash, a.penalty, service, address) + a.isSuppressed = true + a.suppressTime = time.Now() + case a.penalty < AdvertRecover && a.isSuppressed: + log.Debugf("Router recovering advert %d %.2f for route %s %s", hash, a.penalty, service, address) + a.isSuppressed = false + } + + // if suppressed, checked how long has it been suppressed for + if a.isSuppressed { + // max suppression time threshold has been reached, delete the advert + if time.Since(a.suppressTime) > MaxSuppressTime { + delete(m, hash) + return nil + } + } + + return nil +} + // advertiseEvents advertises routing table events // It suppresses unhealthy flapping events and advertises healthy events upstream. func (r *router) advertiseEvents() error { @@ -356,8 +392,8 @@ func (r *router) advertiseEvents() error { ticker := time.NewTicker(AdvertiseEventsTick) defer ticker.Stop() - // advertMap is a map of advert events - advertMap := make(map[uint64]*routeAdvert) + // adverts is a map of advert events + adverts := make(adverts) // routing table watcher tableWatcher, err := r.Watch() @@ -379,82 +415,74 @@ func (r *router) advertiseEvents() error { case <-ticker.C: var events []*Event // collect all events which are not flapping - for key, advert := range advertMap { - // decay the event penalty - delta := time.Since(advert.lastUpdate).Seconds() - advert.penalty = advert.penalty * math.Exp(-delta*PenaltyDecay) - service := advert.event.Route.Service - address := advert.event.Route.Address - // suppress/recover the event based on its penalty level - switch { - case advert.penalty > AdvertSuppress && !advert.isSuppressed: - log.Debugf("Router suppressing advert %d %.2f for route %s %s", key, advert.penalty, service, address) - advert.isSuppressed = true - advert.suppressTime = time.Now() - case advert.penalty < AdvertRecover && advert.isSuppressed: - log.Debugf("Router recovering advert %d %.2f for route %s %s", key, advert.penalty, service, address) - advert.isSuppressed = false + for key, advert := range adverts { + // process the advert + if err := adverts.process(advert); err != nil { + log.Debugf("Router failed processing advert %d: %v", key, err) + continue } - + // if suppressed go to the next advert if advert.isSuppressed { - // max suppression time threshold has been reached, delete the advert - if time.Since(advert.suppressTime) > MaxSuppressTime { - delete(advertMap, key) - continue - } - // process next advert continue } // copy the event and append e := new(Event) // this is ok, because router.Event only contains builtin types - // and no references so this creates a deep struct copy of Event + // and no references so this creates a deep copy of struct Event *e = *(advert.event) events = append(events, e) - // delete the advert from the advertMap - delete(advertMap, key) + // delete the advert from adverts + delete(adverts, key) } - // advertise all Update events to subscribers + // advertise events to subscribers if len(events) > 0 { - r.advertWg.Add(1) log.Debugf("Router publishing %d events", len(events)) - go r.publishAdvert(RouteUpdate, events) + r.advertWg.Add(1) + go func() { + defer r.advertWg.Done() + r.publishAdvert(RouteUpdate, events) + }() } case e := <-r.eventChan: // if event is nil, continue if e == nil { continue } - log.Debugf("Router processing table event %s for service %s %s", e.Type, e.Route.Service, e.Route.Address) + now := time.Now() - // determine the event penalty - // TODO: should there be any difference in penalty for different event types - penalty := Penalty + log.Debugf("Router processing table event %s for service %s %s", e.Type, e.Route.Service, e.Route.Address) // check if we have already registered the route hash := e.Route.Hash() - advert, ok := advertMap[hash] + a, ok := adverts[hash] if !ok { - advert = &routeAdvert{ - event: e, - penalty: penalty, - lastUpdate: time.Now(), + a = &advert{ + event: e, + penalty: Penalty, + lastSeen: now, } - advertMap[hash] = advert + adverts[hash] = a continue } - // override the route event only if the last event was different - if advert.event.Type != e.Type { - advert.event = e + // override the route event only if the previous event was different + if a.event.Type != e.Type { + a.event = e + } + + // process the advert + if err := adverts.process(a); err != nil { + log.Debugf("Router error processing advert %d: %v", hash, err) + continue } // update event penalty and timestamp - advert.lastUpdate = time.Now() - advert.penalty += penalty - log.Debugf("Router advert %d for route %s %s event penalty: %f", hash, advert.event.Route.Service, advert.event.Route.Address, advert.penalty) + a.lastSeen = now + // increment the penalty + a.penalty += Penalty + log.Debugf("Router advert %d for route %s %s event penalty: %f", hash, a.event.Route.Service, a.event.Route.Address, a.penalty) case <-r.exit: // first wait for the advertiser to finish r.advertWg.Wait() @@ -474,6 +502,7 @@ func (r *router) close() { for range r.eventChan { } + r.sub.RLock() // close advert subscribers for id, sub := range r.subscribers { // close the channel @@ -482,6 +511,7 @@ func (r *router) close() { // delete the subscriber delete(r.subscribers, id) } + r.sub.RUnlock() } // mark the router as Stopped and set its Error to nil @@ -603,9 +633,16 @@ func (r *router) Advertise() (<-chan *Advert, error) { // create event channels r.eventChan = make(chan *Event) + // create advert channel + advertChan := make(chan *Advert, 128) + r.subscribers[uuid.New().String()] = advertChan + // advertise your presence r.advertWg.Add(1) - go r.publishAdvert(Announce, events) + go func() { + defer r.advertWg.Done() + r.publishAdvert(Announce, events) + }() r.wg.Add(1) go func() { @@ -629,10 +666,7 @@ func (r *router) Advertise() (<-chan *Advert, error) { // mark router as Running and set its Error to nil r.status = Status{Code: Advertising, Error: nil} - // create advert channel - advertChan := make(chan *Advert, 128) - r.subscribers[uuid.New().String()] = advertChan - + log.Debugf("Router starting to advertise") return advertChan, nil case Stopped: return nil, fmt.Errorf("not running") @@ -747,7 +781,10 @@ func (r *router) Solicit() error { // advertise the routes r.advertWg.Add(1) - go r.publishAdvert(RouteUpdate, events) + go func() { + defer r.advertWg.Done() + r.publishAdvert(RouteUpdate, events) + }() return nil } @@ -776,19 +813,27 @@ func (r *router) Status() Status { // Stop stops the router func (r *router) Stop() error { r.Lock() - defer r.Unlock() + + log.Debugf("Router shutting down") switch r.status.Code { case Stopped, Error: + r.Unlock() return r.status.Error case Running, Advertising: // close all the channels + // NOTE: close marks the router status as Stopped r.close() } + r.Unlock() + + log.Debugf("Router waiting for all goroutines to finish") // wait for all goroutines to finish r.wg.Wait() + log.Debugf("Router successfully stopped") + return nil } diff --git a/router/default_test.go b/router/default_test.go new file mode 100644 index 00000000..4c3c933e --- /dev/null +++ b/router/default_test.go @@ -0,0 +1,127 @@ +package router + +import ( + "fmt" + "sync" + "testing" + "time" + + "github.com/micro/go-micro/registry/memory" + "github.com/micro/go-micro/util/log" +) + +func routerTestSetup() Router { + r := memory.NewRegistry() + return newRouter(Registry(r)) +} + +func TestRouterStartStop(t *testing.T) { + r := routerTestSetup() + + log.Debugf("TestRouterStartStop STARTING") + if err := r.Start(); err != nil { + t.Errorf("failed to start router: %v", err) + } + + _, err := r.Advertise() + if err != nil { + t.Errorf("failed to start advertising: %v", err) + } + + if err := r.Stop(); err != nil { + t.Errorf("failed to stop router: %v", err) + } + log.Debugf("TestRouterStartStop STOPPED") +} + +func TestRouterAdvertise(t *testing.T) { + r := routerTestSetup() + + // lower the advertise interval + AdvertiseEventsTick = 500 * time.Millisecond + AdvertiseTableTick = 1 * time.Second + + if err := r.Start(); err != nil { + t.Errorf("failed to start router: %v", err) + } + + ch, err := r.Advertise() + if err != nil { + t.Errorf("failed to start advertising: %v", err) + } + + // receive announce event + ann := <-ch + log.Debugf("received announce advert: %v", ann) + + // Generate random unique routes + nrRoutes := 5 + routes := make([]Route, nrRoutes) + route := Route{ + Service: "dest.svc", + Address: "dest.addr", + Gateway: "dest.gw", + Network: "dest.network", + Router: "src.router", + Link: "det.link", + Metric: 10, + } + + for i := 0; i < nrRoutes; i++ { + testRoute := route + testRoute.Service = fmt.Sprintf("%s-%d", route.Service, i) + routes[i] = testRoute + } + + var advertErr error + + errChan := make(chan error) + + var wg sync.WaitGroup + wg.Add(1) + go func() { + wg.Done() + for _, route := range routes { + log.Debugf("Creating route %v", route) + if err := r.Table().Create(route); err != nil { + log.Debugf("Failed to create route: %v", err) + errChan <- err + return + } + } + }() + + var adverts int + doneChan := make(chan bool) + + wg.Add(1) + go func() { + defer func() { + wg.Done() + doneChan <- true + }() + for advert := range ch { + select { + case advertErr = <-errChan: + t.Errorf("failed advertising events: %v", advertErr) + default: + // do nothing for now + log.Debugf("Router advert received: %v", advert) + adverts += len(advert.Events) + } + return + } + }() + + <-doneChan + + if adverts != nrRoutes { + t.Errorf("Expected %d adverts, received: %d", nrRoutes, adverts) + } + + wg.Wait() + + if err := r.Stop(); err != nil { + t.Errorf("failed to stop router: %v", err) + } +} diff --git a/router/table_test.go b/router/table_test.go index b37de1cb..50966f99 100644 --- a/router/table_test.go +++ b/router/table_test.go @@ -7,6 +7,7 @@ func testSetup() (*table, Route) { route := Route{ Service: "dest.svc", + Address: "dest.addr", Gateway: "dest.gw", Network: "dest.network", Router: "src.router", From 254045e9f389e30d85d85ebbfa7739407b2758e8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 6 Nov 2019 15:49:40 +0000 Subject: [PATCH 180/344] Remove go routines for mdns watcher and cache registry (#919) --- registry/cache/cache.go | 44 +++++++++++++----- registry/mdns_registry.go | 95 ++++++++++++++++++++++++++++++++++++--- registry/mdns_watcher.go | 7 +++ 3 files changed, 128 insertions(+), 18 deletions(-) diff --git a/registry/cache/cache.go b/registry/cache/cache.go index f8bee4a9..75fcac32 100644 --- a/registry/cache/cache.go +++ b/registry/cache/cache.go @@ -39,6 +39,8 @@ type cache struct { // used to stop the cache exit chan bool + // indicate whether its running + running bool // status of the registry // used to hold onto the cache // in failure state @@ -157,13 +159,26 @@ func (c *cache) get(service string) ([]*registry.Service, error) { } // watch service if not watched - if _, ok := c.watched[service]; !ok { - go c.run(service) - } + _, ok := c.watched[service] // unlock the read lock c.RUnlock() + // check if its being watched + if !ok { + c.Lock() + + // set to watched + c.watched[service] = true + + // only kick it off if not running + if !c.running { + go c.run() + } + + c.Unlock() + } + // get and return services return get(service, cp) } @@ -181,6 +196,11 @@ func (c *cache) update(res *registry.Result) { c.Lock() defer c.Unlock() + // only save watched services + if _, ok := c.watched[res.Service.Name]; !ok { + return + } + services, ok := c.cache[res.Service.Name] if !ok { // we're not going to cache anything @@ -283,16 +303,16 @@ func (c *cache) update(res *registry.Result) { // run starts the cache watcher loop // it creates a new watcher if there's a problem -func (c *cache) run(service string) { - // set watcher +func (c *cache) run() { c.Lock() - c.watched[service] = true + c.running = true c.Unlock() - // delete watcher on exit + // reset watcher on exit defer func() { c.Lock() - delete(c.watched, service) + c.watched = make(map[string]bool) + c.running = false c.Unlock() }() @@ -309,10 +329,7 @@ func (c *cache) run(service string) { time.Sleep(time.Duration(j) * time.Millisecond) // create new watcher - w, err := c.Registry.Watch( - registry.WatchService(service), - ) - + w, err := c.Registry.Watch() if err != nil { if c.quit() { return @@ -414,6 +431,9 @@ func (c *cache) GetService(service string) ([]*registry.Service, error) { } func (c *cache) Stop() { + c.Lock() + defer c.Unlock() + select { case <-c.exit: return diff --git a/registry/mdns_registry.go b/registry/mdns_registry.go index 646032ad..5f0dc073 100644 --- a/registry/mdns_registry.go +++ b/registry/mdns_registry.go @@ -10,6 +10,7 @@ import ( "sync" "time" + "github.com/google/uuid" "github.com/micro/mdns" ) @@ -37,6 +38,14 @@ type mdnsRegistry struct { sync.Mutex services map[string][]*mdnsEntry + + mtx sync.RWMutex + + // watchers + watchers map[string]*mdnsWatcher + + // listener + listener chan *mdns.ServiceEntry } func newRegistry(opts ...Option) Registry { @@ -61,6 +70,7 @@ func newRegistry(opts ...Option) Registry { opts: options, domain: domain, services: make(map[string][]*mdnsEntry), + watchers: make(map[string]*mdnsWatcher), } } @@ -346,15 +356,88 @@ func (m *mdnsRegistry) Watch(opts ...WatchOption) (Watcher, error) { } md := &mdnsWatcher{ - wo: wo, - ch: make(chan *mdns.ServiceEntry, 32), - exit: make(chan struct{}), - domain: m.domain, + id: uuid.New().String(), + wo: wo, + ch: make(chan *mdns.ServiceEntry, 32), + exit: make(chan struct{}), + domain: m.domain, + registry: m, } + m.mtx.Lock() + defer m.mtx.Unlock() + + // save the watcher + m.watchers[md.id] = md + + // check of the listener exists + if m.listener != nil { + return md, nil + } + + // start the listener go func() { - if err := mdns.Listen(md.ch, md.exit); err != nil { - md.Stop() + // go to infinity + for { + m.mtx.Lock() + + // just return if there are no watchers + if len(m.watchers) == 0 { + m.listener = nil + m.mtx.Unlock() + return + } + + // check existing listener + if m.listener != nil { + m.mtx.Unlock() + return + } + + // reset the listener + exit := make(chan struct{}) + ch := make(chan *mdns.ServiceEntry, 32) + m.listener = ch + + m.mtx.Unlock() + + // send messages to the watchers + go func() { + send := func(w *mdnsWatcher, e *mdns.ServiceEntry) { + select { + case w.ch <- e: + default: + } + } + + for { + select { + case <-exit: + return + case e, ok := <-ch: + if !ok { + return + } + m.mtx.RLock() + // send service entry to all watchers + for _, w := range m.watchers { + send(w, e) + } + m.mtx.RUnlock() + } + } + + }() + + // start listening, blocking call + mdns.Listen(ch, exit) + + // mdns.Listen has unblocked + // kill the saved listener + m.mtx.Lock() + m.listener = nil + close(ch) + m.mtx.Unlock() } }() diff --git a/registry/mdns_watcher.go b/registry/mdns_watcher.go index ce13866f..402811b9 100644 --- a/registry/mdns_watcher.go +++ b/registry/mdns_watcher.go @@ -8,11 +8,14 @@ import ( ) type mdnsWatcher struct { + id string wo WatchOptions ch chan *mdns.ServiceEntry exit chan struct{} // the mdns domain domain string + // the registry + registry *mdnsRegistry } func (m *mdnsWatcher) Next() (*Result, error) { @@ -76,5 +79,9 @@ func (m *mdnsWatcher) Stop() { return default: close(m.exit) + // remove self from the registry + m.registry.mtx.Lock() + delete(m.registry.watchers, m.id) + m.registry.mtx.Unlock() } } From ce080d76c643c592f4f5ac7e06df62a979a8f2dc Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 6 Nov 2019 19:36:04 +0000 Subject: [PATCH 181/344] add debug/profile package (#920) * add debug/profile package * set service+version for profile --- config/cmd/cmd.go | 17 +++-- debug/profile/pprof/pprof.go | 118 +++++++++++++++++++++++++++++++++++ debug/profile/profile.go | 23 +++++++ service.go | 16 +++++ 4 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 debug/profile/pprof/pprof.go create mode 100644 debug/profile/profile.go diff --git a/config/cmd/cmd.go b/config/cmd/cmd.go index e66836c1..18f12528 100644 --- a/config/cmd/cmd.go +++ b/config/cmd/cmd.go @@ -71,12 +71,6 @@ var ( DefaultCmd = newCmd() DefaultFlags = []cli.Flag{ - cli.StringFlag{ - Name: "runtime", - Usage: "Micro runtime", - EnvVar: "MICRO_RUNTIME", - Value: "local", - }, cli.StringFlag{ Name: "client", EnvVar: "MICRO_CLIENT", @@ -161,6 +155,11 @@ var ( EnvVar: "MICRO_BROKER_ADDRESS", Usage: "Comma-separated list of broker addresses", }, + cli.StringFlag{ + Name: "profile", + Usage: "Debug profiler for cpu and memory stats", + EnvVar: "MICRO_DEBUG_PROFILE", + }, cli.StringFlag{ Name: "registry", EnvVar: "MICRO_REGISTRY", @@ -171,6 +170,12 @@ var ( EnvVar: "MICRO_REGISTRY_ADDRESS", Usage: "Comma-separated list of registry addresses", }, + cli.StringFlag{ + Name: "runtime", + Usage: "Runtime for building and running services e.g local, kubernetes", + EnvVar: "MICRO_RUNTIME", + Value: "local", + }, cli.StringFlag{ Name: "selector", EnvVar: "MICRO_SELECTOR", diff --git a/debug/profile/pprof/pprof.go b/debug/profile/pprof/pprof.go new file mode 100644 index 00000000..b1f126d9 --- /dev/null +++ b/debug/profile/pprof/pprof.go @@ -0,0 +1,118 @@ +// Package pprof provides a pprof profiler +package pprof + +import ( + "os" + "path/filepath" + "runtime" + "runtime/pprof" + "sync" + "time" + + "github.com/micro/go-micro/debug/profile" +) + +type profiler struct { + opts profile.Options + + sync.Mutex + running bool + exit chan bool + + // where the cpu profile is written + cpuFile *os.File + // where the mem profile is written + memFile *os.File +} + +func (p *profiler) writeHeap(f *os.File) { + defer f.Close() + + t := time.NewTicker(time.Second * 30) + defer t.Stop() + + for { + select { + case <-t.C: + runtime.GC() + pprof.WriteHeapProfile(f) + case <-p.exit: + return + } + } +} + +func (p *profiler) Start() error { + p.Lock() + defer p.Unlock() + + if p.running { + return nil + } + + // create exit channel + p.exit = make(chan bool) + + cpuFile := filepath.Join("/tmp", "cpu.pprof") + memFile := filepath.Join("/tmp", "mem.pprof") + + if len(p.opts.Name) > 0 { + cpuFile = filepath.Join("/tmp", p.opts.Name+".cpu.pprof") + memFile = filepath.Join("/tmp", p.opts.Name+".mem.pprof") + } + + f1, err := os.Create(cpuFile) + if err != nil { + return err + } + + f2, err := os.Create(memFile) + if err != nil { + return err + } + + // start cpu profiling + if err := pprof.StartCPUProfile(f1); err != nil { + return err + } + + // write the heap periodically + go p.writeHeap(f2) + + // set cpu file + p.cpuFile = f1 + // set mem file + p.memFile = f2 + + p.running = true + + return nil +} + +func (p *profiler) Stop() error { + p.Lock() + defer p.Unlock() + + select { + case <-p.exit: + return nil + default: + close(p.exit) + pprof.StopCPUProfile() + p.cpuFile.Close() + p.running = false + p.cpuFile = nil + p.memFile = nil + return nil + } +} + +func NewProfile(opts ...profile.Option) profile.Profile { + var options profile.Options + for _, o := range opts { + o(&options) + } + p := new(profiler) + p.opts = options + return p +} diff --git a/debug/profile/profile.go b/debug/profile/profile.go new file mode 100644 index 00000000..2dbe1e13 --- /dev/null +++ b/debug/profile/profile.go @@ -0,0 +1,23 @@ +// Package profile is for profilers +package profile + +type Profile interface { + // Start the profiler + Start() error + // Stop the profiler + Stop() error +} + +type Options struct { + // Name to use for the profile + Name string +} + +type Option func(o *Options) + +// Name of the profile +func Name(n string) Option { + return func(o *Options) { + o.Name = n + } +} diff --git a/service.go b/service.go index a0f9817c..4073ff8d 100644 --- a/service.go +++ b/service.go @@ -10,6 +10,8 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/config/cmd" "github.com/micro/go-micro/debug/handler" + "github.com/micro/go-micro/debug/profile" + "github.com/micro/go-micro/debug/profile/pprof" "github.com/micro/go-micro/metadata" "github.com/micro/go-micro/plugin" "github.com/micro/go-micro/server" @@ -147,6 +149,20 @@ func (s *service) Run() error { ), ) + // start the profiler + // TODO: set as an option to the service, don't just use pprof + if prof := os.Getenv("MICRO_DEBUG_PROFILE"); len(prof) > 0 { + service := s.opts.Server.Options().Name + version := s.opts.Server.Options().Version + profiler := pprof.NewProfile( + profile.Name(service + "." + version), + ) + if err := profiler.Start(); err != nil { + return err + } + defer profiler.Stop() + } + if err := s.Start(); err != nil { return err } From f9400ba7136b82d0c7fe4dcbd1bfdc334f63aab8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 6 Nov 2019 22:03:35 +0000 Subject: [PATCH 182/344] update readme --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 1c689389..2e6b2723 100644 --- a/README.md +++ b/README.md @@ -20,8 +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. 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. +multicast DNS (mdns), a zeroconf system. You can optionally set the use of etcd 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 0e3550229bbdbf0917086fea08bc660a73c7eacb Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 6 Nov 2019 22:04:02 +0000 Subject: [PATCH 183/344] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e6b2723..61239ba2 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. The default discovery mechanism is -multicast DNS (mdns), a zeroconf system. You can optionally set the use of etcd for a resilient cloud-native setup. +multicast DNS (mdns), a zeroconf system. - **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 6f28852e1bb25b56780f5ece9544a37a93444db9 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 7 Nov 2019 07:44:57 +0000 Subject: [PATCH 184/344] K8s list deployments (#921) * Outline of ListDeployments method * Added implementation of DeploymentList --- runtime/kubernetes/client/api/request.go | 2 +- runtime/kubernetes/client/client.go | 15 +++++++- runtime/kubernetes/client/kubernetes.go | 21 ++++++++++ runtime/kubernetes/kubernetes.go | 49 ++++++++++++++++++------ 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/runtime/kubernetes/client/api/request.go b/runtime/kubernetes/client/api/request.go index b40ed72a..20158806 100644 --- a/runtime/kubernetes/client/api/request.go +++ b/runtime/kubernetes/client/api/request.go @@ -103,7 +103,7 @@ func (r *Request) Body(in interface{}) *Request { // Params isused to set paramters on a request func (r *Request) Params(p *Params) *Request { for k, v := range p.LabelSelector { - r.params.Add("labelSelectors", k+"="+v) + r.params.Add("labelSelector", k+"="+v) } return r diff --git a/runtime/kubernetes/client/client.go b/runtime/kubernetes/client/client.go index 695ecd65..d201604e 100644 --- a/runtime/kubernetes/client/client.go +++ b/runtime/kubernetes/client/client.go @@ -90,7 +90,7 @@ func detectNamespace() (string, error) { } } -// UpdateDeployment +// UpdateDeployment patches kubernetes deployment with metadata provided in body func (c *client) UpdateDeployment(name string, body interface{}) error { return api.NewRequest(c.opts). Patch(). @@ -100,3 +100,16 @@ func (c *client) UpdateDeployment(name string, body interface{}) error { Do(). Error() } + +// ListDeployments lists all kubernetes deployments with given labels +func (c *client) ListDeployments(labels map[string]string) (*DeploymentList, error) { + var deployments DeploymentList + err := api.NewRequest(c.opts). + Get(). + Resource("deployments"). + Params(&api.Params{LabelSelector: labels}). + Do(). + Into(&deployments) + + return &deployments, err +} diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index 565d2243..82a626f2 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -4,9 +4,30 @@ package client type Kubernetes interface { // UpdateDeployment patches deployment annotations with new metadata UpdateDeployment(string, interface{}) error + // ListDeployments lists all micro deployments + ListDeployments(labels map[string]string) (*DeploymentList, error) } // Metadata defines api request metadata type Metadata struct { + Name string `json:"name,omitempty"` + Labels map[string]string `json:"labels,omitempty"` Annotations map[string]string `json:"annotations,omitempty"` } + +// DeploymentList +type DeploymentList struct { + Items []Deployment `json:"items"` +} + +// Deployment is Kubernetes deployment +type Deployment struct { + Metadata *Metadata `json:"metadata"` + Status *Status `json:"status"` +} + +// Status is Kubernetes deployment status +type Status struct { + Replicas int `json:"replicas"` + AvailableReplicas int `json:"availablereplicas"` +} diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 15f0fcb1..99cc9437 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -137,14 +137,31 @@ func (k *kubernetes) Update(s *runtime.Service) error { // List the managed services func (k *kubernetes) List() ([]*runtime.Service, error) { - // TODO: this should list the k8s deployments - // but for now we return in-memory tracked services - services := make([]*runtime.Service, 0, len(k.services)) - k.RLock() - defer k.RUnlock() + labels := map[string]string{ + "micro": "service", + } + // list all micro core deployments + deployments, err := k.client.ListDeployments(labels) + if err != nil { + return nil, err + } - for _, service := range k.services { - services = append(services, service) + log.Debugf("Runtime found %d micro deployments with labels %v", len(deployments.Items), labels) + + services := make([]*runtime.Service, 0, len(deployments.Items)) + + for _, service := range deployments.Items { + buildTime, err := time.Parse(time.RFC3339, service.Metadata.Annotations["build"]) + if err != nil { + log.Debugf("Runtime error parsing build time: %v", err) + continue + } + // add the service to the list of services + svc := &runtime.Service{ + Name: service.Metadata.Name, + Version: fmt.Sprintf("%d", buildTime.Unix()), + } + services = append(services, svc) } return services, nil @@ -152,18 +169,26 @@ func (k *kubernetes) List() ([]*runtime.Service, error) { // run runs the runtime management loop func (k *kubernetes) run(events <-chan runtime.Event) { - t := time.NewTicker(time.Second * 5) + t := time.NewTicker(time.Second * 10) defer t.Stop() for { select { case <-t.C: - // TODO: noop for now // check running services - // * deployments exist - // * service is exposed + services, err := k.List() + if err != nil { + log.Debugf("Runtime failed listing running services: %v", err) + continue + } + // TODO: for now we just log the running services + // * make sure all core deployments exist + // * make sure all core services are exposed + for _, service := range services { + log.Debugf("Runtime found running service: %v", service) + } case service := <-k.start: - // TODO: following might have to be done + // TODO: this is a noop for now // * create a deployment // * expose a service log.Debugf("Runtime starting service: %s", service.Name) From 82272062082e880f08e9589039723cdb93013613 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Fri, 8 Nov 2019 12:11:55 +0300 Subject: [PATCH 185/344] use service id in profile file name (#925) Signed-off-by: Vasiliy Tolstov --- service.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service.go b/service.go index 4073ff8d..f2d9fea8 100644 --- a/service.go +++ b/service.go @@ -154,8 +154,9 @@ func (s *service) Run() error { if prof := os.Getenv("MICRO_DEBUG_PROFILE"); len(prof) > 0 { service := s.opts.Server.Options().Name version := s.opts.Server.Options().Version + id := s.opts.Server.Options().Id profiler := pprof.NewProfile( - profile.Name(service + "." + version), + profile.Name(service + "." + version + "." + id), ) if err := profiler.Start(); err != nil { return err From 68419cc0247b9110099245b086954ffc33e0067c Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 8 Nov 2019 14:12:03 +0000 Subject: [PATCH 186/344] Patch deployment spec metadata (#928) --- runtime/kubernetes/client/kubernetes.go | 10 ++++++++++ runtime/kubernetes/kubernetes.go | 12 ++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index 82a626f2..afed5ec2 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -8,6 +8,16 @@ type Kubernetes interface { ListDeployments(labels map[string]string) (*DeploymentList, error) } +// Template is micro deployment template +type Template struct { + Metadata *Metadata `json:"metadata,omitempty"` +} + +// Spec defines micro deployment spec +type Spec struct { + Template *Template `json:"template,omitempty"` +} + // Metadata defines api request metadata type Metadata struct { Name string `json:"name,omitempty"` diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 99cc9437..e77ec243 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -116,7 +116,7 @@ func (k *kubernetes) Delete(s *runtime.Service) error { // Update the service in place func (k *kubernetes) Update(s *runtime.Service) error { type body struct { - Metadata *client.Metadata `json:"metadata"` + Spec *client.Spec `json:"spec"` } // parse version into human readable timestamp updateTimeStamp, err := strconv.ParseInt(s.Version, 10, 64) @@ -126,9 +126,13 @@ func (k *kubernetes) Update(s *runtime.Service) error { unixTimeUTC := time.Unix(updateTimeStamp, 0) // metada which we will PATCH deployment with reqBody := body{ - Metadata: &client.Metadata{ - Annotations: map[string]string{ - "build": unixTimeUTC.Format(time.RFC3339), + Spec: &client.Spec{ + Template: &client.Template{ + Metadata: &client.Metadata{ + Annotations: map[string]string{ + "build": unixTimeUTC.Format(time.RFC3339), + }, + }, }, }, } From 1ffa289d391066f9ee14ba239ad39584e9a83c07 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 8 Nov 2019 15:57:07 +0000 Subject: [PATCH 187/344] Make build timestamp parsing errors clearer (#929) --- runtime/default.go | 2 +- runtime/kubernetes/kubernetes.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/default.go b/runtime/default.go index 1785c2f5..832558f5 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -93,7 +93,7 @@ func (r *runtime) run(events <-chan Event) { // parse returned response to timestamp updateTimeStamp, err := strconv.ParseInt(event.Version, 10, 64) if err != nil { - log.Debugf("Runtime error parsing update build time: %v", err) + log.Debugf("Runtime error parsing build time for %s: %v", event.Service, err) continue } buildTime := time.Unix(updateTimeStamp, 0) diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index e77ec243..27369ac9 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -157,7 +157,7 @@ func (k *kubernetes) List() ([]*runtime.Service, error) { for _, service := range deployments.Items { buildTime, err := time.Parse(time.RFC3339, service.Metadata.Annotations["build"]) if err != nil { - log.Debugf("Runtime error parsing build time: %v", err) + log.Debugf("Runtime error parsing build time for %s: %v", service.Metadata.Name, err) continue } // add the service to the list of services From 0b1e6d7eaf4ab3f906b58f290d64a00599e9dc8b Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 8 Nov 2019 15:57:32 +0000 Subject: [PATCH 188/344] Simplified k8s API Body watcher code and test. (#923) --- runtime/kubernetes/client/watch/body.go | 50 ++++++------------- runtime/kubernetes/client/watch/watch_test.go | 6 +-- 2 files changed, 18 insertions(+), 38 deletions(-) diff --git a/runtime/kubernetes/client/watch/body.go b/runtime/kubernetes/client/watch/body.go index 5f939655..3eaa6d43 100644 --- a/runtime/kubernetes/client/watch/body.go +++ b/runtime/kubernetes/client/watch/body.go @@ -4,7 +4,6 @@ import ( "bufio" "encoding/json" "net/http" - "time" ) // bodyWatcher scans the body of a request for chunks @@ -34,43 +33,26 @@ func (wr *bodyWatcher) Stop() { func (wr *bodyWatcher) stream() { reader := bufio.NewReader(wr.res.Body) - // ignore first few messages from stream, - // as they are usually old. - ignore := true + // stop the watcher + defer wr.Stop() - go func() { - <-time.After(time.Second) - ignore = false - }() - - go func() { - // stop the watcher - defer wr.Stop() - - for { - // read a line - b, err := reader.ReadBytes('\n') - if err != nil { - return - } - - // ignore for the first second - if ignore { - continue - } - - // send the event - var event Event - if err := json.Unmarshal(b, &event); err != nil { - continue - } - wr.results <- event + for { + // read a line + b, err := reader.ReadBytes('\n') + if err != nil { + return } - }() + + // send the event + var event Event + if err := json.Unmarshal(b, &event); err != nil { + continue + } + wr.results <- event + } } -// NewBodyWatcher creates a k8s body watcher for -// a given http request +// NewBodyWatcher creates a k8s body watcher for a given http request func NewBodyWatcher(req *http.Request, client *http.Client) (Watch, error) { stop := make(chan struct{}) req.Cancel = stop diff --git a/runtime/kubernetes/client/watch/watch_test.go b/runtime/kubernetes/client/watch/watch_test.go index d34918c4..ac34141c 100644 --- a/runtime/kubernetes/client/watch/watch_test.go +++ b/runtime/kubernetes/client/watch/watch_test.go @@ -37,17 +37,15 @@ func TestBodyWatcher(t *testing.T) { req, err := http.NewRequest("GET", ts.URL, nil) if err != nil { - t.Fatalf("did not expect NewRequest to return err: %v", err) + t.Fatalf("failed to create new request: %v", err) } // setup body watcher w, err := NewBodyWatcher(req, http.DefaultClient) if err != nil { - t.Fatalf("did not expect NewBodyWatcher to return %v", err) + t.Fatalf("failed to create new BodyWatcher %v", err) } - <-time.After(time.Second) - // send action strings in, and expect result back ch <- actions[0] if r := <-w.ResultChan(); r.Type != "create" { From a9e8fc60391ea6451ae89c266bf8edaa66b7f536 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 9 Nov 2019 10:32:52 +0000 Subject: [PATCH 189/344] Don't set stream unless its true --- server/extractor.go | 14 ++++++++++---- server/grpc/extractor.go | 13 +++++++++---- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/server/extractor.go b/server/extractor.go index 52ce0056..5cbddd77 100644 --- a/server/extractor.go +++ b/server/extractor.go @@ -95,14 +95,20 @@ func extractEndpoint(method reflect.Method) *registry.Endpoint { request := extractValue(reqType, 0) response := extractValue(rspType, 0) - return ®istry.Endpoint{ + ep := ®istry.Endpoint{ Name: method.Name, Request: request, Response: response, - Metadata: map[string]string{ - "stream": fmt.Sprintf("%v", stream), - }, } + + // set endpoint metadata for stream + if stream { + ep.Metadata = map[string]string{ + "stream": fmt.Sprintf("%v", stream), + } + } + + return ep } func extractSubValue(typ reflect.Type) *registry.Value { diff --git a/server/grpc/extractor.go b/server/grpc/extractor.go index 753cc175..8b3ed4f6 100644 --- a/server/grpc/extractor.go +++ b/server/grpc/extractor.go @@ -90,14 +90,19 @@ func extractEndpoint(method reflect.Method) *registry.Endpoint { request := extractValue(reqType, 0) response := extractValue(rspType, 0) - return ®istry.Endpoint{ + ep := ®istry.Endpoint{ Name: method.Name, Request: request, Response: response, - Metadata: map[string]string{ - "stream": fmt.Sprintf("%v", stream), - }, } + + if stream { + ep.Metadata = map[string]string{ + "stream": fmt.Sprintf("%v", stream), + } + } + + return ep } func extractSubValue(typ reflect.Type) *registry.Value { From 5aa28dfb0d4e586271105416b12a8ae842dde285 Mon Sep 17 00:00:00 2001 From: Lars Lehtonen Date: Sat, 9 Nov 2019 07:18:51 -0800 Subject: [PATCH 190/344] store/cloudflare: fix dropped error (#930) --- store/cloudflare/cloudflare.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index d0fa6925..24ca69f0 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -252,6 +252,10 @@ func (w *workersKV) request(ctx context.Context, method, path string, body inter } req, err := http.NewRequestWithContext(ctx, method, apiBaseURL+path, reqBody) + if err != nil { + return nil, nil, 0, errors.Wrap(err, "error creating new request") + } + for key, value := range headers { req.Header[key] = value } From 929ffdcc42e953763d0b19388119e0f99bd24a19 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 9 Nov 2019 15:37:30 +0000 Subject: [PATCH 191/344] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 61239ba2..eaff0d85 100644 --- a/README.md +++ b/README.md @@ -44,5 +44,5 @@ are pluggable and allows Go Micro to be runtime agnostic. You can plugin any und ## Getting Started -See the [docs](https://micro.mu/docs/go-micro.html) for detailed information on the architecture, installation and use of go-micro. +See the [docs](https://micro.mu/docs/framework.html) for detailed information on the architecture, installation and use of go-micro. From c433de80cde0145b146c9aadc4db53ad1459dd61 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 9 Nov 2019 15:44:52 +0000 Subject: [PATCH 192/344] Update go mod --- go.mod | 40 ++++------- go.sum | 207 ++++++++++++++++++++++++++------------------------------- 2 files changed, 105 insertions(+), 142 deletions(-) diff --git a/go.mod b/go.mod index 12808717..41b82b77 100644 --- a/go.mod +++ b/go.mod @@ -6,58 +6,42 @@ require ( github.com/BurntSushi/toml v0.3.1 github.com/beevik/ntp v0.2.0 github.com/bitly/go-simplejson v0.5.0 - github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect - github.com/bwmarrin/discordgo v0.19.0 - github.com/coreos/bbolt v1.3.3 // indirect + github.com/bwmarrin/discordgo v0.20.1 github.com/coreos/etcd v3.3.17+incompatible - github.com/coreos/go-semver v0.3.0 // indirect - github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c github.com/fsnotify/fsnotify v1.4.7 - github.com/fsouza/go-dockerclient v1.4.4 + github.com/fsouza/go-dockerclient v1.6.0 github.com/ghodss/yaml v1.0.0 github.com/go-acme/lego/v3 v3.1.0 github.com/go-log/log v0.1.0 - github.com/go-playground/locales v0.12.1 // indirect + github.com/go-playground/locales v0.13.0 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect - github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect - github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc // indirect github.com/golang/protobuf v1.3.2 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/websocket v1.4.1 - github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 github.com/imdario/mergo v0.3.8 - github.com/jonboulle/clockwork v0.1.0 // indirect github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 - github.com/json-iterator/go v1.1.7 + github.com/json-iterator/go v1.1.8 github.com/kr/pretty v0.1.0 - github.com/leodido/go-urn v1.1.0 // indirect + github.com/leodido/go-urn v1.2.0 // indirect github.com/lib/pq v1.2.0 - github.com/lucas-clemente/quic-go v0.12.1 - github.com/mholt/certmagic v0.7.5 + github.com/lucas-clemente/quic-go v0.13.1 + github.com/mholt/certmagic v0.8.3 github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 github.com/mitchellh/hashstructure v1.0.0 - github.com/nats-io/nats-server/v2 v2.1.0 // indirect - github.com/nats-io/nats.go v1.8.1 + github.com/nats-io/nats.go v1.9.1 github.com/nlopes/slack v0.6.0 github.com/pkg/errors v0.8.1 - github.com/soheilhy/cmux v0.1.4 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect - github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect - github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect - go.etcd.io/bbolt v1.3.3 // indirect - go.uber.org/multierr v1.2.0 // indirect - golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 - golang.org/x/net v0.0.0-20191011234655-491137f69257 - google.golang.org/grpc v1.24.0 - gopkg.in/go-playground/assert.v1 v1.2.1 // indirect + go.uber.org/zap v1.12.0 // indirect + golang.org/x/crypto v0.0.0-20191108234033-bd318be0434a + golang.org/x/net v0.0.0-20191109021931-daa7c04131f5 + google.golang.org/grpc v1.25.1 gopkg.in/go-playground/validator.v9 v9.30.0 gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/telegram-bot-api.v4 v4.6.4 - sigs.k8s.io/yaml v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index fd44a28e..0ca438cd 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= github.com/Azure/azure-sdk-for-go v32.4.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/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw= @@ -19,24 +18,20 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c/go.mod h1:7xhjOwRV2+0HXGmM0jxaEu+ZiXJFoVZOTfL/dmqbrD8= github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= 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/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= +github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= 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-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= @@ -44,50 +39,52 @@ github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -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/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY= -github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bwmarrin/discordgo v0.20.1 h1:Ihh3/mVoRwy3otmaoPDUioILBJq4fdWkpsi83oj2Lmk= +github.com/bwmarrin/discordgo v0.20.1/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.10.2 h1:VBodKICVPnwmDxstcW3biKcDSpFIfS/RELUXsZSBYK4= github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= -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/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= -github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0 h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/coreos/etcd v3.3.17+incompatible h1:f/Z3EoDSx1yjaIjLQGo1diYUlQYSBrrAQ5vP8NjwXwo= github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/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/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= -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/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/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b h1:+Ga+YpCDpcY1fln6GI0fiiirpqHGcob5/Vk3oKNuGdU= -github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23 h1:oqgGT9O61YAYvI41EBsLePOr+LE6roB0xY4gpkZuFSE= +github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23/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.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= @@ -97,20 +94,21 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c h1:pBgVXWDXju1m8W4lnEeIqTHPOzhTUO81a7yknM/xQR4= github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY= 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/fsouza/go-dockerclient v1.4.4 h1:Sd5nD4wdAgiPxvrbYUzT2ZZNmPk3z+GGnZ+frvw8z04= -github.com/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA= +github.com/fsouza/go-dockerclient v1.6.0 h1:f7j+AX94143JL1H3TiqSMkM4EcLDI0De1qD4GGn3Hig= +github.com/fsouza/go-dockerclient v1.6.0/go.mod h1:YWwtNPuL4XTX1SKJQk86cWPmmqwx+4np9qfPbb+znGc= 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.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-acme/lego v2.7.2+incompatible h1:ThhpPBgf6oa9X/vRd0kEmWOsX7+vmYdckmGZSb+FEp0= github.com/go-acme/lego/v3 v3.1.0 h1:yanYFoYW8azFkCvJfIk7edWWfjkYkhDxe45ZsxoW4Xk= github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= @@ -121,25 +119,20 @@ 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-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= -github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 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/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-20191002201903-404acd9df4cc h1:55rEp52jU6bkyslZ1+C/7NGfpQsEc6pxGLAGDOctqbw= -github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= @@ -147,16 +140,15 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 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/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -172,38 +164,30 @@ github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= -github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= -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.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= -github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM= -github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -215,7 +199,6 @@ github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= 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= @@ -226,25 +209,26 @@ 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/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= -github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= -github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= -github.com/lucas-clemente/quic-go v0.12.1 h1:BPITli+6KnKogtTxBk2aS4okr5dUHz2LtIDAP1b8UL4= -github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= +github.com/lucas-clemente/quic-go v0.13.1 h1:CxtJTXQIh2aboCPk0M6vf530XOov6DZjVBiSE3nSj8s= +github.com/lucas-clemente/quic-go v0.13.1/go.mod h1:Vn3/Fb0/77b02SGhQk36KzOUmXgVpFfizUfW5WMaqyU= +github.com/marten-seemann/chacha20 v0.2.0 h1:f40vqzzx+3GdOmzQoItkLX5WLvHgPgyYqFFIO5Gh4hQ= +github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1HFkWoEwNDb4TMtE= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= -github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI= -github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= +github.com/marten-seemann/qtls v0.4.1 h1:YlT8QP3WCCvvok7MGEZkMldXbyqgr8oFg5/n8Gtbkks= +github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= -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/certmagic v0.7.5 h1:1ZGHwUI4+zg1S17tPUj5Xxb9Q1ghTjLcUZE5G4yV5SM= -github.com/mholt/certmagic v0.7.5/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= +github.com/mholt/certmagic v0.8.3 h1:JOUiX9IAZbbgyjNP2GY6v/6lorH+9GkZsc7ktMpGCSo= +github.com/mholt/certmagic v0.8.3/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= github.com/micro/cli v0.2.0 h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA= github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= @@ -257,7 +241,6 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= 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/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -265,16 +248,14 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ 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/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= +github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/nats-server/v2 v2.1.0 h1:Yi0+ZhRPtPAGeIxFn5erIeJIV9wXA+JznfSxK621Fbk= -github.com/nats-io/nats-server/v2 v2.1.0/go.mod h1:r5y0WgCag0dTj/qiHkHrXAcKQ/f5GMOZaEGdoxxnJ4I= -github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ= -github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= -github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M= -github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= +github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -287,17 +268,18 @@ github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2 github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 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.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 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.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= 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.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= @@ -306,29 +288,27 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 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/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -342,8 +322,6 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -351,59 +329,58 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ 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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= -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/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -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.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4= -go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= -go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.12.0 h1:dySoUQPFBGj6xwjmBzageVL8jGi8uxc6bEmJQjA06bw= +go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191108234033-bd318be0434a h1:R/qVym5WAxsZWQqZCwDY/8sdVKV1m1WgU4/S5IRQAzc= +golang.org/x/crypto v0.0.0-20191108234033-bd318be0434a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 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= @@ -416,13 +393,14 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191011234655-491137f69257 h1:ry8e2D+cwaV6hk7lb3aRTjjZo24shrbK0e11QEOkTIg= -golang.org/x/net v0.0.0-20191011234655-491137f69257/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191109021931-daa7c04131f5 h1:bHNaocaoJxYBo5cw41UyTMLjYlb8wPY7+WFrnklbHOM= +golang.org/x/net v0.0.0-20191109021931-daa7c04131f5/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -443,15 +421,17 @@ golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190221075227-b4e8571b14e0/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-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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -470,7 +450,11 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -481,7 +465,7 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= @@ -490,16 +474,14 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= @@ -512,13 +494,11 @@ 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/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/telegram-bot-api.v4 v4.6.4 h1:hpHWhzn4jTCsAJZZ2loNKfy2QWyPDRJVl3aTFXeMW8g= gopkg.in/telegram-bot-api.v4 v4.6.4/go.mod h1:5DpGO5dbumb40px+dXcwCpcjmeHNYLpk0bp3XRNvWDM= -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/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= @@ -526,12 +506,11 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl 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= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/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-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= From 174b01ca2954fce2a14614c057d0a3096c539392 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 9 Nov 2019 16:20:54 +0000 Subject: [PATCH 193/344] update link in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eaff0d85..02763aa7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ 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. +Follow us on [Twitter](https://twitter.com/microhq) or join the [Slack](https://micro.mu/slack) community. ## Features From c696a859be5c28a14196f2a62d3c0a9a01b98d5e Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Sun, 10 Nov 2019 00:52:41 +0300 Subject: [PATCH 194/344] fix data race for server Wait option (#931) Signed-off-by: Vasiliy Tolstov --- server/rpc_server.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/server/rpc_server.go b/server/rpc_server.go index 9e4828c6..850fd97b 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -112,8 +112,12 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { wg.Add(1) // add to wait group if "wait" is opt-in - if s.wg != nil { - s.wg.Add(1) + s.Lock() + swg := s.wg + s.Unlock() + + if swg != nil { + swg.Add(1) } // check we have an existing socket @@ -132,8 +136,8 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { } // done(1) - if s.wg != nil { - s.wg.Done() + if swg != nil { + swg.Done() } wg.Done() @@ -203,8 +207,8 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { Body: []byte(err.Error()), }) - if s.wg != nil { - s.wg.Done() + if swg != nil { + swg.Done() } wg.Done() @@ -324,8 +328,8 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { mtx.Unlock() // signal we're done - if s.wg != nil { - s.wg.Done() + if swg != nil { + swg.Done() } // done with this socket @@ -744,9 +748,13 @@ func (s *rpcServer) Start() error { log.Logf("Server %s-%s deregister error: %s", config.Name, config.Id, err) } + s.Lock() + swg := s.wg + s.Unlock() + // wait for requests to finish - if s.wg != nil { - s.wg.Wait() + if swg != nil { + swg.Wait() } // close transport listener From 5ae3e179b9c057b2d711f4485789d84c8c194e70 Mon Sep 17 00:00:00 2001 From: Till Knuesting Date: Mon, 11 Nov 2019 00:03:51 +0000 Subject: [PATCH 195/344] preallocated slices (#934) --- config/loader/memory/memory.go | 2 +- network/node.go | 2 +- network/resolver/dns/dns.go | 2 +- network/resolver/static/static.go | 2 +- registry/etcd/etcd.go | 4 ++-- registry/mdns_registry.go | 2 +- registry/memory/memory.go | 2 +- registry/service/util.go | 10 +++++----- router/handler/table.go | 4 ++-- server/grpc/grpc.go | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/config/loader/memory/memory.go b/config/loader/memory/memory.go index 6d5b27cb..62f1e0ae 100644 --- a/config/loader/memory/memory.go +++ b/config/loader/memory/memory.go @@ -153,7 +153,7 @@ func (m *memory) reload() error { } func (m *memory) update() { - var watchers []*watcher + watchers := make([]*watcher, 0, len(m.watchers)) m.RLock() for _, w := range m.watchers { diff --git a/network/node.go b/network/node.go index 167f5e43..f0d3809c 100644 --- a/network/node.go +++ b/network/node.go @@ -158,7 +158,7 @@ func (n *node) Nodes() []Node { visited := n.walk(untilNoMorePeers, justWalk) - var nodes []Node + nodes := make([]Node, 0, len(visited)) // collect all the nodes and return them for _, node := range visited { nodes = append(nodes, node) diff --git a/network/resolver/dns/dns.go b/network/resolver/dns/dns.go index 4cd99bf8..b4fa4fc5 100644 --- a/network/resolver/dns/dns.go +++ b/network/resolver/dns/dns.go @@ -27,7 +27,7 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { return nil, err } - var records []*resolver.Record + records := make([]*resolver.Record, 0, len(addrs)) for _, addr := range addrs { // join resolved record with port diff --git a/network/resolver/static/static.go b/network/resolver/static/static.go index 8157e4ea..485332c5 100644 --- a/network/resolver/static/static.go +++ b/network/resolver/static/static.go @@ -21,7 +21,7 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { }, nil } - var records []*resolver.Record + records := make([]*resolver.Record, 0, len(r.Nodes)) for _, node := range r.Nodes { records = append(records, &resolver.Record{ diff --git a/registry/etcd/etcd.go b/registry/etcd/etcd.go index ed4fec1c..182ddbf8 100644 --- a/registry/etcd/etcd.go +++ b/registry/etcd/etcd.go @@ -341,7 +341,7 @@ func (e *etcdRegistry) GetService(name string) ([]*registry.Service, error) { } } - var services []*registry.Service + services := make([]*registry.Service, 0, len(serviceMap)) for _, service := range serviceMap { services = append(services, service) } @@ -350,7 +350,6 @@ func (e *etcdRegistry) GetService(name string) ([]*registry.Service, error) { } func (e *etcdRegistry) ListServices() ([]*registry.Service, error) { - var services []*registry.Service versions := make(map[string]*registry.Service) ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) @@ -379,6 +378,7 @@ func (e *etcdRegistry) ListServices() ([]*registry.Service, error) { v.Nodes = append(v.Nodes, sn.Nodes...) } + services := make([]*registry.Service, 0, len(versions)) for _, service := range versions { services = append(services, service) } diff --git a/registry/mdns_registry.go b/registry/mdns_registry.go index 5f0dc073..6d1c75f7 100644 --- a/registry/mdns_registry.go +++ b/registry/mdns_registry.go @@ -292,7 +292,7 @@ func (m *mdnsRegistry) GetService(service string) ([]*Service, error) { <-done // create list and return - var services []*Service + services := make([]*Service, 0, len(serviceMap)) for _, service := range serviceMap { services = append(services, service) diff --git a/registry/memory/memory.go b/registry/memory/memory.go index eecb1284..f3b2e26e 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -111,7 +111,7 @@ func (m *Registry) ttlPrune() { } func (m *Registry) sendEvent(r *registry.Result) { - var watchers []*Watcher + watchers := make([]*Watcher, 0, len(m.Watchers)) m.RLock() for _, w := range m.Watchers { diff --git a/registry/service/util.go b/registry/service/util.go index 04519db3..ad74ce0c 100644 --- a/registry/service/util.go +++ b/registry/service/util.go @@ -10,7 +10,7 @@ func values(v []*registry.Value) []*pb.Value { return []*pb.Value{} } - var vs []*pb.Value + vs := make([]*pb.Value, 0, len(v)) for _, vi := range v { vs = append(vs, &pb.Value{ Name: vi.Name, @@ -26,7 +26,7 @@ func toValues(v []*pb.Value) []*registry.Value { return []*registry.Value{} } - var vs []*registry.Value + vs := make([]*registry.Value, 0, len(v)) for _, vi := range v { vs = append(vs, ®istry.Value{ Name: vi.Name, @@ -66,7 +66,7 @@ func ToProto(s *registry.Service) *pb.Service { }) } - var nodes []*pb.Node + nodes := make([]*pb.Node, 0, len(s.Nodes)) for _, node := range s.Nodes { nodes = append(nodes, &pb.Node{ @@ -86,7 +86,7 @@ func ToProto(s *registry.Service) *pb.Service { } func ToService(s *pb.Service) *registry.Service { - var endpoints []*registry.Endpoint + endpoints := make([]*registry.Endpoint, 0, len(s.Endpoints)) for _, ep := range s.Endpoints { var request, response *registry.Value @@ -114,7 +114,7 @@ func ToService(s *pb.Service) *registry.Service { }) } - var nodes []*registry.Node + nodes := make([]*registry.Node, 0, len(s.Nodes)) for _, node := range s.Nodes { nodes = append(nodes, ®istry.Node{ Id: node.Id, diff --git a/router/handler/table.go b/router/handler/table.go index bf972efb..42a824fe 100644 --- a/router/handler/table.go +++ b/router/handler/table.go @@ -70,7 +70,7 @@ func (t *Table) List(ctx context.Context, req *pb.Request, resp *pb.ListResponse return errors.InternalServerError("go.micro.router", "failed to list routes: %s", err) } - var respRoutes []*pb.Route + respRoutes := make([]*pb.Route, 0, len(routes)) for _, route := range routes { respRoute := &pb.Route{ Service: route.Service, @@ -95,7 +95,7 @@ func (t *Table) Query(ctx context.Context, req *pb.QueryRequest, resp *pb.QueryR return errors.InternalServerError("go.micro.router", "failed to lookup routes: %s", err) } - var respRoutes []*pb.Route + respRoutes := make([]*pb.Route, 0, len(routes)) for _, route := range routes { respRoute := &pb.Route{ Service: route.Service, diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index 9b66428e..ef613084 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -582,7 +582,7 @@ func (g *grpcServer) Register() error { return subscriberList[i].topic > subscriberList[j].topic }) - var endpoints []*registry.Endpoint + endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList)) for _, n := range handlerList { endpoints = append(endpoints, g.handlers[n].Endpoints()...) } From 5ffe367caee24245e731683fb91b2af0ebd1acdc Mon Sep 17 00:00:00 2001 From: "Huang.X" Date: Mon, 11 Nov 2019 15:57:14 +0800 Subject: [PATCH 196/344] fix# Change the Log level and add WarnLevel (#935) * fix# Change the Log level and add WarnLevel * fix# Change the Log level and add WarnLevel --- util/log/log.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/util/log/log.go b/util/log/log.go index 32992545..52184c5e 100644 --- a/util/log/log.go +++ b/util/log/log.go @@ -14,8 +14,9 @@ type Level int const ( LevelFatal Level = iota - LevelInfo LevelError + LevelInfo + LevelWarn LevelDebug LevelTrace ) @@ -37,6 +38,8 @@ func init() { level = LevelTrace case "debug": level = LevelDebug + case "warn": + level = LevelWarn case "info": level = LevelInfo case "error": @@ -99,6 +102,16 @@ func Debugf(format string, v ...interface{}) { WithLevelf(LevelDebug, format, v...) } +// Warn provides warn level logging +func Warn(v ...interface{}) { + WithLevel(LevelWarn, v...) +} + +// Warnf provides warn level logging +func Warnf(format string, v ...interface{}) { + WithLevelf(LevelWarn, format, v...) +} + // Info provides info level logging func Info(v ...interface{}) { WithLevel(LevelInfo, v...) From 65b1283459e7bfc55dbef2268c62288e1aa13fab Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 11 Nov 2019 09:13:02 +0000 Subject: [PATCH 197/344] add metadata.Get(context, key) as short hand --- metadata/metadata.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/metadata/metadata.go b/metadata/metadata.go index f7444501..74b0aa3c 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -21,6 +21,16 @@ func Copy(md Metadata) Metadata { return cmd } +// Get returns a single value from metadata in the context +func Get(ctx context.Context, key string) (string, bool) { + md, ok := FromContext(ctx) + if !ok { + return "", ok + } + val, ok := md[key] + return val, ok +} + // FromContext returns metadata from the given context func FromContext(ctx context.Context) (Metadata, bool) { md, ok := ctx.Value(metaKey{}).(Metadata) From fd5c29addc99cb6b180c704c27d551557bf5185a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 11 Nov 2019 15:28:37 +0000 Subject: [PATCH 198/344] Add the ability to only advertise local routes or don't advertise at all (#932) * Add the ability to only advertise local routes or don't advertise at all * Reorder processing to shortcircuit no advertising --- router/default.go | 48 ++++++++++++++++++++++++++++++++++++++++++----- router/router.go | 8 ++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/router/default.go b/router/default.go index 49f0ff1f..b77a3683 100644 --- a/router/default.go +++ b/router/default.go @@ -413,7 +413,13 @@ func (r *router) advertiseEvents() error { for { select { case <-ticker.C: + // If we're not advertising any events then sip processing them entirely + if r.options.Advertise == AdvertiseNone { + continue + } + var events []*Event + // collect all events which are not flapping for key, advert := range adverts { // process the advert @@ -426,6 +432,11 @@ func (r *router) advertiseEvents() error { continue } + // if we only advertise local routes skip processing anything not link local + if r.options.Advertise == AdvertiseLocal && advert.event.Route.Link != "local" { + continue + } + // copy the event and append e := new(Event) // this is ok, because router.Event only contains builtin types @@ -450,6 +461,17 @@ func (r *router) advertiseEvents() error { if e == nil { continue } + + // If we're not advertising any events then skip processing them entirely + if r.options.Advertise == AdvertiseNone { + continue + } + + // if we only advertise local routes skip processing anything not link local + if r.options.Advertise == AdvertiseLocal && e.Route.Link != "local" { + continue + } + now := time.Now() log.Debugf("Router processing table event %s for service %s %s", e.Type, e.Route.Service, e.Route.Address) @@ -708,12 +730,18 @@ func (r *router) Process(a *Advert) error { // flushRouteEvents returns a slice of events, one per each route in the routing table func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { + // Do not advertise anything + if r.options.Advertise == AdvertiseNone { + return []*Event{}, nil + } + // list all routes routes, err := r.table.List() if err != nil { return nil, fmt.Errorf("failed listing routes: %s", err) } + // Return all the routes if r.options.Advertise == AdvertiseAll { // build a list of events to advertise events := make([]*Event, len(routes)) @@ -728,24 +756,34 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { return events, nil } - // routeMap stores optimal routes per service + // routeMap stores the routes we're going to advertise bestRoutes := make(map[string]Route) + // set whether we're advertising only local + advertiseLocal := r.options.Advertise == AdvertiseLocal + // go through all routes found in the routing table and collapse them to optimal routes for _, route := range routes { + // if we're only advertising local routes + if advertiseLocal && route.Link != "local" { + continue + } + + // now we're going to find the best routes + routeKey := route.Service + "@" + route.Network - optimal, ok := bestRoutes[routeKey] + current, ok := bestRoutes[routeKey] if !ok { bestRoutes[routeKey] = route continue } // if the current optimal route metric is higher than routing table route, replace it - if optimal.Metric > route.Metric { + if current.Metric > route.Metric { bestRoutes[routeKey] = route continue } // if the metrics are the same, prefer advertising your own route - if optimal.Metric == route.Metric { + if current.Metric == route.Metric { if route.Router == r.options.Id { bestRoutes[routeKey] = route continue @@ -753,7 +791,7 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { } } - log.Debugf("Router advertising %d best routes out of %d", len(bestRoutes), len(routes)) + log.Debugf("Router advertising %d %s routes out of %d", len(bestRoutes), r.options.Advertise, len(routes)) // build a list of events to advertise events := make([]*Event, len(bestRoutes)) diff --git a/router/router.go b/router/router.go index cd300e7e..e6018766 100644 --- a/router/router.go +++ b/router/router.go @@ -147,6 +147,10 @@ const ( AdvertiseAll Strategy = iota // AdvertiseBest advertises optimal routes to the network AdvertiseBest + // AdvertiseLocal will only advertise the local routes + AdvertiseLocal + // AdvertiseNone will not advertise any routes + AdvertiseNone ) // String returns human readable Strategy @@ -156,6 +160,10 @@ func (s Strategy) String() string { return "all" case AdvertiseBest: return "best" + case AdvertiseLocal: + return "local" + case AdvertiseNone: + return "none" default: return "unknown" } From 72522a869ad7435a6f5de2f77431c9ce1ec57e65 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 11 Nov 2019 17:37:48 +0000 Subject: [PATCH 199/344] fix endpoint extractor panic --- server/extractor.go | 1 + server/grpc/extractor.go | 1 + 2 files changed, 2 insertions(+) diff --git a/server/extractor.go b/server/extractor.go index 5cbddd77..2a9d4e01 100644 --- a/server/extractor.go +++ b/server/extractor.go @@ -99,6 +99,7 @@ func extractEndpoint(method reflect.Method) *registry.Endpoint { Name: method.Name, Request: request, Response: response, + Metadata: make(map[string]string), } // set endpoint metadata for stream diff --git a/server/grpc/extractor.go b/server/grpc/extractor.go index 8b3ed4f6..875bb1c9 100644 --- a/server/grpc/extractor.go +++ b/server/grpc/extractor.go @@ -94,6 +94,7 @@ func extractEndpoint(method reflect.Method) *registry.Endpoint { Name: method.Name, Request: request, Response: response, + Metadata: make(map[string]string), } if stream { From bdb62e8ed177e7154e2a605f655b89c4b1eeaeb2 Mon Sep 17 00:00:00 2001 From: Lars Lehtonen Date: Mon, 11 Nov 2019 23:54:33 -0800 Subject: [PATCH 200/344] store/postgresql: fix dropped error (#938) --- store/postgresql/postgresql.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/store/postgresql/postgresql.go b/store/postgresql/postgresql.go index a574c5ed..58fa935c 100644 --- a/store/postgresql/postgresql.go +++ b/store/postgresql/postgresql.go @@ -178,6 +178,9 @@ func (s *sqlStore) initDB(options options.Options) error { expiry timestamp with time zone, CONSTRAINT %s_pkey PRIMARY KEY (key) );`, s.table, s.table)) + if err != nil { + return errors.Wrap(err, "SQL statement preparation failed") + } _, err = tableq.Exec() if err != nil { return errors.Wrap(err, "Couldn't create table") From 671408b3a54ec1fcd287898f4d6347f9e765d256 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 12 Nov 2019 12:27:51 +0000 Subject: [PATCH 201/344] Create FUNDING.yml --- .github/FUNDING.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..29be717d --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +issuehunt: micro/go-micro From 8867539d787b9ee2ea761079cfc56704daded540 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 12 Nov 2019 12:35:09 +0000 Subject: [PATCH 202/344] Update FUNDING.yml --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 29be717d..b6392e26 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,3 @@ # These are supported funding model platforms -issuehunt: micro/go-micro +issuehunt: micro/development From cffa5b6b50d25a48b20754af5fc9a5154d516c5e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 12 Nov 2019 15:46:30 +0000 Subject: [PATCH 203/344] Make use of cloudflare 1.0.0.1 by default to resolve addresses --- network/resolver/dns/dns.go | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/network/resolver/dns/dns.go b/network/resolver/dns/dns.go index b4fa4fc5..aaa3a744 100644 --- a/network/resolver/dns/dns.go +++ b/network/resolver/dns/dns.go @@ -2,13 +2,18 @@ package dns import ( + "context" "net" "github.com/micro/go-micro/network/resolver" + "github.com/miekg/dns" ) // Resolver is a DNS network resolve -type Resolver struct{} +type Resolver struct { + // The resolver address to use + Address string +} // Resolve assumes ID is a domain name e.g micro.mu func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { @@ -22,14 +27,29 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { host = "localhost" } - addrs, err := net.LookupHost(host) + if len(r.Address) == 0 { + r.Address = "1.0.0.1:53" + } + + m := new(dns.Msg) + m.SetQuestion(dns.Fqdn(host), dns.TypeA) + rec, err := dns.ExchangeContext(context.Background(), m, r.Address) if err != nil { return nil, err } - records := make([]*resolver.Record, 0, len(addrs)) + var records []*resolver.Record + + for _, answer := range rec.Answer { + h := answer.Header() + // check record type matches + if h.Rrtype != dns.TypeA { + continue + } + + arec, _ := answer.(*dns.A) + addr := arec.A.String() - for _, addr := range addrs { // join resolved record with port address := net.JoinHostPort(addr, port) // append to record set From 9f481542f38df502f114b1bf54e0ee1157aaf35c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 13 Nov 2019 11:05:53 +0000 Subject: [PATCH 204/344] Fix a codec race by locking the buffers. Include a buffer pool for perf. (#941) * Fix a codec race by locking the buffers. Include a buffer pool for perf. * Read Lock on buffer Read --- server/rpc_codec.go | 62 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 2fea1b83..2fbddc0e 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -2,6 +2,7 @@ package server import ( "bytes" + "sync" "github.com/micro/go-micro/codec" raw "github.com/micro/go-micro/codec/bytes" @@ -11,20 +12,25 @@ import ( "github.com/micro/go-micro/codec/proto" "github.com/micro/go-micro/codec/protorpc" "github.com/micro/go-micro/transport" + "github.com/oxtoacart/bpool" "github.com/pkg/errors" ) type rpcCodec struct { socket transport.Socket codec codec.Codec - first bool protocol string req *transport.Message buf *readWriteCloser + + // check if we're the first + sync.RWMutex + first chan bool } type readWriteCloser struct { + sync.RWMutex wbuf *bytes.Buffer rbuf *bytes.Buffer } @@ -51,19 +57,24 @@ var ( "application/proto-rpc": protorpc.NewCodec, "application/octet-stream": protorpc.NewCodec, } + + // the local buffer pool + bufferPool = bpool.NewSizedBufferPool(32, 1) ) func (rwc *readWriteCloser) Read(p []byte) (n int, err error) { + rwc.RLock() + defer rwc.RUnlock() return rwc.rbuf.Read(p) } func (rwc *readWriteCloser) Write(p []byte) (n int, err error) { + rwc.Lock() + defer rwc.Unlock() return rwc.wbuf.Write(p) } func (rwc *readWriteCloser) Close() error { - rwc.rbuf.Reset() - rwc.wbuf.Reset() return nil } @@ -155,8 +166,8 @@ func setupProtocol(msg *transport.Message) codec.NewCodec { func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCodec) codec.Codec { rwc := &readWriteCloser{ - rbuf: bytes.NewBuffer(nil), - wbuf: bytes.NewBuffer(nil), + rbuf: bufferPool.Get(), + wbuf: bufferPool.Get(), } r := &rpcCodec{ @@ -165,18 +176,20 @@ func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCod req: req, socket: socket, protocol: "mucp", + first: make(chan bool), } // if grpc pre-load the buffer // TODO: remove this terrible hack switch r.codec.String() { case "grpc": - // set as first - r.first = true // write the body rwc.rbuf.Write(req.Body) // set the protocol r.protocol = "grpc" + default: + // first is not preloaded + close(r.first) } return r @@ -190,7 +203,9 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { } // first message could be pre-loaded - if !c.first { + select { + case <-c.first: + // not the first var tm transport.Message // read off the socket @@ -212,11 +227,26 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { // set req c.req = &tm + default: + // we need to lock here to prevent race conditions + // and we make use of a channel otherwise because + // this does not result in a context switch + // locking to check c.first on every call to ReadHeader + // would otherwise drastically slow the code execution + c.Lock() + // recheck before closing because the select statement + // above is not thread safe, so thread safety here is + // mandatory + select { + case <-c.first: + default: + // disable first + close(c.first) + } + // now unlock and we never need this again + c.Unlock() } - // disable first - c.first = false - // set some internal things getHeaders(&m) @@ -309,9 +339,15 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { } func (c *rpcCodec) Close() error { - c.buf.Close() + // close the codec c.codec.Close() - return c.socket.Close() + // close the socket + err := c.socket.Close() + // put back the buffers + bufferPool.Put(c.buf.rbuf) + bufferPool.Put(c.buf.wbuf) + // return the error + return err } func (c *rpcCodec) String() string { From 43d11a9b8d8c2e7db4f0daa2d98851e9f0cfb903 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 14 Nov 2019 10:50:51 +0000 Subject: [PATCH 205/344] Create CNAME --- CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 CNAME diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..e54d8572 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +gomicro.dev \ No newline at end of file From 946c76cb0343def4601df3c1342091c843702d3e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 14 Nov 2019 11:01:27 +0000 Subject: [PATCH 206/344] Delete CNAME --- CNAME | 1 - 1 file changed, 1 deletion(-) delete mode 100644 CNAME diff --git a/CNAME b/CNAME deleted file mode 100644 index e54d8572..00000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -gomicro.dev \ No newline at end of file From 920c026f145eb792eec2bb072cb584912f718c82 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 14 Nov 2019 11:01:36 +0000 Subject: [PATCH 207/344] Create CNAME --- CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 CNAME diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..e54d8572 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +gomicro.dev \ No newline at end of file From 8e9eef794f7dc7c73c215f8068155f9ad66edd51 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 14 Nov 2019 11:15:50 +0000 Subject: [PATCH 208/344] Set theme jekyll-theme-minimal --- _config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 _config.yml diff --git a/_config.yml b/_config.yml new file mode 100644 index 00000000..2f7efbea --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-minimal \ No newline at end of file From 1c7d44282e5a290a61a3daca4d622c0e550f9ad6 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 14 Nov 2019 11:17:02 +0000 Subject: [PATCH 209/344] Set theme jekyll-theme-minimal From 58b25d7241fe12c4ec77bc4a5ee438018053f86e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 14 Nov 2019 11:54:16 +0000 Subject: [PATCH 210/344] Update CNAME --- CNAME | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CNAME b/CNAME index e54d8572..0be20e66 100644 --- a/CNAME +++ b/CNAME @@ -1 +1 @@ -gomicro.dev \ No newline at end of file +go-micro.dev \ No newline at end of file From 16754a747747666114440d25c0e5591425e06c98 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 14 Nov 2019 11:55:07 +0000 Subject: [PATCH 211/344] Set theme jekyll-theme-architect --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 2f7efbea..3397c9a4 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-minimal \ No newline at end of file +theme: jekyll-theme-architect \ No newline at end of file From 383658edf28ecec73c16a5f157417da9d5149274 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 14 Nov 2019 14:26:21 +0000 Subject: [PATCH 212/344] Fix a runtime deadlock as well as fixing some graceful exiting issues (#945) --- runtime/default.go | 42 +++++++++++++++++++++++++++++++++------- runtime/process/os/os.go | 15 +++++++++++++- runtime/service.go | 7 ++++++- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/runtime/default.go b/runtime/default.go index 832558f5..6fdb2953 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -98,31 +98,39 @@ func (r *runtime) run(events <-chan Event) { } buildTime := time.Unix(updateTimeStamp, 0) processEvent := func(event Event, service *Service) error { - buildTimeStamp, err := strconv.ParseInt(service.Version, 10, 64) + r.RLock() + name := service.Name + version := service.Version + r.RUnlock() + + buildTimeStamp, err := strconv.ParseInt(version, 10, 64) if err != nil { return err } muBuild := time.Unix(buildTimeStamp, 0) if buildTime.After(muBuild) { + log.Debugf("Runtime updating service %s", name) if err := r.Update(service); err != nil { return err } + r.Lock() service.Version = fmt.Sprintf("%d", buildTime.Unix()) + r.Unlock() } return nil } - r.Lock() + if len(event.Service) > 0 { + r.RLock() service, ok := r.services[event.Service] + r.RUnlock() if !ok { log.Debugf("Runtime unknown service: %s", event.Service) - r.Unlock() continue } if err := processEvent(event, service.Service); err != nil { log.Debugf("Runtime error updating service %s: %v", event.Service, err) } - r.Unlock() continue } // if blank service was received we update all services @@ -131,7 +139,6 @@ func (r *runtime) run(events <-chan Event) { log.Debugf("Runtime error updating service %s: %v", service.Name, err) } } - r.Unlock() } case <-r.closed: log.Debugf("Runtime stopped.") @@ -162,6 +169,7 @@ func (r *runtime) Create(s *Service, opts ...CreateOption) error { r.services[s.Name] = newService(s, options) // push into start queue + log.Debugf("Runtime creating service %s", s.Name) r.start <- r.services[s.Name] return nil @@ -172,9 +180,20 @@ func (r *runtime) Delete(s *Service) error { r.Lock() defer r.Unlock() + log.Debugf("Runtime deleting service %s", s.Name) if s, ok := r.services[s.Name]; ok { + // check if running + if !s.Running() { + delete(r.services, s.Name) + return nil + } + // otherwise stop it + if err := s.Stop(); err != nil { + return err + } + // delete it delete(r.services, s.Name) - return s.Stop() + return nil } return nil @@ -182,13 +201,22 @@ func (r *runtime) Delete(s *Service) error { // Update attemps to update the service func (r *runtime) Update(s *Service) error { + var opts []CreateOption + + // check if the service already exists + r.RLock() + if service, ok := r.services[s.Name]; ok { + opts = append(opts, WithOutput(service.output)) + } + r.RUnlock() + // delete the service if err := r.Delete(s); err != nil { return err } // create new service - return r.Create(s) + return r.Create(s, opts...) } // List returns a slice of all services tracked by the runtime diff --git a/runtime/process/os/os.go b/runtime/process/os/os.go index ec7d09f3..83eca1f3 100644 --- a/runtime/process/os/os.go +++ b/runtime/process/os/os.go @@ -6,6 +6,7 @@ import ( "os" "os/exec" "strconv" + "syscall" "github.com/micro/go-micro/runtime/process" ) @@ -24,6 +25,9 @@ func (p *Process) Fork(exe *process.Executable) (*process.PID, error) { // set env vars cmd.Env = append(cmd.Env, exe.Env...) + // create process group + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + in, err := cmd.StdinPipe() if err != nil { return nil, err @@ -61,7 +65,16 @@ func (p *Process) Kill(pid *process.PID) error { return err } - return pr.Kill() + // now kill it + err = pr.Kill() + + // kill the group + if pgid, err := syscall.Getpgid(id); err == nil { + syscall.Kill(-pgid, syscall.SIGKILL) + } + + // return the kill error + return err } func (p *Process) Wait(pid *process.PID) error { diff --git a/runtime/service.go b/runtime/service.go index cb0d3bb9..d83d7a5f 100644 --- a/runtime/service.go +++ b/runtime/service.go @@ -129,7 +129,12 @@ func (s *service) Stop() error { if s.PID == nil { return nil } - return s.Process.Kill(s.PID) + // kill the process + err := s.Process.Kill(s.PID) + // wait for it to exit + s.Process.Wait(s.PID) + // return the kill error + return err } } From a91b3f3e8b1a7cade255e177f74a119b5fefd6c9 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 15 Nov 2019 08:20:05 +0000 Subject: [PATCH 213/344] windows specific os tag --- runtime/process/os/os_windows.go | 97 ++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 runtime/process/os/os_windows.go diff --git a/runtime/process/os/os_windows.go b/runtime/process/os/os_windows.go new file mode 100644 index 00000000..8c5a4a02 --- /dev/null +++ b/runtime/process/os/os_windows.go @@ -0,0 +1,97 @@ +// Package os runs processes locally +package os + +import ( + "fmt" + "os" + "os/exec" + "strconv" + "syscall" + + "github.com/micro/go-micro/runtime/process" +) + +type Process struct { +} + +func (p *Process) Exec(exe *process.Executable) error { + cmd := exec.Command(exe.Binary.Path) + return cmd.Run() +} + +func (p *Process) Fork(exe *process.Executable) (*process.PID, error) { + // create command + cmd := exec.Command(exe.Binary.Path, exe.Args...) + // set env vars + cmd.Env = append(cmd.Env, exe.Env...) + + in, err := cmd.StdinPipe() + if err != nil { + return nil, err + } + out, err := cmd.StdoutPipe() + if err != nil { + return nil, err + } + er, err := cmd.StderrPipe() + if err != nil { + return nil, err + } + + // start the process + if err := cmd.Start(); err != nil { + return nil, err + } + + return &process.PID{ + ID: fmt.Sprintf("%d", cmd.Process.Pid), + Input: in, + Output: out, + Error: er, + }, nil +} + +func (p *Process) Kill(pid *process.PID) error { + id, err := strconv.Atoi(pid.ID) + if err != nil { + return err + } + + pr, err := os.FindProcess(id) + if err != nil { + return err + } + + // now kill it + err = pr.Kill() + + // return the kill error + return err +} + +func (p *Process) Wait(pid *process.PID) error { + id, err := strconv.Atoi(pid.ID) + if err != nil { + return err + } + + pr, err := os.FindProcess(id) + if err != nil { + return err + } + + ps, err := pr.Wait() + if err != nil { + return err + } + + if ps.Success() { + return nil + } + + return fmt.Errorf(ps.String()) +} + +func NewProcess(opts ...process.Option) process.Process { + return &Process{} +} From 0af8be35bb9d29e29f2a3af3acf9a65fd41ef7df Mon Sep 17 00:00:00 2001 From: mirwaisx <57108408+mirwaisx@users.noreply.github.com> Date: Fri, 15 Nov 2019 14:03:45 +0100 Subject: [PATCH 214/344] -bugfix #889 set body corretly in case of missing content-type (#950) --- api/handler/api/util.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/api/handler/api/util.go b/api/handler/api/util.go index 7a4607c7..824ec5da 100644 --- a/api/handler/api/util.go +++ b/api/handler/api/util.go @@ -29,16 +29,20 @@ func requestToProto(r *http.Request) (*api.Request, error) { ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) if err != nil { - ct = "application/x-www-form-urlencoded" + ct = "text/plain; charset=UTF-8" //default CT is text/plain r.Header.Set("Content-Type", ct) } - switch ct { - case "application/x-www-form-urlencoded": - // expect form vals - default: - data, _ := ioutil.ReadAll(r.Body) - req.Body = string(data) + //set the body: + if r.Body != nil { + switch ct { + case "application/x-www-form-urlencoded": + // expect form vals in Post data + default: + + data, _ := ioutil.ReadAll(r.Body) + req.Body = string(data) + } } // Set X-Forwarded-For if it does not exist From 97c1300f5320c2e04c18ea836df5be72174673cc Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 15 Nov 2019 13:41:40 +0000 Subject: [PATCH 215/344] [WIP] Micro Runtime (#947) * Add Get() and GetOptions. * Removed watcher. Outline of client. YAML templates * Added default service and deployment templates and types * Added API tests and cleaned up errors. * Small refactoring. Template package is no more. * Ripped out existing code in preparation to small rework * Reshuffled the source code to make it organized better * Create service and deployment in kubernetes runtime * Major cleanup and refactoring of Kubernetes runtime * Service now handles low level K8s API calls across both K8s deployment an service API objects * Runtime has a task queue that serves for queueing runtime action requests * General refactoring * No need for Lock in k8s service * Added kubernetes runtime env var to default deployment * Enable running different versions of the same service * Can't delete services through labels * Proto cruft. Added runtime.CreateOptions implementation in proto * Removed proxy service from default env variables * Make service name mandatory param to Get method * Get Delete changes from https://github.com/micro/go-micro/pull/945 * Replaced template files with global variables * Validate service names before sending K8s API request * Refactored Kubernetes API client. Fixed typos. * Added client.Resource to make API resources more explicit in code --- go.mod | 2 + go.sum | 2 + runtime/default.go | 71 ++- runtime/kubernetes/client/api/api_test.go | 169 +++++++ runtime/kubernetes/client/api/request.go | 58 ++- runtime/kubernetes/client/api/response.go | 7 +- runtime/kubernetes/client/client.go | 82 +++- runtime/kubernetes/client/kubernetes.go | 149 ++++-- runtime/kubernetes/client/templates.go | 93 ++++ runtime/kubernetes/client/types.go | 125 +++++ runtime/kubernetes/client/utils.go | 13 + runtime/kubernetes/client/utils_test.go | 25 + runtime/kubernetes/client/watch/body.go | 74 --- runtime/kubernetes/client/watch/watch.go | 26 -- runtime/kubernetes/client/watch/watch_test.go | 69 --- runtime/kubernetes/kubernetes.go | 291 +++++++----- runtime/kubernetes/service.go | 106 +++++ runtime/options.go | 15 + runtime/runtime.go | 12 +- runtime/service/handler/handler.go | 60 ++- runtime/service/proto/runtime.micro.go | 19 +- runtime/service/proto/runtime.pb.go | 441 ++++++++---------- runtime/service/proto/runtime.proto | 21 +- 23 files changed, 1284 insertions(+), 646 deletions(-) create mode 100644 runtime/kubernetes/client/api/api_test.go create mode 100644 runtime/kubernetes/client/templates.go create mode 100644 runtime/kubernetes/client/types.go create mode 100644 runtime/kubernetes/client/utils_test.go delete mode 100644 runtime/kubernetes/client/watch/body.go delete mode 100644 runtime/kubernetes/client/watch/watch.go delete mode 100644 runtime/kubernetes/client/watch/watch_test.go create mode 100644 runtime/kubernetes/service.go diff --git a/go.mod b/go.mod index 41b82b77..c83307cc 100644 --- a/go.mod +++ b/go.mod @@ -32,9 +32,11 @@ require ( github.com/mholt/certmagic v0.8.3 github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 + github.com/miekg/dns v1.1.15 github.com/mitchellh/hashstructure v1.0.0 github.com/nats-io/nats.go v1.9.1 github.com/nlopes/slack v0.6.0 + github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c github.com/pkg/errors v0.8.1 github.com/technoweenie/multipartstreamer v1.0.1 // indirect go.uber.org/zap v1.12.0 // indirect diff --git a/go.sum b/go.sum index 0ca438cd..33216a46 100644 --- a/go.sum +++ b/go.sum @@ -283,6 +283,8 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= +github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= +github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= 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= diff --git a/runtime/default.go b/runtime/default.go index 6fdb2953..18d8d7a9 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -21,6 +21,7 @@ type runtime struct { // indicates if we're running running bool // the service map + // TODO: track different versions of the same service services map[string]*service } @@ -175,6 +176,56 @@ func (r *runtime) Create(s *Service, opts ...CreateOption) error { return nil } +// Get returns all instances of requested service +// If no service name is provided we return all the track services. +func (r *runtime) Get(name string, opts ...GetOption) ([]*Service, error) { + r.Lock() + defer r.Unlock() + + if len(name) == 0 { + return nil, errors.New("missing service name") + } + + gopts := GetOptions{} + for _, o := range opts { + o(&gopts) + } + + var services []*Service + // if we track the service check if the version is provided + if s, ok := r.services[name]; ok { + if len(gopts.Version) > 0 { + if s.Version == gopts.Version { + services = append(services, s.Service) + } + return services, nil + } + // no version has sbeen requested, just append the service + services = append(services, s.Service) + } + return services, nil +} + +// Update attemps to update the service +func (r *runtime) Update(s *Service) error { + var opts []CreateOption + + // check if the service already exists + r.RLock() + if service, ok := r.services[s.Name]; ok { + opts = append(opts, WithOutput(service.output)) + } + r.RUnlock() + + // delete the service + if err := r.Delete(s); err != nil { + return err + } + + // create new service + return r.Create(s, opts...) +} + // Delete removes the service from the runtime and stops it func (r *runtime) Delete(s *Service) error { r.Lock() @@ -199,26 +250,6 @@ func (r *runtime) Delete(s *Service) error { return nil } -// Update attemps to update the service -func (r *runtime) Update(s *Service) error { - var opts []CreateOption - - // check if the service already exists - r.RLock() - if service, ok := r.services[s.Name]; ok { - opts = append(opts, WithOutput(service.output)) - } - r.RUnlock() - - // delete the service - if err := r.Delete(s); err != nil { - return err - } - - // create new service - return r.Create(s, opts...) -} - // List returns a slice of all services tracked by the runtime func (r *runtime) List() ([]*Service, error) { var services []*Service diff --git a/runtime/kubernetes/client/api/api_test.go b/runtime/kubernetes/client/api/api_test.go new file mode 100644 index 00000000..474dff55 --- /dev/null +++ b/runtime/kubernetes/client/api/api_test.go @@ -0,0 +1,169 @@ +package api + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "reflect" + "testing" +) + +type testcase struct { + Token string + ReqFn func(opts *Options) *Request + Method string + URI string + Body interface{} + Header map[string]string + Assert func(req *http.Request) bool +} + +type assertFn func(req *http.Request) bool + +var tests = []testcase{ + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Get().Resource("service") + }, + Method: "GET", + URI: "/api/v1/namespaces/default/services/", + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Get().Resource("service").Name("foo") + }, + Method: "GET", + URI: "/api/v1/namespaces/default/services/foo", + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Get().Resource("service").Namespace("test").Name("bar") + }, + Method: "GET", + URI: "/api/v1/namespaces/test/services/bar", + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Get().Resource("deployment").Name("foo") + }, + Method: "GET", + URI: "/apis/apps/v1/namespaces/default/deployments/foo", + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Get().Resource("deployment").Namespace("test").Name("foo") + }, + Method: "GET", + URI: "/apis/apps/v1/namespaces/test/deployments/foo", + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Get().Resource("pod").Params(&Params{LabelSelector: map[string]string{"foo": "bar"}}) + }, + Method: "GET", + URI: "/api/v1/namespaces/default/pods/?labelSelector=foo%3Dbar", + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Post().Resource("service").Name("foo").Body(map[string]string{"foo": "bar"}) + }, + Method: "POST", + URI: "/api/v1/namespaces/default/services/foo", + Body: map[string]string{"foo": "bar"}, + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Post().Resource("deployment").Namespace("test").Name("foo").Body(map[string]string{"foo": "bar"}) + }, + Method: "POST", + URI: "/apis/apps/v1/namespaces/test/deployments/foo", + Body: map[string]string{"foo": "bar"}, + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Put().Resource("endpoint").Name("baz").Body(map[string]string{"bam": "bar"}) + }, + Method: "PUT", + URI: "/api/v1/namespaces/default/endpoints/baz", + Body: map[string]string{"bam": "bar"}, + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Patch().Resource("endpoint").Name("baz").Body(map[string]string{"bam": "bar"}) + }, + Method: "PATCH", + URI: "/api/v1/namespaces/default/endpoints/baz", + Body: map[string]string{"bam": "bar"}, + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Patch().Resource("endpoint").Name("baz").SetHeader("foo", "bar") + }, + Method: "PATCH", + URI: "/api/v1/namespaces/default/endpoints/baz", + Header: map[string]string{"foo": "bar"}, + }, + testcase{ + ReqFn: func(opts *Options) *Request { + return NewRequest(opts).Patch().Resource("deployment").Name("baz").SetHeader("foo", "bar") + }, + Method: "PATCH", + URI: "/apis/apps/v1/namespaces/default/deployments/baz", + Header: map[string]string{"foo": "bar"}, + }, +} + +var wrappedHandler = func(test *testcase, t *testing.T) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + auth := r.Header.Get("Authorization") + if len(test.Token) > 0 && (len(auth) == 0 || auth != "Bearer "+test.Token) { + t.Errorf("test case token (%s) did not match expected token (%s)", "Bearer "+test.Token, auth) + } + + if len(test.Method) > 0 && test.Method != r.Method { + t.Errorf("test case Method (%s) did not match expected Method (%s)", test.Method, r.Method) + } + + if len(test.URI) > 0 && test.URI != r.URL.RequestURI() { + t.Errorf("test case URI (%s) did not match expected URI (%s)", test.URI, r.URL.RequestURI()) + } + + if test.Body != nil { + var res map[string]string + decoder := json.NewDecoder(r.Body) + if err := decoder.Decode(&res); err != nil { + t.Errorf("decoding body failed: %v", err) + } + if !reflect.DeepEqual(res, test.Body) { + t.Error("body did not match") + } + } + + if test.Header != nil { + for k, v := range test.Header { + if r.Header.Get(k) != v { + t.Error("header did not exist") + } + } + } + + w.WriteHeader(http.StatusOK) + }) +} + +func TestRequest(t *testing.T) { + for _, test := range tests { + ts := httptest.NewServer(wrappedHandler(&test, t)) + req := test.ReqFn(&Options{ + Host: ts.URL, + Client: &http.Client{}, + BearerToken: &test.Token, + Namespace: "default", + }) + res := req.Do() + if res.Error() != nil { + t.Errorf("request failed with %v", res.Error()) + } + ts.Close() + } +} diff --git a/runtime/kubernetes/client/api/request.go b/runtime/kubernetes/client/api/request.go index 20158806..bfb8b117 100644 --- a/runtime/kubernetes/client/api/request.go +++ b/runtime/kubernetes/client/api/request.go @@ -3,12 +3,12 @@ package api import ( "bytes" "encoding/json" + "errors" "fmt" "io" "net/http" "net/url" - "github.com/micro/go-micro/runtime/kubernetes/client/watch" "github.com/micro/go-micro/util/log" ) @@ -33,7 +33,6 @@ type Request struct { type Params struct { LabelSelector map[string]string Annotations map[string]string - Watch bool } // verb sets method @@ -58,9 +57,8 @@ func (r *Request) Put() *Request { } // Patch request -// https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md#patch-operations func (r *Request) Patch() *Request { - return r.verb("PATCH").SetHeader("Content-Type", "application/strategic-merge-patch+json") + return r.verb("PATCH") } // Delete request @@ -87,15 +85,33 @@ func (r *Request) Name(s string) *Request { return r } -// Body pass in a body to set, this is for POST, PUT -// and PATCH requests +// Body pass in a body to set, this is for POST, PUT and PATCH requests func (r *Request) Body(in interface{}) *Request { b := new(bytes.Buffer) - if err := json.NewEncoder(b).Encode(&in); err != nil { + // if we're not sending YAML request, we encode to JSON + if r.header.Get("Content-Type") != "application/yaml" { + if err := json.NewEncoder(b).Encode(&in); err != nil { + r.err = err + return r + } + log.Debugf("Request body: %v", b) + r.body = b + return r + } + + // if application/yaml is set, we assume we get a raw bytes so we just copy over + body, ok := in.(io.Reader) + if !ok { + r.err = errors.New("invalid data") + return r + } + // copy over data to the bytes buffer + if _, err := io.Copy(b, body); err != nil { r.err = err return r } - log.Debugf("Patch body: %v", b) + + log.Debugf("Request body: %v", b) r.body = b return r } @@ -120,12 +136,12 @@ func (r *Request) SetHeader(key, value string) *Request { func (r *Request) request() (*http.Request, error) { var url string switch r.resource { - case "pods": + case "pod", "service", "endpoint": // /api/v1/namespaces/{namespace}/pods - url = fmt.Sprintf("%s/api/v1/namespaces/%s/%s/", r.host, r.namespace, r.resource) - case "deployments": + url = fmt.Sprintf("%s/api/v1/namespaces/%s/%ss/", r.host, r.namespace, r.resource) + case "deployment": // /apis/apps/v1/namespaces/{namespace}/deployments/{name} - url = fmt.Sprintf("%s/apis/apps/v1/namespaces/%s/%s/", r.host, r.namespace, r.resource) + url = fmt.Sprintf("%s/apis/apps/v1/namespaces/%s/%ss/", r.host, r.namespace, r.resource) } // append resourceName if it is present @@ -179,24 +195,6 @@ func (r *Request) Do() *Response { return newResponse(res, err) } -// Watch builds and triggers the request, but -// will watch instead of return an object -func (r *Request) Watch() (watch.Watch, error) { - if r.err != nil { - return nil, r.err - } - - r.params.Set("watch", "true") - - req, err := r.request() - if err != nil { - return nil, err - } - - w, err := watch.NewBodyWatcher(req, r.client) - return w, err -} - // Options ... type Options struct { Host string diff --git a/runtime/kubernetes/client/api/response.go b/runtime/kubernetes/client/api/response.go index 8700115f..ceed48db 100644 --- a/runtime/kubernetes/client/api/response.go +++ b/runtime/kubernetes/client/api/response.go @@ -11,9 +11,9 @@ import ( // Errors ... var ( - ErrNotFound = errors.New("kubernetes: not found") + ErrNotFound = errors.New("kubernetes: resource not found") ErrDecode = errors.New("kubernetes: error decoding") - ErrOther = errors.New("kubernetes: unknown error") + ErrUnknown = errors.New("kubernetes: unknown error") ) // Status is an object that is returned when a request @@ -89,6 +89,7 @@ func newResponse(res *http.Response, err error) *Response { log.Log("kubernetes: request failed with body:") log.Log(string(b)) } - r.err = ErrOther + r.err = ErrUnknown + return r } diff --git a/runtime/kubernetes/client/client.go b/runtime/kubernetes/client/client.go index d201604e..bfebad9b 100644 --- a/runtime/kubernetes/client/client.go +++ b/runtime/kubernetes/client/client.go @@ -1,6 +1,7 @@ package client import ( + "bytes" "crypto/tls" "errors" "io/ioutil" @@ -13,6 +14,7 @@ import ( ) var ( + // path to kubernetes service account token serviceAccountPath = "/var/run/secrets/kubernetes.io/serviceaccount" // ErrReadNamespace is returned when the names could not be read from service account ErrReadNamespace = errors.New("Could not read namespace from service account secret") @@ -23,9 +25,7 @@ type client struct { opts *api.Options } -// NewClientInCluster should work similarily to the official api -// NewInClient by setting up a client configuration for use within -// a k8s pod. +// NewClientInCluster creates a Kubernetes client for use from within a k8s pod. func NewClientInCluster() *client { host := "https://" + os.Getenv("KUBERNETES_SERVICE_HOST") + ":" + os.Getenv("KUBERNETES_SERVICE_PORT") @@ -34,7 +34,7 @@ func NewClientInCluster() *client { log.Fatal(err) } if s == nil || !s.IsDir() { - log.Fatal(errors.New("no k8s service account found")) + log.Fatal(errors.New("service account not found")) } token, err := ioutil.ReadFile(path.Join(serviceAccountPath, "token")) @@ -90,26 +90,72 @@ func detectNamespace() (string, error) { } } -// UpdateDeployment patches kubernetes deployment with metadata provided in body -func (c *client) UpdateDeployment(name string, body interface{}) error { +// Create creates new API object +func (c *client) Create(r *Resource) error { + b := new(bytes.Buffer) + if err := renderTemplate(r.Kind, b, r.Value); err != nil { + return err + } + return api.NewRequest(c.opts). - Patch(). - Resource("deployments"). - Name(name). - Body(body). + Post(). + SetHeader("Content-Type", "application/yaml"). + Resource(r.Kind). + Body(b). Do(). Error() } -// ListDeployments lists all kubernetes deployments with given labels -func (c *client) ListDeployments(labels map[string]string) (*DeploymentList, error) { - var deployments DeploymentList - err := api.NewRequest(c.opts). +// Get queries API objects and stores the result in r +func (c *client) Get(r *Resource, labels map[string]string) error { + return api.NewRequest(c.opts). Get(). - Resource("deployments"). + Resource(r.Kind). Params(&api.Params{LabelSelector: labels}). Do(). - Into(&deployments) - - return &deployments, err + Into(r.Value) +} + +// Update updates API object +func (c *client) Update(r *Resource) error { + req := api.NewRequest(c.opts). + Patch(). + SetHeader("Content-Type", "application/strategic-merge-patch+json"). + Resource(r.Kind). + Name(r.Name) + + switch r.Kind { + case "service": + req.Body(r.Value.(*Service).Spec) + case "deployment": + req.Body(r.Value.(*Deployment).Spec) + default: + return errors.New("unsupported resource") + } + + return req.Do().Error() +} + +// Delete removes API object +func (c *client) Delete(r *Resource) error { + return api.NewRequest(c.opts). + Delete(). + Resource(r.Kind). + Name(r.Name). + Do(). + Error() +} + +// List lists API objects and stores the result in r +func (c *client) List(r *Resource) error { + labels := map[string]string{ + "micro": "service", + } + + return api.NewRequest(c.opts). + Get(). + Resource(r.Kind). + Params(&api.Params{LabelSelector: labels}). + Do(). + Into(r.Value) } diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index afed5ec2..4c378ea1 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -1,43 +1,132 @@ +// Package client provides an implementation of a restricted subset of kubernetes API client package client +import ( + "regexp" + "strconv" + "strings" + "time" + + "github.com/micro/go-micro/util/log" +) + +const ( + // https://github.com/kubernetes/apimachinery/blob/master/pkg/util/validation/validation.go#L134 + dns1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?" +) + +var ( + // DefaultImage is default micro image + DefaultImage = "micro/micro" + // ServiceRegexp is used to validate service name + ServiceRegexp = regexp.MustCompile("^" + dns1123LabelFmt + "$") +) + // Kubernetes client type Kubernetes interface { - // UpdateDeployment patches deployment annotations with new metadata - UpdateDeployment(string, interface{}) error - // ListDeployments lists all micro deployments - ListDeployments(labels map[string]string) (*DeploymentList, error) + // Create creates new API resource + Create(*Resource) error + // Get queries API resrouces + Get(*Resource, map[string]string) error + // Update patches existing API object + Update(*Resource) error + // Delete deletes API resource + Delete(*Resource) error + // List lists API resources + List(*Resource) error } -// Template is micro deployment template -type Template struct { - Metadata *Metadata `json:"metadata,omitempty"` +// DefaultService returns default micro kubernetes service definition +func DefaultService(name, version string) *Service { + Labels := map[string]string{ + "name": name, + "version": version, + "micro": "service", + } + + svcName := name + if len(version) > 0 { + // API service object name joins name and version over "-" + svcName = strings.Join([]string{name, version}, "-") + + } + + Metadata := &Metadata{ + Name: svcName, + Namespace: "default", + Version: version, + Labels: Labels, + } + + Spec := &ServiceSpec{ + Type: "ClusterIP", + Selector: Labels, + Ports: []ServicePort{{ + name + "-port", 9090, "", + }}, + } + + return &Service{ + Metadata: Metadata, + Spec: Spec, + } } -// Spec defines micro deployment spec -type Spec struct { - Template *Template `json:"template,omitempty"` -} +// DefaultService returns default micro kubernetes deployment definition +func DefaultDeployment(name, version string) *Deployment { + Labels := map[string]string{ + "name": name, + "version": version, + "micro": "service", + } -// Metadata defines api request metadata -type Metadata struct { - Name string `json:"name,omitempty"` - Labels map[string]string `json:"labels,omitempty"` - Annotations map[string]string `json:"annotations,omitempty"` -} + // API deployment object name joins name and version over "=" + depName := strings.Join([]string{name, version}, "-") -// DeploymentList -type DeploymentList struct { - Items []Deployment `json:"items"` -} + Metadata := &Metadata{ + Name: depName, + Namespace: "default", + Version: version, + Labels: Labels, + } -// Deployment is Kubernetes deployment -type Deployment struct { - Metadata *Metadata `json:"metadata"` - Status *Status `json:"status"` -} + // TODO: we need to figure out this version stuff + // might be worth adding Build to runtime.Service + buildTime, err := strconv.ParseInt(version, 10, 64) + if err == nil { + buildUnixTimeUTC := time.Unix(buildTime, 0) + Metadata.Annotations = map[string]string{ + "build": buildUnixTimeUTC.Format(time.RFC3339), + } + } else { + log.Debugf("Runtime could not parse build: %v", err) + } -// Status is Kubernetes deployment status -type Status struct { - Replicas int `json:"replicas"` - AvailableReplicas int `json:"availablereplicas"` + // TODO: change the image name here + Spec := &DeploymentSpec{ + Replicas: 1, + Selector: &LabelSelector{ + MatchLabels: Labels, + }, + Template: &Template{ + Metadata: Metadata, + PodSpec: &PodSpec{ + Containers: []Container{{ + Name: name, + Image: DefaultImage, + Env: []EnvVar{}, + Command: []string{"go", "run", "main.go"}, + Ports: []ContainerPort{{ + Name: name + "-port", + ContainerPort: 8080, + }}, + }}, + }, + }, + } + + return &Deployment{ + Metadata: Metadata, + Spec: Spec, + } } diff --git a/runtime/kubernetes/client/templates.go b/runtime/kubernetes/client/templates.go new file mode 100644 index 00000000..5292ac4f --- /dev/null +++ b/runtime/kubernetes/client/templates.go @@ -0,0 +1,93 @@ +package client + +var templates = map[string]string{ + "deployments": deploymentTmpl, + "services": serviceTmpl, +} + +var deploymentTmpl = ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "{{ .Metadata.Name }}" + namespace: "{{ .Metadata.Namespace }}" + labels: + {{- with .Metadata.Labels }} + {{- range $key, $value := . }} + {{ $key }}: "{{ $value }}" + {{- end }} + {{- end }} +spec: + replicas: {{ .Spec.Replicas }} + selector: + matchLabels: + {{- with .Spec.Selector.MatchLabels }} + {{- range $key, $value := . }} + {{ $key }}: "{{ $value }}" + {{- end }} + {{- end }} + template: + metadata: + labels: + {{- with .Spec.Template.Metadata.Labels }} + {{- range $key, $value := . }} + {{ $key }}: "{{ $value }}" + {{- end }} + {{- end }} + spec: + containers: + {{- with .Spec.Template.PodSpec.Containers }} + {{- range . }} + - name: {{ .Name }} + env: + {{- with .Env }} + {{- range . }} + - name: "{{ .Name }}" + value: "{{ .Value }}" + {{- end }} + {{- end }} + command: + {{- range .Command }} + - {{.}} + {{- end }} + image: {{ .Image }} + imagePullPolicy: Always + ports: + {{- with .Ports }} + {{- range . }} + - containerPort: {{ .ContainerPort }} + name: {{ .Name }} + {{- end}} + {{- end}} + {{- end }} + {{- end}} +` + +var serviceTmpl = ` +apiVersion: v1 +kind: Service +metadata: + name: "{{ .Metadata.Name }}" + namespace: "{{ .Metadata.Namespace }}" + labels: + {{- with .Metadata.Labels }} + {{- range $key, $value := . }} + {{ $key }}: "{{ $value }}" + {{- end }} + {{- end }} +spec: + selector: + {{- with .Spec.Selector }} + {{- range $key, $value := . }} + {{ $key }}: "{{ $value }}" + {{- end }} + {{- end }} + ports: + {{- with .Spec.Ports }} + {{- range . }} + - name: "{{ .Name }}" + port: {{ .Port }} + protocol: {{ .Protocol }} + {{- end }} + {{- end }} +` diff --git a/runtime/kubernetes/client/types.go b/runtime/kubernetes/client/types.go new file mode 100644 index 00000000..882b826e --- /dev/null +++ b/runtime/kubernetes/client/types.go @@ -0,0 +1,125 @@ +package client + +// Resource is API resource +type Resource struct { + Name string + Kind string + Value interface{} +} + +// Metadata defines api object metadata +type Metadata struct { + Name string `json:"name,omitempty"` + Namespace string `json:"namespace,omitempty"` + Version string `json:"version,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` +} + +// ServicePort configures service ports +type ServicePort struct { + Name string `json:"name,omitempty"` + Port int `json:"port"` + Protocol string `json:"protocol,omitempty"` +} + +// ServiceSpec provides service configuration +type ServiceSpec struct { + Type string `json:"type,omitempty"` + Selector map[string]string `json:"selector,omitempty"` + Ports []ServicePort `json:"ports,omitempty"` +} + +type LoadBalancerIngress struct { + IP string `json:"ip,omitempty"` + Hostname string `json:"hostname,omitempty"` +} + +type LoadBalancerStatus struct { + Ingress []LoadBalancerIngress `json:"ingress,omitempty"` +} + +// ServiceStatus +type ServiceStatus struct { + LoadBalancer LoadBalancerStatus `json:"loadBalancer,omitempty"` +} + +// Service is kubernetes service +type Service struct { + Metadata *Metadata `json:"metadata"` + Spec *ServiceSpec `json:"spec,omitempty"` + Status *ServiceStatus `json:"status,omitempty"` +} + +// ServiceList +type ServiceList struct { + Items []Service `json:"items"` +} + +// ContainerPort +type ContainerPort struct { + Name string `json:"name,omitempty"` + HostPort int `json:"hostPort,omitempty"` + ContainerPort int `json:"containerPort"` + Protocol string `json:"protocol,omitempty"` +} + +// EnvVar is environment variable +type EnvVar struct { + Name string `json:"name"` + Value string `json:"value,omitempty"` +} + +// Container defined container runtime values +type Container struct { + Name string `json:"name"` + Image string `json:"image"` + Env []EnvVar `json:"env,omitempty"` + Command []string `json:"command,omitempty"` + Ports []ContainerPort `json:"ports,omitempty"` +} + +// PodSpec +type PodSpec struct { + Containers []Container `json:"containers"` +} + +// Template is micro deployment template +type Template struct { + Metadata *Metadata `json:"metadata,omitempty"` + PodSpec *PodSpec `json:"spec,omitempty"` +} + +// LabelSelector is a label query over a set of resources +// NOTE: we do not support MatchExpressions at the moment +type LabelSelector struct { + MatchLabels map[string]string `json:"matchLabels,omitempty"` +} + +// DeploymentSpec defines micro deployment spec +type DeploymentSpec struct { + Replicas int `json:"replicas,omitempty"` + Selector *LabelSelector `json:"selector"` + Template *Template `json:"template,omitempty"` +} + +// DeploymentStatus is returned when querying deployment +type DeploymentStatus struct { + Replicas int `json:"replicas,omitempty"` + UpdatedReplicas int `json:"updatedReplicas,omitempty"` + ReadyReplicas int `json:"readyReplicas,omitempty"` + AvailableReplicas int `json:"availableReplicas,omitempty"` + UnavailableReplicas int `json:"unavailableReplicas,omitempty"` +} + +// Deployment is Kubernetes deployment +type Deployment struct { + Metadata *Metadata `json:"metadata"` + Spec *DeploymentSpec `json:"spec,omitempty"` + Status *DeploymentStatus `json:"status,omitempty"` +} + +// DeploymentList +type DeploymentList struct { + Items []Deployment `json:"items"` +} diff --git a/runtime/kubernetes/client/utils.go b/runtime/kubernetes/client/utils.go index ec250aca..b70ca44f 100644 --- a/runtime/kubernetes/client/utils.go +++ b/runtime/kubernetes/client/utils.go @@ -5,9 +5,22 @@ import ( "encoding/pem" "errors" "fmt" + "io" "io/ioutil" + "text/template" ) +// renderTemplateFile renders template file in path into writer w with supplied data +func renderTemplate(text string, w io.Writer, data interface{}) error { + t := template.Must(template.New("kubernetes").Parse(text)) + + if err := t.Execute(w, data); err != nil { + return err + } + + return nil +} + // COPIED FROM // https://github.com/kubernetes/kubernetes/blob/7a725418af4661067b56506faabc2d44c6d7703a/pkg/util/crypto/crypto.go diff --git a/runtime/kubernetes/client/utils_test.go b/runtime/kubernetes/client/utils_test.go new file mode 100644 index 00000000..0e69c012 --- /dev/null +++ b/runtime/kubernetes/client/utils_test.go @@ -0,0 +1,25 @@ +package client + +import ( + "bytes" + "testing" +) + +func TestTemplates(t *testing.T) { + name := "foo" + version := "1.2.3" + + // Render default service + s := DefaultService(name, version) + bs := new(bytes.Buffer) + if err := renderTemplate(serviceTmpl, bs, s); err != nil { + t.Errorf("Failed to render kubernetes service: %v", err) + } + + // Render default deployment + d := DefaultDeployment(name, version) + bd := new(bytes.Buffer) + if err := renderTemplate(deploymentTmpl, bd, d); err != nil { + t.Errorf("Failed to render kubernetes deployment: %v", err) + } +} diff --git a/runtime/kubernetes/client/watch/body.go b/runtime/kubernetes/client/watch/body.go deleted file mode 100644 index 3eaa6d43..00000000 --- a/runtime/kubernetes/client/watch/body.go +++ /dev/null @@ -1,74 +0,0 @@ -package watch - -import ( - "bufio" - "encoding/json" - "net/http" -) - -// bodyWatcher scans the body of a request for chunks -type bodyWatcher struct { - results chan Event - stop chan struct{} - res *http.Response - req *http.Request -} - -// Changes returns the results channel -func (wr *bodyWatcher) ResultChan() <-chan Event { - return wr.results -} - -// Stop cancels the request -func (wr *bodyWatcher) Stop() { - select { - case <-wr.stop: - return - default: - close(wr.stop) - close(wr.results) - } -} - -func (wr *bodyWatcher) stream() { - reader := bufio.NewReader(wr.res.Body) - - // stop the watcher - defer wr.Stop() - - for { - // read a line - b, err := reader.ReadBytes('\n') - if err != nil { - return - } - - // send the event - var event Event - if err := json.Unmarshal(b, &event); err != nil { - continue - } - wr.results <- event - } -} - -// NewBodyWatcher creates a k8s body watcher for a given http request -func NewBodyWatcher(req *http.Request, client *http.Client) (Watch, error) { - stop := make(chan struct{}) - req.Cancel = stop - - res, err := client.Do(req) - if err != nil { - return nil, err - } - - wr := &bodyWatcher{ - results: make(chan Event), - stop: stop, - req: req, - res: res, - } - - go wr.stream() - return wr, nil -} diff --git a/runtime/kubernetes/client/watch/watch.go b/runtime/kubernetes/client/watch/watch.go deleted file mode 100644 index f8a178b8..00000000 --- a/runtime/kubernetes/client/watch/watch.go +++ /dev/null @@ -1,26 +0,0 @@ -package watch - -import "encoding/json" - -// Watch ... -type Watch interface { - Stop() - ResultChan() <-chan Event -} - -// EventType defines the possible types of events. -type EventType string - -// EventTypes used -const ( - Added EventType = "ADDED" - Modified EventType = "MODIFIED" - Deleted EventType = "DELETED" - Error EventType = "ERROR" -) - -// Event represents a single event to a watched resource. -type Event struct { - Type EventType `json:"type"` - Object json.RawMessage `json:"object"` -} diff --git a/runtime/kubernetes/client/watch/watch_test.go b/runtime/kubernetes/client/watch/watch_test.go deleted file mode 100644 index ac34141c..00000000 --- a/runtime/kubernetes/client/watch/watch_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package watch - -import ( - "fmt" - "net/http" - "net/http/httptest" - "testing" - "time" -) - -var actions = []string{ - `{"type": "create", "object":{"foo": "bar"}}`, - `{"type": "delete", INVALID}`, - `{"type": "update", "object":{"foo": {"foo": "bar"}}}`, - `{"type": "delete", "object":null}`, -} - -func TestBodyWatcher(t *testing.T) { - // set up server with handler to flush strings from ch. - ch := make(chan string) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - flusher, ok := w.(http.Flusher) - if !ok { - t.Fatal("expected ResponseWriter to be a flusher") - } - - fmt.Fprintf(w, "\n") - flusher.Flush() - - for v := range ch { - fmt.Fprintf(w, "%s\n", v) - flusher.Flush() - time.Sleep(10 * time.Millisecond) - } - })) - defer ts.Close() - - req, err := http.NewRequest("GET", ts.URL, nil) - if err != nil { - t.Fatalf("failed to create new request: %v", err) - } - - // setup body watcher - w, err := NewBodyWatcher(req, http.DefaultClient) - if err != nil { - t.Fatalf("failed to create new BodyWatcher %v", err) - } - - // send action strings in, and expect result back - ch <- actions[0] - if r := <-w.ResultChan(); r.Type != "create" { - t.Fatalf("expected result to be create") - } - - ch <- actions[1] // should be ignored as its invalid json - ch <- actions[2] - if r := <-w.ResultChan(); r.Type != "update" { - t.Fatalf("expected result to be update") - } - - ch <- actions[3] - if r := <-w.ResultChan(); r.Type != "delete" { - t.Fatalf("expected result to be delete") - } - - // stop should clean up all channels. - w.Stop() - close(ch) -} diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 27369ac9..1939c46a 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -14,18 +14,31 @@ import ( "github.com/micro/go-micro/util/log" ) +// action to take on runtime service +type action int + +const ( + start action = iota + update + stop +) + +// task is queued into runtime queue +type task struct { + action action + service *service +} + type kubernetes struct { sync.RWMutex // options configure runtime options runtime.Options // indicates if we're running running bool - // used to start new services - start chan *runtime.Service + // task queue for kubernetes services + queue chan *task // used to stop the runtime closed chan bool - // service tracks deployed services - services map[string]*runtime.Service // client is kubernetes client client client.Kubernetes } @@ -44,11 +57,10 @@ func NewRuntime(opts ...runtime.Option) runtime.Runtime { client := client.NewClientInCluster() return &kubernetes{ - options: options, - closed: make(chan bool), - start: make(chan *runtime.Service, 128), - services: make(map[string]*runtime.Service), - client: client, + options: options, + closed: make(chan bool), + queue: make(chan *task, 128), + client: client, } } @@ -64,33 +76,109 @@ func (k *kubernetes) Init(opts ...runtime.Option) error { return nil } -// Registers a service +// Creates a service func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) error { k.Lock() defer k.Unlock() - // TODO: - // * create service - // * create deployment - - // NOTE: our services have micro- prefix - muName := strings.Split(s.Name, ".") - s.Name = "micro-" + muName[len(muName)-1] - - // NOTE: we are tracking this in memory for now - if _, ok := k.services[s.Name]; ok { - return errors.New("service already registered") - } - var options runtime.CreateOptions for _, o := range opts { o(&options) } - // save service - k.services[s.Name] = s + svcName := s.Name + if len(s.Version) > 0 { + svcName = strings.Join([]string{s.Name, s.Version}, "-") + } + + if !client.ServiceRegexp.MatchString(svcName) { + return fmt.Errorf("invalid service name: %s", svcName) + } + + // create new kubernetes micro service + service := newService(s, options) + + log.Debugf("Runtime queueing service %s for start action", service.Name) + // push into start queue - k.start <- k.services[s.Name] + k.queue <- &task{ + action: start, + service: service, + } + + return nil +} + +// Get returns all instances of given service +func (k *kubernetes) Get(name string, opts ...runtime.GetOption) ([]*runtime.Service, error) { + k.Lock() + defer k.Unlock() + + // if no name has been passed in, return error + if len(name) == 0 { + return nil, errors.New("missing service name") + } + + // set the default label + labels := map[string]string{ + "micro": "service", + "name": name, + } + var options runtime.GetOptions + for _, o := range opts { + o(&options) + } + + // add version to labels if a version has been supplied + if len(options.Version) > 0 { + labels["version"] = options.Version + } + + log.Debugf("Runtime querying service %s", name) + + serviceList := new(client.ServiceList) + r := &client.Resource{ + Kind: "service", + Value: serviceList, + } + if err := k.client.Get(r, labels); err != nil { + return nil, err + } + + services := make([]*runtime.Service, 0, len(serviceList.Items)) + for _, kservice := range serviceList.Items { + service := &runtime.Service{ + Name: kservice.Metadata.Name, + Version: kservice.Metadata.Version, + } + services = append(services, service) + } + + return services, nil +} + +// Update the service in place +func (k *kubernetes) Update(s *runtime.Service) error { + // parse version into human readable timestamp + updateTimeStamp, err := strconv.ParseInt(s.Version, 10, 64) + if err != nil { + return err + } + unixTimeUTC := time.Unix(updateTimeStamp, 0) + + // create new kubernetes micro service + service := newService(s, runtime.CreateOptions{}) + + // update build time annotation + service.kdeploy.Spec.Template.Metadata.Annotations["build"] = unixTimeUTC.Format(time.RFC3339) + + log.Debugf("Runtime queueing service %s for update action", service.Name) + + // queue service for removal + k.queue <- &task{ + action: update, + service: service, + } return nil } @@ -100,61 +188,37 @@ func (k *kubernetes) Delete(s *runtime.Service) error { k.Lock() defer k.Unlock() - // TODO: - // * delete service - // * delete dpeloyment + // create new kubernetes micro service + service := newService(s, runtime.CreateOptions{}) - // NOTE: we are tracking this in memory for now - if s, ok := k.services[s.Name]; ok { - delete(k.services, s.Name) - return nil + log.Debugf("Runtime queueing service %s for delete action", service.Name) + + // queue service for removal + k.queue <- &task{ + action: stop, + service: service, } return nil } -// Update the service in place -func (k *kubernetes) Update(s *runtime.Service) error { - type body struct { - Spec *client.Spec `json:"spec"` - } - // parse version into human readable timestamp - updateTimeStamp, err := strconv.ParseInt(s.Version, 10, 64) - if err != nil { - return err - } - unixTimeUTC := time.Unix(updateTimeStamp, 0) - // metada which we will PATCH deployment with - reqBody := body{ - Spec: &client.Spec{ - Template: &client.Template{ - Metadata: &client.Metadata{ - Annotations: map[string]string{ - "build": unixTimeUTC.Format(time.RFC3339), - }, - }, - }, - }, - } - return k.client.UpdateDeployment(s.Name, reqBody) -} - // List the managed services func (k *kubernetes) List() ([]*runtime.Service, error) { - labels := map[string]string{ - "micro": "service", + serviceList := new(client.ServiceList) + r := &client.Resource{ + Kind: "service", + Value: serviceList, } - // list all micro core deployments - deployments, err := k.client.ListDeployments(labels) - if err != nil { + + if err := k.client.List(r); err != nil { return nil, err } - log.Debugf("Runtime found %d micro deployments with labels %v", len(deployments.Items), labels) + log.Debugf("Runtime found %d micro services", len(serviceList.Items)) - services := make([]*runtime.Service, 0, len(deployments.Items)) + services := make([]*runtime.Service, 0, len(serviceList.Items)) - for _, service := range deployments.Items { + for _, service := range serviceList.Items { buildTime, err := time.Parse(time.RFC3339, service.Metadata.Annotations["build"]) if err != nil { log.Debugf("Runtime error parsing build time for %s: %v", service.Metadata.Name, err) @@ -179,23 +243,31 @@ func (k *kubernetes) run(events <-chan runtime.Event) { for { select { case <-t.C: - // check running services - services, err := k.List() - if err != nil { - log.Debugf("Runtime failed listing running services: %v", err) - continue + // TODO: figure out what to do here + // - do we even need the ticker for k8s services? + case task := <-k.queue: + switch task.action { + case start: + log.Debugf("Runtime starting new service: %s", task.service.Name) + if err := task.service.Start(k.client); err != nil { + log.Debugf("Runtime failed to start service %s: %v", task.service.Name, err) + continue + } + case stop: + log.Debugf("Runtime stopping service: %s", task.service.Name) + if err := task.service.Stop(k.client); err != nil { + log.Debugf("Runtime failed to stop service %s: %v", task.service.Name, err) + continue + } + case update: + log.Debugf("Runtime updating service: %s", task.service.Name) + if err := task.service.Update(k.client); err != nil { + log.Debugf("Runtime failed to update service %s: %v", task.service.Name, err) + continue + } + default: + log.Debugf("Runtime received unknown action for service: %s", task.service.Name) } - // TODO: for now we just log the running services - // * make sure all core deployments exist - // * make sure all core services are exposed - for _, service := range services { - log.Debugf("Runtime found running service: %v", service) - } - case service := <-k.start: - // TODO: this is a noop for now - // * create a deployment - // * expose a service - log.Debugf("Runtime starting service: %s", service.Name) case event := <-events: // NOTE: we only handle Update events for now log.Debugf("Runtime received notification event: %v", event) @@ -207,50 +279,23 @@ func (k *kubernetes) run(events <-chan runtime.Event) { log.Debugf("Runtime error parsing update build time: %v", err) continue } - buildTime := time.Unix(updateTimeStamp, 0) - processEvent := func(event runtime.Event, service *runtime.Service) error { - buildTimeStamp, err := strconv.ParseInt(service.Version, 10, 64) - if err != nil { - return err - } - muBuild := time.Unix(buildTimeStamp, 0) - if buildTime.After(muBuild) { - version := fmt.Sprintf("%d", buildTime.Unix()) - muService := &runtime.Service{ - Name: service.Name, - Source: service.Source, - Path: service.Path, - Exec: service.Exec, - Version: version, - } - if err := k.Update(muService); err != nil { - return err - } - service.Version = version - } - return nil - } - k.Lock() + unixTimeUTC := time.Unix(updateTimeStamp, 0) if len(event.Service) > 0 { - service, ok := k.services[event.Service] - if !ok { - log.Debugf("Runtime unknown service: %s", event.Service) - k.Unlock() + s := &runtime.Service{ + Name: event.Service, + Version: event.Version, + } + // create new kubernetes micro service + service := newService(s, runtime.CreateOptions{}) + // update build time annotation + service.kdeploy.Spec.Template.Metadata.Annotations["build"] = unixTimeUTC.Format(time.RFC3339) + + log.Debugf("Runtime updating service: %s", service.Name) + if err := service.Update(k.client); err != nil { + log.Debugf("Runtime failed to update service %s: %v", service.Name, err) continue } - if err := processEvent(event, service); err != nil { - log.Debugf("Runtime error updating service %s: %v", event.Service, err) - } - k.Unlock() - continue } - // if blank service was received we update all services - for _, service := range k.services { - if err := processEvent(event, service); err != nil { - log.Debugf("Runtime error updating service %s: %v", service.Name, err) - } - } - k.Unlock() } case <-k.closed: log.Debugf("Runtime stopped") diff --git a/runtime/kubernetes/service.go b/runtime/kubernetes/service.go new file mode 100644 index 00000000..0c02d1b9 --- /dev/null +++ b/runtime/kubernetes/service.go @@ -0,0 +1,106 @@ +package kubernetes + +import ( + "strings" + + "github.com/micro/go-micro/runtime" + "github.com/micro/go-micro/runtime/kubernetes/client" + "github.com/micro/go-micro/util/log" +) + +type service struct { + // service to manage + *runtime.Service + // Kubernetes service + kservice *client.Service + // Kubernetes deployment + kdeploy *client.Deployment +} + +func newService(s *runtime.Service, c runtime.CreateOptions) *service { + kservice := client.DefaultService(s.Name, s.Version) + kdeploy := client.DefaultDeployment(s.Name, s.Version) + + env := make([]client.EnvVar, 0, len(c.Env)) + for _, evar := range c.Env { + evarPair := strings.Split(evar, "=") + env = append(env, client.EnvVar{Name: evarPair[0], Value: evarPair[1]}) + } + + // TODO: should we append instead of overriding? + // if environment has been supplied update deployment + if len(env) > 0 { + kdeploy.Spec.Template.PodSpec.Containers[0].Env = env + } + + // if Command has been supplied override the default command + if len(c.Command) > 0 { + kdeploy.Spec.Template.PodSpec.Containers[0].Command = c.Command + } + + return &service{ + Service: s, + kservice: kservice, + kdeploy: kdeploy, + } +} + +func deploymentResource(d *client.Deployment) *client.Resource { + return &client.Resource{ + Name: d.Metadata.Name, + Kind: "deployment", + Value: d, + } +} + +func serviceResource(s *client.Service) *client.Resource { + return &client.Resource{ + Name: s.Metadata.Name, + Kind: "service", + Value: s, + } +} + +// Start starts the Kubernetes service. It creates new kubernetes deployment and service API objects +func (s *service) Start(k client.Kubernetes) error { + // create deployment first; if we fail, we dont create service + if err := k.Create(deploymentResource(s.kdeploy)); err != nil { + log.Debugf("Runtime failed to create deployment: %v", err) + return err + } + // create service now that the deployment has been created + if err := k.Create(serviceResource(s.kservice)); err != nil { + log.Debugf("Runtime failed to create service: %v", err) + return err + } + + return nil +} + +func (s *service) Stop(k client.Kubernetes) error { + // first attempt to delete service + if err := k.Delete(serviceResource(s.kservice)); err != nil { + log.Debugf("Runtime failed to delete service: %v", err) + return err + } + // delete deployment once the service has been deleted + if err := k.Delete(deploymentResource(s.kdeploy)); err != nil { + log.Debugf("Runtime failed to delete deployment: %v", err) + return err + } + + return nil +} + +func (s *service) Update(k client.Kubernetes) error { + if err := k.Update(deploymentResource(s.kdeploy)); err != nil { + log.Debugf("Runtime failed to update deployment: %v", err) + return err + } + if err := k.Update(serviceResource(s.kservice)); err != nil { + log.Debugf("Runtime failed to update service: %v", err) + return err + } + + return nil +} diff --git a/runtime/options.go b/runtime/options.go index 82284b36..e031656d 100644 --- a/runtime/options.go +++ b/runtime/options.go @@ -54,3 +54,18 @@ func WithOutput(out io.Writer) CreateOption { o.Output = out } } + +type GetOption func(o *GetOptions) + +// GetOptions queries runtime services +type GetOptions struct { + // Version queries services with given version + Version string +} + +// WithVersion confifgures service version +func WithVersion(version string) GetOption { + return func(o *GetOptions) { + o.Version = version + } +} diff --git a/runtime/runtime.go b/runtime/runtime.go index ca5762bb..36836392 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -12,17 +12,19 @@ var ( type Runtime interface { // Init initializes runtime Init(...Option) error - // Registers a service + // Create registers a service Create(*Service, ...CreateOption) error - // Remove a service - Delete(*Service) error + // Get returns service or fails with error + Get(string, ...GetOption) ([]*Service, error) // Update the service in place Update(*Service) error + // Remove a service + Delete(*Service) error // List the managed services List() ([]*Service, error) - // starts the runtime + // Start starts the runtime Start() error - // Shutdown the runtime + // Stop shuts down the runtime Stop() error } diff --git a/runtime/service/handler/handler.go b/runtime/service/handler/handler.go index 8f9abc38..aecef40b 100644 --- a/runtime/service/handler/handler.go +++ b/runtime/service/handler/handler.go @@ -32,14 +32,48 @@ func toService(s *pb.Service) *runtime.Service { } } +func toCreateOptions(opts *pb.CreateOptions) []runtime.CreateOption { + options := []runtime.CreateOption{} + // command options + l := len(opts.Command) + if l == 1 { + options = append(options, runtime.WithCommand(opts.Command[0])) + } + if l > 1 { + options = append(options, runtime.WithCommand(opts.Command[0], opts.Command[1:]...)) + } + // env options + if len(opts.Env) > 0 { + options = append(options, runtime.WithEnv(opts.Env)) + } + + // TODO: output options + + return options +} + +func toGetOptions(opts *pb.GetOptions) []runtime.GetOption { + options := []runtime.GetOption{} + // version options + if len(opts.Version) > 0 { + options = append(options, runtime.WithVersion(opts.Version)) + } + + return options +} + func (r *Runtime) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error { if req.Service == nil { return errors.BadRequest("go.micro.runtime", "blank service") } - // TODO: add opts + var options []runtime.CreateOption + if req.Options != nil { + options = toCreateOptions(req.Options) + } + service := toService(req.Service) - err := r.Runtime.Create(service) + err := r.Runtime.Create(service, options...) if err != nil { return errors.InternalServerError("go.micro.runtime", err.Error()) } @@ -47,6 +81,28 @@ func (r *Runtime) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.Cre return nil } +func (r *Runtime) Get(ctx context.Context, req *pb.GetRequest, rsp *pb.GetResponse) error { + if len(req.Name) == 0 { + return errors.BadRequest("go.micro.runtime", "blank service") + } + + var options []runtime.GetOption + if req.Options != nil { + options = toGetOptions(req.Options) + } + + services, err := r.Runtime.Get(req.Name, options...) + if err != nil { + return errors.InternalServerError("go.micro.runtime", err.Error()) + } + + for _, service := range services { + rsp.Services = append(rsp.Services, toProto(service)) + } + + return nil +} + func (r *Runtime) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error { if req.Service == nil { return errors.BadRequest("go.micro.runtime", "blank service") diff --git a/runtime/service/proto/runtime.micro.go b/runtime/service/proto/runtime.micro.go index 86c00c21..b5a3c4f5 100644 --- a/runtime/service/proto/runtime.micro.go +++ b/runtime/service/proto/runtime.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: micro/go-micro/runtime/service/proto/runtime.proto +// source: runtime.proto package go_micro_runtime @@ -35,6 +35,7 @@ var _ server.Option type RuntimeService interface { Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) + Get(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) @@ -68,6 +69,16 @@ func (c *runtimeService) Create(ctx context.Context, in *CreateRequest, opts ... return out, nil } +func (c *runtimeService) Get(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error) { + req := c.c.NewRequest(c.name, "Runtime.Get", in) + out := new(GetResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *runtimeService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) { req := c.c.NewRequest(c.name, "Runtime.Delete", in) out := new(DeleteResponse) @@ -102,6 +113,7 @@ func (c *runtimeService) List(ctx context.Context, in *ListRequest, opts ...clie type RuntimeHandler interface { Create(context.Context, *CreateRequest, *CreateResponse) error + Get(context.Context, *GetRequest, *GetResponse) error Delete(context.Context, *DeleteRequest, *DeleteResponse) error Update(context.Context, *UpdateRequest, *UpdateResponse) error List(context.Context, *ListRequest, *ListResponse) error @@ -110,6 +122,7 @@ type RuntimeHandler interface { func RegisterRuntimeHandler(s server.Server, hdlr RuntimeHandler, opts ...server.HandlerOption) error { type runtime interface { Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error + Get(ctx context.Context, in *GetRequest, out *GetResponse) error Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error List(ctx context.Context, in *ListRequest, out *ListResponse) error @@ -129,6 +142,10 @@ func (h *runtimeHandler) Create(ctx context.Context, in *CreateRequest, out *Cre return h.RuntimeHandler.Create(ctx, in, out) } +func (h *runtimeHandler) Get(ctx context.Context, in *GetRequest, out *GetResponse) error { + return h.RuntimeHandler.Get(ctx, in, out) +} + func (h *runtimeHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error { return h.RuntimeHandler.Delete(ctx, in, out) } diff --git a/runtime/service/proto/runtime.pb.go b/runtime/service/proto/runtime.pb.go index 2ff2cae8..b34df91d 100644 --- a/runtime/service/proto/runtime.pb.go +++ b/runtime/service/proto/runtime.pb.go @@ -1,13 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: micro/go-micro/runtime/service/proto/runtime.proto +// source: runtime.proto package go_micro_runtime import ( - context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" math "math" ) @@ -42,7 +40,7 @@ func (m *Service) Reset() { *m = Service{} } func (m *Service) String() string { return proto.CompactTextString(m) } func (*Service) ProtoMessage() {} func (*Service) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{0} + return fileDescriptor_86e2dd377c869464, []int{0} } func (m *Service) XXX_Unmarshal(b []byte) error { @@ -98,9 +96,9 @@ func (m *Service) GetExec() string { return "" } -type Options struct { +type CreateOptions struct { // command to pass in - Command string `protobuf:"bytes,1,opt,name=command,proto3" json:"command,omitempty"` + Command []string `protobuf:"bytes,1,rep,name=command,proto3" json:"command,omitempty"` // environment to pass in Env []string `protobuf:"bytes,2,rep,name=env,proto3" json:"env,omitempty"` // output to send to @@ -110,46 +108,46 @@ type Options struct { XXX_sizecache int32 `json:"-"` } -func (m *Options) Reset() { *m = Options{} } -func (m *Options) String() string { return proto.CompactTextString(m) } -func (*Options) ProtoMessage() {} -func (*Options) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{1} +func (m *CreateOptions) Reset() { *m = CreateOptions{} } +func (m *CreateOptions) String() string { return proto.CompactTextString(m) } +func (*CreateOptions) ProtoMessage() {} +func (*CreateOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_86e2dd377c869464, []int{1} } -func (m *Options) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Options.Unmarshal(m, b) +func (m *CreateOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CreateOptions.Unmarshal(m, b) } -func (m *Options) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Options.Marshal(b, m, deterministic) +func (m *CreateOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CreateOptions.Marshal(b, m, deterministic) } -func (m *Options) XXX_Merge(src proto.Message) { - xxx_messageInfo_Options.Merge(m, src) +func (m *CreateOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateOptions.Merge(m, src) } -func (m *Options) XXX_Size() int { - return xxx_messageInfo_Options.Size(m) +func (m *CreateOptions) XXX_Size() int { + return xxx_messageInfo_CreateOptions.Size(m) } -func (m *Options) XXX_DiscardUnknown() { - xxx_messageInfo_Options.DiscardUnknown(m) +func (m *CreateOptions) XXX_DiscardUnknown() { + xxx_messageInfo_CreateOptions.DiscardUnknown(m) } -var xxx_messageInfo_Options proto.InternalMessageInfo +var xxx_messageInfo_CreateOptions proto.InternalMessageInfo -func (m *Options) GetCommand() string { +func (m *CreateOptions) GetCommand() []string { if m != nil { return m.Command } - return "" + return nil } -func (m *Options) GetEnv() []string { +func (m *CreateOptions) GetEnv() []string { if m != nil { return m.Env } return nil } -func (m *Options) GetOutput() string { +func (m *CreateOptions) GetOutput() string { if m != nil { return m.Output } @@ -157,18 +155,18 @@ func (m *Options) GetOutput() string { } type CreateRequest struct { - Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` - Options *Options `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` + Options *CreateOptions `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *CreateRequest) Reset() { *m = CreateRequest{} } func (m *CreateRequest) String() string { return proto.CompactTextString(m) } func (*CreateRequest) ProtoMessage() {} func (*CreateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{2} + return fileDescriptor_86e2dd377c869464, []int{2} } func (m *CreateRequest) XXX_Unmarshal(b []byte) error { @@ -196,7 +194,7 @@ func (m *CreateRequest) GetService() *Service { return nil } -func (m *CreateRequest) GetOptions() *Options { +func (m *CreateRequest) GetOptions() *CreateOptions { if m != nil { return m.Options } @@ -213,7 +211,7 @@ func (m *CreateResponse) Reset() { *m = CreateResponse{} } func (m *CreateResponse) String() string { return proto.CompactTextString(m) } func (*CreateResponse) ProtoMessage() {} func (*CreateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{3} + return fileDescriptor_86e2dd377c869464, []int{3} } func (m *CreateResponse) XXX_Unmarshal(b []byte) error { @@ -234,6 +232,132 @@ func (m *CreateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_CreateResponse proto.InternalMessageInfo +type GetOptions struct { + // version of the service + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetOptions) Reset() { *m = GetOptions{} } +func (m *GetOptions) String() string { return proto.CompactTextString(m) } +func (*GetOptions) ProtoMessage() {} +func (*GetOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_86e2dd377c869464, []int{4} +} + +func (m *GetOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetOptions.Unmarshal(m, b) +} +func (m *GetOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetOptions.Marshal(b, m, deterministic) +} +func (m *GetOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetOptions.Merge(m, src) +} +func (m *GetOptions) XXX_Size() int { + return xxx_messageInfo_GetOptions.Size(m) +} +func (m *GetOptions) XXX_DiscardUnknown() { + xxx_messageInfo_GetOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_GetOptions proto.InternalMessageInfo + +func (m *GetOptions) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + +type GetRequest struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Options *GetOptions `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetRequest) Reset() { *m = GetRequest{} } +func (m *GetRequest) String() string { return proto.CompactTextString(m) } +func (*GetRequest) ProtoMessage() {} +func (*GetRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_86e2dd377c869464, []int{5} +} + +func (m *GetRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetRequest.Unmarshal(m, b) +} +func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetRequest.Marshal(b, m, deterministic) +} +func (m *GetRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetRequest.Merge(m, src) +} +func (m *GetRequest) XXX_Size() int { + return xxx_messageInfo_GetRequest.Size(m) +} +func (m *GetRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetRequest proto.InternalMessageInfo + +func (m *GetRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *GetRequest) GetOptions() *GetOptions { + if m != nil { + return m.Options + } + return nil +} + +type GetResponse struct { + Services []*Service `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetResponse) Reset() { *m = GetResponse{} } +func (m *GetResponse) String() string { return proto.CompactTextString(m) } +func (*GetResponse) ProtoMessage() {} +func (*GetResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_86e2dd377c869464, []int{6} +} + +func (m *GetResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetResponse.Unmarshal(m, b) +} +func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetResponse.Marshal(b, m, deterministic) +} +func (m *GetResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetResponse.Merge(m, src) +} +func (m *GetResponse) XXX_Size() int { + return xxx_messageInfo_GetResponse.Size(m) +} +func (m *GetResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetResponse proto.InternalMessageInfo + +func (m *GetResponse) GetServices() []*Service { + if m != nil { + return m.Services + } + return nil +} + type DeleteRequest struct { Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -245,7 +369,7 @@ func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } func (*DeleteRequest) ProtoMessage() {} func (*DeleteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{4} + return fileDescriptor_86e2dd377c869464, []int{7} } func (m *DeleteRequest) XXX_Unmarshal(b []byte) error { @@ -283,7 +407,7 @@ func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } func (*DeleteResponse) ProtoMessage() {} func (*DeleteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{5} + return fileDescriptor_86e2dd377c869464, []int{8} } func (m *DeleteResponse) XXX_Unmarshal(b []byte) error { @@ -315,7 +439,7 @@ func (m *UpdateRequest) Reset() { *m = UpdateRequest{} } func (m *UpdateRequest) String() string { return proto.CompactTextString(m) } func (*UpdateRequest) ProtoMessage() {} func (*UpdateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{6} + return fileDescriptor_86e2dd377c869464, []int{9} } func (m *UpdateRequest) XXX_Unmarshal(b []byte) error { @@ -353,7 +477,7 @@ func (m *UpdateResponse) Reset() { *m = UpdateResponse{} } func (m *UpdateResponse) String() string { return proto.CompactTextString(m) } func (*UpdateResponse) ProtoMessage() {} func (*UpdateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{7} + return fileDescriptor_86e2dd377c869464, []int{10} } func (m *UpdateResponse) XXX_Unmarshal(b []byte) error { @@ -384,7 +508,7 @@ func (m *ListRequest) Reset() { *m = ListRequest{} } func (m *ListRequest) String() string { return proto.CompactTextString(m) } func (*ListRequest) ProtoMessage() {} func (*ListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{8} + return fileDescriptor_86e2dd377c869464, []int{11} } func (m *ListRequest) XXX_Unmarshal(b []byte) error { @@ -416,7 +540,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} } func (m *ListResponse) String() string { return proto.CompactTextString(m) } func (*ListResponse) ProtoMessage() {} func (*ListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_4bc91a8efec81434, []int{9} + return fileDescriptor_86e2dd377c869464, []int{12} } func (m *ListResponse) XXX_Unmarshal(b []byte) error { @@ -446,9 +570,12 @@ func (m *ListResponse) GetServices() []*Service { func init() { proto.RegisterType((*Service)(nil), "go.micro.runtime.Service") - proto.RegisterType((*Options)(nil), "go.micro.runtime.Options") + proto.RegisterType((*CreateOptions)(nil), "go.micro.runtime.CreateOptions") proto.RegisterType((*CreateRequest)(nil), "go.micro.runtime.CreateRequest") proto.RegisterType((*CreateResponse)(nil), "go.micro.runtime.CreateResponse") + proto.RegisterType((*GetOptions)(nil), "go.micro.runtime.GetOptions") + proto.RegisterType((*GetRequest)(nil), "go.micro.runtime.GetRequest") + proto.RegisterType((*GetResponse)(nil), "go.micro.runtime.GetResponse") proto.RegisterType((*DeleteRequest)(nil), "go.micro.runtime.DeleteRequest") proto.RegisterType((*DeleteResponse)(nil), "go.micro.runtime.DeleteResponse") proto.RegisterType((*UpdateRequest)(nil), "go.micro.runtime.UpdateRequest") @@ -457,205 +584,35 @@ func init() { proto.RegisterType((*ListResponse)(nil), "go.micro.runtime.ListResponse") } -func init() { - proto.RegisterFile("micro/go-micro/runtime/service/proto/runtime.proto", fileDescriptor_4bc91a8efec81434) -} - -var fileDescriptor_4bc91a8efec81434 = []byte{ - // 379 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0xcb, 0x4e, 0xc2, 0x40, - 0x14, 0x86, 0x81, 0x22, 0x95, 0x83, 0x18, 0x32, 0x0b, 0x33, 0x92, 0xa8, 0x4d, 0x57, 0x6c, 0x2c, - 0x09, 0xc4, 0x27, 0x10, 0xe3, 0x46, 0x62, 0x52, 0xe3, 0x03, 0xd4, 0x72, 0x82, 0x4d, 0x6c, 0xa7, - 0xce, 0x4c, 0x51, 0x9f, 0xce, 0x57, 0x33, 0x73, 0x43, 0x81, 0xe2, 0x86, 0xdd, 0xb9, 0x7e, 0xff, - 0x99, 0xbf, 0x29, 0x4c, 0xf2, 0x2c, 0xe5, 0x6c, 0xbc, 0x64, 0xd7, 0x26, 0xe0, 0x55, 0x21, 0xb3, - 0x1c, 0xc7, 0x02, 0xf9, 0x2a, 0x4b, 0x71, 0x5c, 0x72, 0x26, 0xd7, 0xd5, 0x48, 0x67, 0x64, 0xb0, - 0x64, 0x91, 0x9e, 0x8e, 0x6c, 0x3d, 0xfc, 0x00, 0xff, 0xc9, 0x2c, 0x10, 0x02, 0xed, 0x22, 0xc9, - 0x91, 0x36, 0x83, 0xe6, 0xa8, 0x1b, 0xeb, 0x98, 0x50, 0xf0, 0x57, 0xc8, 0x45, 0xc6, 0x0a, 0xda, - 0xd2, 0x65, 0x97, 0x92, 0x33, 0xe8, 0x08, 0x56, 0xf1, 0x14, 0xa9, 0xa7, 0x1b, 0x36, 0x53, 0x94, - 0x32, 0x91, 0xaf, 0xb4, 0x6d, 0x28, 0x2a, 0x56, 0x35, 0xfc, 0xc4, 0x94, 0x1e, 0x99, 0x9a, 0x8a, - 0xc3, 0x39, 0xf8, 0x8f, 0xa5, 0xcc, 0x58, 0x21, 0x94, 0x48, 0xca, 0xf2, 0x3c, 0x29, 0x16, 0x56, - 0xdb, 0xa5, 0x64, 0x00, 0x1e, 0x16, 0x2b, 0xda, 0x0a, 0xbc, 0x51, 0x37, 0x56, 0xa1, 0x92, 0x65, - 0x95, 0x2c, 0x2b, 0xe9, 0x64, 0x4d, 0x16, 0x7e, 0x41, 0xff, 0x96, 0x63, 0x22, 0x31, 0xc6, 0xf7, - 0x0a, 0x85, 0x24, 0x53, 0xf0, 0xad, 0x13, 0x1a, 0xda, 0x9b, 0x9c, 0x47, 0xdb, 0x8f, 0x8f, 0xec, - 0xcb, 0x63, 0x37, 0xa9, 0x96, 0x98, 0x39, 0x4a, 0x3f, 0xb7, 0x76, 0xc9, 0x5e, 0x1d, 0xbb, 0xc9, - 0x70, 0x00, 0xa7, 0x4e, 0x5a, 0x94, 0xac, 0x10, 0x18, 0xce, 0xa0, 0x3f, 0xc3, 0x37, 0x3c, 0xec, - 0x18, 0xc5, 0x75, 0x94, 0x5f, 0xee, 0x73, 0xb9, 0x48, 0x0e, 0xe7, 0x3a, 0x8a, 0xe5, 0xf6, 0xa1, - 0xf7, 0x90, 0x09, 0x69, 0xa9, 0xe1, 0x1d, 0x9c, 0x98, 0xd4, 0xb4, 0xc9, 0x0d, 0x1c, 0xdb, 0x5d, - 0x41, 0x9b, 0x81, 0xf7, 0xbf, 0xcc, 0x7a, 0x74, 0xf2, 0xdd, 0x02, 0x3f, 0x36, 0x5d, 0x32, 0x87, - 0x8e, 0xf1, 0x88, 0x5c, 0xed, 0xae, 0x6e, 0x7c, 0xb8, 0x61, 0xb0, 0x7f, 0xc0, 0x9e, 0xdb, 0x50, - 0x38, 0x63, 0x4d, 0x1d, 0x6e, 0xc3, 0xfa, 0x3a, 0xdc, 0x96, 0xab, 0x1a, 0x67, 0x1c, 0xa9, 0xc3, - 0x6d, 0x38, 0x5e, 0x87, 0xdb, 0x32, 0xb3, 0x41, 0xee, 0xa1, 0xad, 0xfc, 0x23, 0x17, 0xbb, 0xb3, - 0x7f, 0x6c, 0x1e, 0x5e, 0xee, 0x6b, 0x3b, 0xd0, 0x4b, 0x47, 0xff, 0xb5, 0xd3, 0x9f, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x69, 0x49, 0x0f, 0xe1, 0xeb, 0x03, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// RuntimeClient is the client API for Runtime service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type RuntimeClient interface { - Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) - Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) - Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) - List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) -} - -type runtimeClient struct { - cc *grpc.ClientConn -} - -func NewRuntimeClient(cc *grpc.ClientConn) RuntimeClient { - return &runtimeClient{cc} -} - -func (c *runtimeClient) Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) { - out := new(CreateResponse) - err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Create", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *runtimeClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) { - out := new(DeleteResponse) - err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Delete", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *runtimeClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) { - out := new(UpdateResponse) - err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Update", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *runtimeClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { - out := new(ListResponse) - err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/List", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// RuntimeServer is the server API for Runtime service. -type RuntimeServer interface { - Create(context.Context, *CreateRequest) (*CreateResponse, error) - Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) - Update(context.Context, *UpdateRequest) (*UpdateResponse, error) - List(context.Context, *ListRequest) (*ListResponse, error) -} - -func RegisterRuntimeServer(s *grpc.Server, srv RuntimeServer) { - s.RegisterService(&_Runtime_serviceDesc, srv) -} - -func _Runtime_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RuntimeServer).Create(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.runtime.Runtime/Create", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RuntimeServer).Create(ctx, req.(*CreateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Runtime_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RuntimeServer).Delete(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.runtime.Runtime/Delete", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RuntimeServer).Delete(ctx, req.(*DeleteRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Runtime_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UpdateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RuntimeServer).Update(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.runtime.Runtime/Update", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RuntimeServer).Update(ctx, req.(*UpdateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Runtime_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RuntimeServer).List(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.runtime.Runtime/List", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RuntimeServer).List(ctx, req.(*ListRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Runtime_serviceDesc = grpc.ServiceDesc{ - ServiceName: "go.micro.runtime.Runtime", - HandlerType: (*RuntimeServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Create", - Handler: _Runtime_Create_Handler, - }, - { - MethodName: "Delete", - Handler: _Runtime_Delete_Handler, - }, - { - MethodName: "Update", - Handler: _Runtime_Update_Handler, - }, - { - MethodName: "List", - Handler: _Runtime_List_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "micro/go-micro/runtime/service/proto/runtime.proto", +func init() { proto.RegisterFile("runtime.proto", fileDescriptor_86e2dd377c869464) } + +var fileDescriptor_86e2dd377c869464 = []byte{ + // 425 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xc9, 0xcb, 0xd3, 0x40, + 0x14, 0xff, 0xda, 0xd4, 0x44, 0x5f, 0x8c, 0x94, 0x39, 0xc8, 0x58, 0x5c, 0xca, 0x1c, 0xc4, 0x53, + 0x0e, 0x2d, 0x0a, 0x9e, 0x8d, 0xf4, 0x62, 0x11, 0x52, 0x04, 0xaf, 0x31, 0x7d, 0x68, 0xc0, 0x64, + 0x62, 0x66, 0x52, 0xbd, 0x79, 0xf2, 0xff, 0x96, 0xd9, 0xba, 0xa4, 0x93, 0xef, 0xd2, 0xdb, 0xbc, + 0xa5, 0xbf, 0xf7, 0x5b, 0x4a, 0x20, 0xe9, 0xfa, 0x46, 0x56, 0x35, 0xa6, 0x6d, 0xc7, 0x25, 0x27, + 0xf3, 0xef, 0x3c, 0xad, 0xab, 0xb2, 0xe3, 0xa9, 0xed, 0xb3, 0xdf, 0x10, 0xed, 0xb0, 0x3b, 0x54, + 0x25, 0x12, 0x02, 0xb3, 0xa6, 0xa8, 0x91, 0x4e, 0x96, 0x93, 0x37, 0x8f, 0x72, 0xfd, 0x26, 0x14, + 0xa2, 0x03, 0x76, 0xa2, 0xe2, 0x0d, 0x9d, 0xea, 0xb6, 0x2b, 0xc9, 0x53, 0x08, 0x05, 0xef, 0xbb, + 0x12, 0x69, 0xa0, 0x07, 0xb6, 0x52, 0x28, 0x6d, 0x21, 0x7f, 0xd0, 0x99, 0x41, 0x51, 0x6f, 0xd5, + 0xc3, 0x3f, 0x58, 0xd2, 0x07, 0xa6, 0xa7, 0xde, 0x6c, 0x07, 0xc9, 0x87, 0x0e, 0x0b, 0x89, 0x9f, + 0x5b, 0x59, 0xf1, 0x46, 0xa8, 0x53, 0x25, 0xaf, 0xeb, 0xa2, 0xd9, 0xd3, 0xc9, 0x32, 0x50, 0xa7, + 0x6c, 0x49, 0xe6, 0x10, 0x60, 0x73, 0xa0, 0x53, 0xdd, 0x55, 0x4f, 0x75, 0x9c, 0xf7, 0xb2, 0xed, + 0xa5, 0x3b, 0x6e, 0x2a, 0xf6, 0xd7, 0x81, 0xe6, 0xf8, 0xab, 0x47, 0x21, 0xc9, 0x1a, 0x22, 0x61, + 0xe4, 0x69, 0x59, 0xf1, 0xea, 0x59, 0x3a, 0xb4, 0x20, 0xb5, 0xfa, 0x73, 0xb7, 0x49, 0xde, 0x43, + 0xc4, 0x0d, 0x29, 0x2d, 0x3a, 0x5e, 0xbd, 0xba, 0xfe, 0xd1, 0x05, 0xf7, 0xdc, 0xed, 0xb3, 0x39, + 0x3c, 0x71, 0x04, 0x44, 0xcb, 0x1b, 0x81, 0xec, 0x35, 0xc0, 0x06, 0xe5, 0x99, 0x48, 0xbf, 0x9f, + 0xec, 0xab, 0xde, 0x73, 0xbc, 0x7d, 0x59, 0xbc, 0x1b, 0xd2, 0x7a, 0x7e, 0x4d, 0xeb, 0x74, 0xea, + 0xc4, 0x29, 0x83, 0x58, 0x23, 0x1b, 0x42, 0xe4, 0x2d, 0x3c, 0xb4, 0x42, 0x85, 0x36, 0xfa, 0x5e, + 0x4f, 0x8e, 0xab, 0x2c, 0x83, 0x24, 0xc3, 0x9f, 0x78, 0x9b, 0xb5, 0xca, 0x1f, 0x87, 0x62, 0xfd, + 0xc9, 0x20, 0xf9, 0xd2, 0xee, 0x8b, 0xdb, 0x71, 0x1d, 0x8a, 0xc5, 0x4d, 0x20, 0xfe, 0x54, 0x09, + 0x67, 0x28, 0xfb, 0x08, 0x8f, 0x4d, 0x79, 0x93, 0x0b, 0xab, 0x7f, 0x01, 0x44, 0xb9, 0x99, 0x92, + 0x2d, 0x84, 0x26, 0x6b, 0x32, 0xfa, 0xff, 0xb0, 0xd7, 0x17, 0xcb, 0xf1, 0x05, 0x4b, 0xf7, 0x8e, + 0x64, 0x10, 0x6c, 0x50, 0x12, 0x7f, 0xa8, 0x0e, 0xe8, 0xc5, 0xc8, 0xf4, 0x88, 0xb2, 0x85, 0xd0, + 0x18, 0xec, 0x23, 0x75, 0x11, 0xa0, 0x8f, 0xd4, 0x20, 0x1b, 0x0d, 0x67, 0x7c, 0xf5, 0xc1, 0x5d, + 0xe4, 0xe6, 0x83, 0x1b, 0x44, 0x72, 0x47, 0x36, 0x30, 0x53, 0x29, 0x10, 0x8f, 0x8c, 0xb3, 0xb0, + 0x16, 0x2f, 0xc7, 0xc6, 0x0e, 0xe8, 0x5b, 0xa8, 0xbf, 0x67, 0xeb, 0xff, 0x01, 0x00, 0x00, 0xff, + 0xff, 0x19, 0x21, 0xd3, 0xfb, 0xe0, 0x04, 0x00, 0x00, } diff --git a/runtime/service/proto/runtime.proto b/runtime/service/proto/runtime.proto index eb5bb128..4a6b1046 100644 --- a/runtime/service/proto/runtime.proto +++ b/runtime/service/proto/runtime.proto @@ -4,6 +4,7 @@ package go.micro.runtime; service Runtime { rpc Create(CreateRequest) returns (CreateResponse) {}; + rpc Get(GetRequest) returns (GetResponse) {}; rpc Delete(DeleteRequest) returns (DeleteResponse) {}; rpc Update(UpdateRequest) returns (UpdateResponse) {}; rpc List(ListRequest) returns (ListResponse) {}; @@ -22,9 +23,9 @@ message Service { string exec = 5; } -message Options { +message CreateOptions { // command to pass in - string command = 1; + repeated string command = 1; // environment to pass in repeated string env = 2; // output to send to @@ -33,11 +34,25 @@ message Options { message CreateRequest { Service service = 1; - Options options = 2; + CreateOptions options = 2; } message CreateResponse {} +message GetOptions { + // version of the service + string version = 2; +} + +message GetRequest { + string name = 1; + GetOptions options = 2; +} + +message GetResponse { + repeated Service services = 1; +} + message DeleteRequest { Service service = 1; } From 41077334534c69cc266de95262f3da4d0b7f5723 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 16 Nov 2019 02:55:11 -0800 Subject: [PATCH 216/344] Memory registry from #801 with additional tweaks (#951) * PoC: memory registry using maps instead of slice madness * Updated proto and handlers. Fixed tests across codebase. * Implemented ttl pruning for memory registry * Added extensive memory registry tests * Squased a bunch of bugs * Proto indent; memory.Registry.String() returns "memory" * Write a test to prove memory registry TTLs are busted Signed-off-by: Erik Hollensbe * Additional memory testing and fixups: * DefaultTTL removed * When TTL == 0, it is automatically removed from expiry conditions * Additional improvements to new tests Signed-off-by: Erik Hollensbe --- broker/http_broker_test.go | 8 +- client/rpc_client_test.go | 5 +- client/selector/default_test.go | 4 +- function_test.go | 3 +- go.mod | 6 +- go.sum | 55 ++++ registry/memory/memory.go | 314 ++++++++++------------- registry/memory/memory_test.go | 118 +++++++++ registry/memory/options.go | 19 +- registry/memory/util.go | 87 +++++++ registry/service/proto/registry.pb.go | 350 +++++--------------------- service_test.go | 3 +- 12 files changed, 476 insertions(+), 496 deletions(-) create mode 100644 registry/memory/util.go diff --git a/broker/http_broker_test.go b/broker/http_broker_test.go index c3849ac6..3b9653fa 100644 --- a/broker/http_broker_test.go +++ b/broker/http_broker_test.go @@ -7,15 +7,13 @@ import ( glog "github.com/go-log/log" "github.com/google/uuid" + "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/memory" "github.com/micro/go-micro/util/log" ) -func newTestRegistry() *memory.Registry { - r := memory.NewRegistry() - m := r.(*memory.Registry) - m.Services = testData - return m +func newTestRegistry() registry.Registry { + return memory.NewRegistry(memory.Services(testData)) } func sub(be *testing.B, c int) { diff --git a/client/rpc_client_test.go b/client/rpc_client_test.go index 88cd08d8..f9dbc04d 100644 --- a/client/rpc_client_test.go +++ b/client/rpc_client_test.go @@ -12,10 +12,7 @@ import ( ) func newTestRegistry() registry.Registry { - r := memory.NewRegistry() - reg := r.(*memory.Registry) - reg.Services = testData - return reg + return memory.NewRegistry(memory.Services(testData)) } func TestCallAddress(t *testing.T) { diff --git a/client/selector/default_test.go b/client/selector/default_test.go index 77075204..948eedcd 100644 --- a/client/selector/default_test.go +++ b/client/selector/default_test.go @@ -9,9 +9,7 @@ import ( func TestRegistrySelector(t *testing.T) { counts := map[string]int{} - r := memory.NewRegistry() - rg := r.(*memory.Registry) - rg.Services = testData + r := memory.NewRegistry(memory.Services(testData)) cache := NewSelector(Registry(r)) next, err := cache.Select("foo") diff --git a/function_test.go b/function_test.go index a7d1b18d..44177cb9 100644 --- a/function_test.go +++ b/function_test.go @@ -13,8 +13,7 @@ func TestFunction(t *testing.T) { var wg sync.WaitGroup wg.Add(1) - r := memory.NewRegistry() - r.(*memory.Registry).Services = testData + r := memory.NewRegistry(memory.Services(testData)) // create service fn := NewFunction( diff --git a/go.mod b/go.mod index c83307cc..48696ba9 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/bitly/go-simplejson v0.5.0 github.com/bwmarrin/discordgo v0.20.1 github.com/coreos/etcd v3.3.17+incompatible - github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c github.com/fsnotify/fsnotify v1.4.7 github.com/fsouza/go-dockerclient v1.6.0 @@ -16,7 +15,6 @@ require ( github.com/go-acme/lego/v3 v3.1.0 github.com/go-log/log v0.1.0 github.com/go-playground/locales v0.13.0 // indirect - github.com/go-playground/universal-translator v0.16.0 // indirect github.com/golang/protobuf v1.3.2 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 @@ -32,13 +30,13 @@ require ( github.com/mholt/certmagic v0.8.3 github.com/micro/cli v0.2.0 github.com/micro/mdns v0.3.0 - github.com/miekg/dns v1.1.15 + github.com/micro/protoc-gen-micro v1.0.0 // indirect + github.com/miekg/dns v1.1.22 github.com/mitchellh/hashstructure v1.0.0 github.com/nats-io/nats.go v1.9.1 github.com/nlopes/slack v0.6.0 github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c github.com/pkg/errors v0.8.1 - github.com/technoweenie/multipartstreamer v1.0.1 // indirect go.uber.org/zap v1.12.0 // indirect golang.org/x/crypto v0.0.0-20191108234033-bd318be0434a golang.org/x/net v0.0.0-20191109021931-daa7c04131f5 diff --git a/go.sum b/go.sum index 33216a46..245c8799 100644 --- a/go.sum +++ b/go.sum @@ -18,7 +18,9 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c/go.mod h1:7xhjOwRV2+0HXGmM0jxaEu+ZiXJFoVZOTfL/dmqbrD8= github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -43,6 +45,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/bwmarrin/discordgo v0.20.1 h1:Ihh3/mVoRwy3otmaoPDUioILBJq4fdWkpsi83oj2Lmk= github.com/bwmarrin/discordgo v0.20.1/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= @@ -59,16 +63,20 @@ github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0 h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.17+incompatible h1:f/Z3EoDSx1yjaIjLQGo1diYUlQYSBrrAQ5vP8NjwXwo= github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/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/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok= @@ -83,6 +91,7 @@ github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s9 github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23 h1:oqgGT9O61YAYvI41EBsLePOr+LE6roB0xY4gpkZuFSE= github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= @@ -103,6 +112,7 @@ github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c h1:pBgVXWDXj github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY= 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/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA= github.com/fsouza/go-dockerclient v1.6.0 h1:f7j+AX94143JL1H3TiqSMkM4EcLDI0De1qD4GGn3Hig= github.com/fsouza/go-dockerclient v1.6.0/go.mod h1:YWwtNPuL4XTX1SKJQk86cWPmmqwx+4np9qfPbb+znGc= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -119,11 +129,13 @@ 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-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -132,6 +144,7 @@ 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/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -164,6 +177,8 @@ github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -175,12 +190,14 @@ 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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= +github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1 h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA= github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -209,17 +226,20 @@ 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/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= +github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= +github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= github.com/lucas-clemente/quic-go v0.13.1 h1:CxtJTXQIh2aboCPk0M6vf530XOov6DZjVBiSE3nSj8s= github.com/lucas-clemente/quic-go v0.13.1/go.mod h1:Vn3/Fb0/77b02SGhQk36KzOUmXgVpFfizUfW5WMaqyU= github.com/marten-seemann/chacha20 v0.2.0 h1:f40vqzzx+3GdOmzQoItkLX5WLvHgPgyYqFFIO5Gh4hQ= github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1HFkWoEwNDb4TMtE= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= +github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/marten-seemann/qtls v0.4.1 h1:YlT8QP3WCCvvok7MGEZkMldXbyqgr8oFg5/n8Gtbkks= github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -227,15 +247,21 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mholt/certmagic v0.7.5/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= github.com/mholt/certmagic v0.8.3 h1:JOUiX9IAZbbgyjNP2GY6v/6lorH+9GkZsc7ktMpGCSo= github.com/mholt/certmagic v0.8.3/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= github.com/micro/cli v0.2.0 h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA= github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= +github.com/micro/go-micro v1.16.0/go.mod h1:A0F58bHLh2m0LAI9QyhvmbN8c1cxhAZo3cM6s+iDsrM= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= +github.com/micro/protoc-gen-micro v1.0.0 h1:qKh5S3I1RfenhIs5mqDFJLwRlRDlgin7XWiUKZbpwLM= +github.com/micro/protoc-gen-micro v1.0.0/go.mod h1:C8ij4DJhapBmypcT00AXdb0cZ675/3PqUO02buWWqbE= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.22 h1:Jm64b3bO9kP43ddLjL2EY3Io6bmy1qGb9Xxz6TqS6rc= +github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= 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-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= @@ -254,8 +280,11 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats-server/v2 v2.1.0/go.mod h1:r5y0WgCag0dTj/qiHkHrXAcKQ/f5GMOZaEGdoxxnJ4I= +github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -280,6 +309,7 @@ github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJ github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= @@ -324,6 +354,7 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -336,6 +367,7 @@ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -347,32 +379,42 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 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/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.12.0 h1:dySoUQPFBGj6xwjmBzageVL8jGi8uxc6bEmJQjA06bw= go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191108234033-bd318be0434a h1:R/qVym5WAxsZWQqZCwDY/8sdVKV1m1WgU4/S5IRQAzc= golang.org/x/crypto v0.0.0-20191108234033-bd318be0434a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -400,7 +442,9 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191011234655-491137f69257/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191109021931-daa7c04131f5 h1:bHNaocaoJxYBo5cw41UyTMLjYlb8wPY7+WFrnklbHOM= golang.org/x/net v0.0.0-20191109021931-daa7c04131f5/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -423,17 +467,23 @@ golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190221075227-b4e8571b14e0/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-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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4 h1:Hynbrlo6LbYI3H1IqXpkVDOcX/3HiPdhVEuyj5a59RM= +golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -454,6 +504,7 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -471,12 +522,14 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 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/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -484,6 +537,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= @@ -516,3 +570,4 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/registry/memory/memory.go b/registry/memory/memory.go index f3b2e26e..83990377 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -3,7 +3,6 @@ package memory import ( "context" - "strings" "sync" "time" @@ -14,23 +13,29 @@ import ( var ( sendEventTime = 10 * time.Millisecond - ttlPruneTime = 1 * time.Minute - DefaultTTL = 1 * time.Minute + ttlPruneTime = time.Second ) -// node tracks node registration timestamp and TTL type node struct { - lastSeen time.Time - ttl time.Duration + *registry.Node + TTL time.Duration + LastSeen time.Time +} + +type record struct { + Name string + Version string + Metadata map[string]string + Nodes map[string]*node + Endpoints []*registry.Endpoint } type Registry struct { options registry.Options sync.RWMutex - Services map[string][]*registry.Service - nodes map[string]*node - Watchers map[string]*Watcher + records map[string]map[string]*record + watchers map[string]*Watcher } func NewRegistry(opts ...registry.Option) registry.Registry { @@ -42,16 +47,15 @@ func NewRegistry(opts ...registry.Option) registry.Registry { o(&options) } - services := getServices(options.Context) - if services == nil { - services = make(map[string][]*registry.Service) + records := getServiceRecords(options.Context) + if records == nil { + records = make(map[string]map[string]*record) } reg := &Registry{ options: options, - Services: services, - nodes: make(map[string]*node), - Watchers: make(map[string]*Watcher), + records: records, + watchers: make(map[string]*Watcher), } go reg.ttlPrune() @@ -59,11 +63,6 @@ func NewRegistry(opts ...registry.Option) registry.Registry { return reg } -// nodeTrackId returns a string we use to track a node of a given service -func nodeTrackId(svcName, svcVersion, nodeId string) string { - return svcName + "+" + svcVersion + "+" + nodeId -} - func (m *Registry) ttlPrune() { prune := time.NewTicker(ttlPruneTime) defer prune.Stop() @@ -72,49 +71,26 @@ func (m *Registry) ttlPrune() { select { case <-prune.C: m.Lock() - for nodeTrackId, node := range m.nodes { - // if the TTL has been set and we exceed the hresholdset by it we stop tracking the node - if node.ttl.Seconds() != 0.0 && time.Since(node.lastSeen) > node.ttl { - // split nodeTrackID into service Name, Version and Node Id - trackIdSplit := strings.Split(nodeTrackId, "+") - svcName, svcVersion, nodeId := trackIdSplit[0], trackIdSplit[1], trackIdSplit[2] - log.Debugf("[memory] Registry TTL expired for service %s, node %s", svcName, nodeId) - // we need to find a node that expired and delete it from service nodes - if _, ok := m.Services[svcName]; ok { - for _, service := range m.Services[svcName] { - if service.Version != svcVersion { - continue - } - // find expired service node and delete it - var nodes []*registry.Node - for _, n := range service.Nodes { - var del bool - if n.Id == nodeId { - del = true - } - if !del { - nodes = append(nodes, n) - } - } - service.Nodes = nodes + for name, records := range m.records { + for version, record := range records { + for id, n := range record.Nodes { + if n.TTL != 0 && time.Since(n.LastSeen) > n.TTL { + log.Debugf("Registry TTL expired for node %s of service %s", n.Id, name) + delete(m.records[name][version].Nodes, id) } } - // stop tracking the node - delete(m.nodes, nodeTrackId) } } m.Unlock() } } - - return } func (m *Registry) sendEvent(r *registry.Result) { - watchers := make([]*Watcher, 0, len(m.Watchers)) + watchers := make([]*Watcher, 0, len(m.watchers)) m.RLock() - for _, w := range m.Watchers { + for _, w := range m.watchers { watchers = append(watchers, w) } m.RUnlock() @@ -123,7 +99,7 @@ func (m *Registry) sendEvent(r *registry.Result) { select { case <-w.exit: m.Lock() - delete(m.Watchers, w.id) + delete(m.watchers, w.id) m.Unlock() default: select { @@ -141,11 +117,24 @@ func (m *Registry) Init(opts ...registry.Option) error { // add services m.Lock() - for k, v := range getServices(m.options.Context) { - s := m.Services[k] - m.Services[k] = registry.Merge(s, v) + defer m.Unlock() + + records := getServiceRecords(m.options.Context) + for name, record := range records { + // add a whole new service including all of its versions + if _, ok := m.records[name]; !ok { + m.records[name] = record + continue + } + // add the versions of the service we dont track yet + for version, r := range record { + if _, ok := m.records[name][version]; !ok { + m.records[name][version] = r + continue + } + } } - m.Unlock() + return nil } @@ -153,104 +142,61 @@ func (m *Registry) Options() registry.Options { return m.options } -func (m *Registry) GetService(name string) ([]*registry.Service, error) { - m.RLock() - service, ok := m.Services[name] - m.RUnlock() - if !ok { - return nil, registry.ErrNotFound - } - - return service, nil -} - -func (m *Registry) ListServices() ([]*registry.Service, error) { - var services []*registry.Service - m.RLock() - 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() - log.Debugf("[memory] Registry registering service: %s", s.Name) - var options registry.RegisterOptions for _, o := range opts { o(&options) } - if service, ok := m.Services[s.Name]; !ok { - m.Services[s.Name] = []*registry.Service{s} - // add all nodes into nodes map to track their TTL - for _, n := range s.Nodes { - log.Debugf("[memory] Registry tracking new service: %s, node %s", s.Name, n.Id) - m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ - lastSeen: time.Now(), - ttl: options.TTL, - } - } + r := serviceToRecord(s, options.TTL) + + if _, ok := m.records[s.Name]; !ok { + m.records[s.Name] = make(map[string]*record) + } + + if _, ok := m.records[s.Name][s.Version]; !ok { + m.records[s.Name][s.Version] = r + log.Debugf("Registry added new service: %s, version: %s", s.Name, s.Version) go m.sendEvent(®istry.Result{Action: "update", Service: s}) return nil - } else { - // svcCount keeps the count of all versions of particular service - //svcCount := len(service) - // svcNodes maintains a list of node Ids per particular service version - svcNodes := make(map[string]map[string][]string) - // collect all service ids for all service versions - for _, s := range service { - if _, ok := svcNodes[s.Name]; !ok { - svcNodes[s.Name] = make(map[string][]string) - } - if _, ok := svcNodes[s.Name][s.Version]; !ok { - for _, n := range s.Nodes { - svcNodes[s.Name][s.Version] = append(svcNodes[s.Name][s.Version], n.Id) - } - } - } - // if merged count and original service counts changed we know we are adding a new version of the service - merged := registry.Merge(service, []*registry.Service{s}) - // if the node count of any service [version] changed we know we are adding a new node to the service - for _, s := range merged { - // we know that if the node counts have changed we need to track new nodes - if len(s.Nodes) != len(svcNodes[s.Name][s.Version]) { - for _, n := range s.Nodes { - var found bool - for _, id := range svcNodes[s.Name][s.Version] { - if n.Id == id { - found = true - break - } - } - if !found { - log.Debugf("[memory] Registry tracking new node: %s for service %s", n.Id, s.Name) - m.nodes[nodeTrackId(s.Name, s.Version, n.Id)] = &node{ - lastSeen: time.Now(), - ttl: options.TTL, - } - } - } - m.Services[s.Name] = merged - go m.sendEvent(®istry.Result{Action: "update", Service: s}) - return nil - } - // refresh the timestamp and TTL of the service node - for _, n := range s.Nodes { - trackId := nodeTrackId(s.Name, s.Version, n.Id) - log.Debugf("[memory] Registry refreshing TTL for node %s for service %s", n.Id, s.Name) - if trackedNode, ok := m.nodes[trackId]; ok { - trackedNode.lastSeen = time.Now() - trackedNode.ttl = options.TTL + } + + addedNodes := false + for _, n := range s.Nodes { + if _, ok := m.records[s.Name][s.Version].Nodes[n.Id]; !ok { + addedNodes = true + metadata := make(map[string]string) + for k, v := range n.Metadata { + metadata[k] = v + m.records[s.Name][s.Version].Nodes[n.Id] = &node{ + Node: ®istry.Node{ + Id: n.Id, + Address: n.Address, + Metadata: metadata, + }, + TTL: options.TTL, + LastSeen: time.Now(), } } } } + if addedNodes { + log.Debugf("Registry added new node to service: %s, version: %s", s.Name, s.Version) + go m.sendEvent(®istry.Result{Action: "update", Service: s}) + return nil + } + + // refresh TTL and timestamp + for _, n := range s.Nodes { + log.Debugf("Updated registration for service: %s, version: %s", s.Name, s.Version) + m.records[s.Name][s.Version].Nodes[n.Id].TTL = options.TTL + m.records[s.Name][s.Version].Nodes[n.Id].LastSeen = time.Now() + } + return nil } @@ -258,57 +204,62 @@ func (m *Registry) Deregister(s *registry.Service) error { m.Lock() defer m.Unlock() - log.Debugf("[memory] Registry deregistering service: %s", s.Name) - - if service, ok := m.Services[s.Name]; ok { - // svcNodes collects the list of all node Ids for each service version - svcNodes := make(map[string]map[string][]string) - // collect all service node ids for all service versions - for _, svc := range service { - if _, ok := svcNodes[svc.Name]; !ok { - svcNodes[svc.Name] = make(map[string][]string) - } - if _, ok := svcNodes[svc.Name][svc.Version]; !ok { - for _, n := range svc.Nodes { - svcNodes[svc.Name][svc.Version] = append(svcNodes[svc.Name][svc.Version], n.Id) + if _, ok := m.records[s.Name]; ok { + if _, ok := m.records[s.Name][s.Version]; ok { + for _, n := range s.Nodes { + if _, ok := m.records[s.Name][s.Version].Nodes[n.Id]; ok { + log.Debugf("Registry removed node from service: %s, version: %s", s.Name, s.Version) + delete(m.records[s.Name][s.Version].Nodes, n.Id) } } - } - // if there are no more services we know we have either removed all nodes or there were no nodes - if updatedService := registry.Remove(service, []*registry.Service{s}); len(updatedService) == 0 { - for _, id := range svcNodes[s.Name][s.Version] { - log.Debugf("[memory] Registry stopped tracking node %s for service %s", id, s.Name) - delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) - go m.sendEvent(®istry.Result{Action: "delete", Service: s}) - } - log.Debugf("[memory] Registry deleting service %s: no service nodes", s.Name) - delete(m.Services, s.Name) - return nil - } else { - // find out which nodes have been removed - for _, id := range svcNodes[s.Name][s.Version] { - for _, svc := range updatedService { - var found bool - for _, n := range svc.Nodes { - if id == n.Id { - found = true - break - } - } - if !found { - log.Debugf("[memory] Registry stopped tracking node %s for service %s", id, s.Name) - delete(m.nodes, nodeTrackId(s.Name, s.Version, id)) - go m.sendEvent(®istry.Result{Action: "delete", Service: s}) - } - } - m.Services[s.Name] = updatedService + if len(m.records[s.Name][s.Version].Nodes) == 0 { + delete(m.records[s.Name], s.Version) + log.Debugf("Registry removed service: %s, version: %s", s.Name, s.Version) } } + if len(m.records[s.Name]) == 0 { + delete(m.records, s.Name) + log.Debugf("Registry removed service: %s", s.Name) + } + go m.sendEvent(®istry.Result{Action: "delete", Service: s}) } return nil } +func (m *Registry) GetService(name string) ([]*registry.Service, error) { + m.RLock() + defer m.RUnlock() + + records, ok := m.records[name] + if !ok { + return nil, registry.ErrNotFound + } + + services := make([]*registry.Service, len(m.records[name])) + i := 0 + for _, record := range records { + services[i] = recordToService(record) + i++ + } + + return services, nil +} + +func (m *Registry) ListServices() ([]*registry.Service, error) { + m.RLock() + defer m.RUnlock() + + var services []*registry.Service + for _, records := range m.records { + for _, record := range records { + services = append(services, recordToService(record)) + } + } + + return services, nil +} + func (m *Registry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { var wo registry.WatchOptions for _, o := range opts { @@ -323,8 +274,9 @@ func (m *Registry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) } m.Lock() - m.Watchers[w.id] = w + m.watchers[w.id] = w m.Unlock() + return w, nil } diff --git a/registry/memory/memory_test.go b/registry/memory/memory_test.go index 593122bf..597beb38 100644 --- a/registry/memory/memory_test.go +++ b/registry/memory/memory_test.go @@ -1,7 +1,9 @@ package memory import ( + "fmt" "testing" + "time" "github.com/micro/go-micro/registry" ) @@ -102,10 +104,20 @@ func TestMemoryRegistry(t *testing.T) { // register data for _, v := range testData { + serviceCount := 0 for _, service := range v { if err := m.Register(service); err != nil { t.Errorf("Unexpected register error: %v", err) } + serviceCount++ + // after the service has been registered we should be able to query it + services, err := m.GetService(service.Name) + if err != nil { + t.Errorf("Unexpected error getting service %s: %v", service.Name, err) + } + if len(services) != serviceCount { + t.Errorf("Expected %d services for %s, got %d", serviceCount, service.Name, len(services)) + } } } @@ -114,6 +126,22 @@ func TestMemoryRegistry(t *testing.T) { fn(k, v) } + services, err := m.ListServices() + if err != nil { + t.Errorf("Unexpected error when listing services: %v", err) + } + + totalServiceCount := 0 + for _, testSvc := range testData { + for range testSvc { + totalServiceCount++ + } + } + + if len(services) != totalServiceCount { + t.Errorf("Expected total service count: %d, got: %d", totalServiceCount, len(services)) + } + // deregister for _, v := range testData { for _, service := range v { @@ -122,4 +150,94 @@ func TestMemoryRegistry(t *testing.T) { } } } + + // after all the service nodes have been deregistered we should not get any results + for _, v := range testData { + for _, service := range v { + services, err := m.GetService(service.Name) + if err != registry.ErrNotFound { + t.Errorf("Expected error: %v, got: %v", registry.ErrNotFound, err) + } + if len(services) != 0 { + t.Errorf("Expected %d services for %s, got %d", 0, service.Name, len(services)) + } + } + } +} + +func TestMemoryRegistryTTL(t *testing.T) { + m := NewRegistry() + + for _, v := range testData { + for _, service := range v { + if err := m.Register(service, registry.RegisterTTL(time.Millisecond)); err != nil { + t.Fatal(err) + } + } + } + + time.Sleep(ttlPruneTime * 2) + + for name := range testData { + svcs, err := m.GetService(name) + if err != nil { + t.Fatal(err) + } + + for _, svc := range svcs { + if len(svc.Nodes) > 0 { + t.Fatalf("Service %q still has nodes registered", name) + } + } + } +} + +func TestMemoryRegistryTTLConcurrent(t *testing.T) { + concurrency := 1000 + waitTime := ttlPruneTime * 2 + m := NewRegistry() + + for _, v := range testData { + for _, service := range v { + if err := m.Register(service, registry.RegisterTTL(waitTime)); err != nil { + t.Fatal(err) + } + } + } + + t.Logf("test will wait %v, then check TTL timeouts", waitTime) + + errChan := make(chan error, concurrency) + syncChan := make(chan struct{}) + + for i := 0; i < concurrency; i++ { + go func() { + <-syncChan + for name := range testData { + svcs, err := m.GetService(name) + if err != nil { + errChan <- err + return + } + + for _, svc := range svcs { + if len(svc.Nodes) > 0 { + errChan <- fmt.Errorf("Service %q still has nodes registered", name) + return + } + } + } + + errChan <- nil + }() + } + + time.Sleep(waitTime) + close(syncChan) + + for i := 0; i < concurrency; i++ { + if err := <-errChan; err != nil { + t.Fatal(err) + } + } } diff --git a/registry/memory/options.go b/registry/memory/options.go index 64680fdc..7922dcaa 100644 --- a/registry/memory/options.go +++ b/registry/memory/options.go @@ -8,12 +8,25 @@ import ( type servicesKey struct{} -func getServices(ctx context.Context) map[string][]*registry.Service { - s, ok := ctx.Value(servicesKey{}).(map[string][]*registry.Service) +func getServiceRecords(ctx context.Context) map[string]map[string]*record { + memServices, ok := ctx.Value(servicesKey{}).(map[string][]*registry.Service) if !ok { return nil } - return s + + services := make(map[string]map[string]*record) + + for name, svc := range memServices { + if _, ok := services[name]; !ok { + services[name] = make(map[string]*record) + } + // go through every version of the service + for _, s := range svc { + services[s.Name][s.Version] = serviceToRecord(s, 0) + } + } + + return services } // Services is an option that preloads service data diff --git a/registry/memory/util.go b/registry/memory/util.go new file mode 100644 index 00000000..e49f30c8 --- /dev/null +++ b/registry/memory/util.go @@ -0,0 +1,87 @@ +package memory + +import ( + "time" + + "github.com/micro/go-micro/registry" +) + +func serviceToRecord(s *registry.Service, ttl time.Duration) *record { + metadata := make(map[string]string) + for k, v := range s.Metadata { + metadata[k] = v + } + + nodes := make(map[string]*node) + for _, n := range s.Nodes { + nodes[n.Id] = &node{ + Node: n, + TTL: ttl, + LastSeen: time.Now(), + } + } + + endpoints := make([]*registry.Endpoint, len(s.Endpoints)) + for i, e := range s.Endpoints { + endpoints[i] = e + } + + return &record{ + Name: s.Name, + Version: s.Version, + Metadata: metadata, + Nodes: nodes, + Endpoints: endpoints, + } +} + +func recordToService(r *record) *registry.Service { + metadata := make(map[string]string) + for k, v := range r.Metadata { + metadata[k] = v + } + + endpoints := make([]*registry.Endpoint, len(r.Endpoints)) + for i, e := range r.Endpoints { + request := new(registry.Value) + request = e.Request + response := new(registry.Value) + response = e.Response + + metadata := make(map[string]string) + for k, v := range e.Metadata { + metadata[k] = v + } + + endpoints[i] = ®istry.Endpoint{ + Name: e.Name, + Request: request, + Response: response, + Metadata: metadata, + } + } + + nodes := make([]*registry.Node, len(r.Nodes)) + i := 0 + for _, n := range r.Nodes { + metadata := make(map[string]string) + for k, v := range n.Metadata { + metadata[k] = v + } + + nodes[i] = ®istry.Node{ + Id: n.Id, + Address: n.Address, + Metadata: metadata, + } + i++ + } + + return ®istry.Service{ + Name: r.Name, + Version: r.Version, + Metadata: metadata, + Endpoints: endpoints, + Nodes: nodes, + } +} diff --git a/registry/service/proto/registry.pb.go b/registry/service/proto/registry.pb.go index 6427812b..99d20bdb 100644 --- a/registry/service/proto/registry.pb.go +++ b/registry/service/proto/registry.pb.go @@ -1,13 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: micro/go-micro/registry/service/proto/registry.proto +// source: go-micro/registry/service/proto/registry.proto package go_micro_registry import ( - context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" math "math" ) @@ -48,7 +46,7 @@ func (x EventType) String() string { } func (EventType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{0} + return fileDescriptor_0e39fd3e4b9b6e63, []int{0} } // Service represents a go-micro service @@ -68,7 +66,7 @@ func (m *Service) Reset() { *m = Service{} } func (m *Service) String() string { return proto.CompactTextString(m) } func (*Service) ProtoMessage() {} func (*Service) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{0} + return fileDescriptor_0e39fd3e4b9b6e63, []int{0} } func (m *Service) XXX_Unmarshal(b []byte) error { @@ -146,7 +144,7 @@ func (m *Node) Reset() { *m = Node{} } func (m *Node) String() string { return proto.CompactTextString(m) } func (*Node) ProtoMessage() {} func (*Node) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{1} + return fileDescriptor_0e39fd3e4b9b6e63, []int{1} } func (m *Node) XXX_Unmarshal(b []byte) error { @@ -210,7 +208,7 @@ func (m *Endpoint) Reset() { *m = Endpoint{} } func (m *Endpoint) String() string { return proto.CompactTextString(m) } func (*Endpoint) ProtoMessage() {} func (*Endpoint) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{2} + return fileDescriptor_0e39fd3e4b9b6e63, []int{2} } func (m *Endpoint) XXX_Unmarshal(b []byte) error { @@ -273,7 +271,7 @@ func (m *Value) Reset() { *m = Value{} } func (m *Value) String() string { return proto.CompactTextString(m) } func (*Value) ProtoMessage() {} func (*Value) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{3} + return fileDescriptor_0e39fd3e4b9b6e63, []int{3} } func (m *Value) XXX_Unmarshal(b []byte) error { @@ -327,7 +325,7 @@ func (m *Options) Reset() { *m = Options{} } func (m *Options) String() string { return proto.CompactTextString(m) } func (*Options) ProtoMessage() {} func (*Options) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{4} + return fileDescriptor_0e39fd3e4b9b6e63, []int{4} } func (m *Options) XXX_Unmarshal(b []byte) error { @@ -369,7 +367,7 @@ func (m *Result) Reset() { *m = Result{} } func (m *Result) String() string { return proto.CompactTextString(m) } func (*Result) ProtoMessage() {} func (*Result) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{5} + return fileDescriptor_0e39fd3e4b9b6e63, []int{5} } func (m *Result) XXX_Unmarshal(b []byte) error { @@ -421,7 +419,7 @@ func (m *EmptyResponse) Reset() { *m = EmptyResponse{} } func (m *EmptyResponse) String() string { return proto.CompactTextString(m) } func (*EmptyResponse) ProtoMessage() {} func (*EmptyResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{6} + return fileDescriptor_0e39fd3e4b9b6e63, []int{6} } func (m *EmptyResponse) XXX_Unmarshal(b []byte) error { @@ -453,7 +451,7 @@ func (m *GetRequest) Reset() { *m = GetRequest{} } func (m *GetRequest) String() string { return proto.CompactTextString(m) } func (*GetRequest) ProtoMessage() {} func (*GetRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{7} + return fileDescriptor_0e39fd3e4b9b6e63, []int{7} } func (m *GetRequest) XXX_Unmarshal(b []byte) error { @@ -492,7 +490,7 @@ func (m *GetResponse) Reset() { *m = GetResponse{} } func (m *GetResponse) String() string { return proto.CompactTextString(m) } func (*GetResponse) ProtoMessage() {} func (*GetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{8} + return fileDescriptor_0e39fd3e4b9b6e63, []int{8} } func (m *GetResponse) XXX_Unmarshal(b []byte) error { @@ -530,7 +528,7 @@ func (m *ListRequest) Reset() { *m = ListRequest{} } func (m *ListRequest) String() string { return proto.CompactTextString(m) } func (*ListRequest) ProtoMessage() {} func (*ListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{9} + return fileDescriptor_0e39fd3e4b9b6e63, []int{9} } func (m *ListRequest) XXX_Unmarshal(b []byte) error { @@ -562,7 +560,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} } func (m *ListResponse) String() string { return proto.CompactTextString(m) } func (*ListResponse) ProtoMessage() {} func (*ListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{10} + return fileDescriptor_0e39fd3e4b9b6e63, []int{10} } func (m *ListResponse) XXX_Unmarshal(b []byte) error { @@ -602,7 +600,7 @@ func (m *WatchRequest) Reset() { *m = WatchRequest{} } func (m *WatchRequest) String() string { return proto.CompactTextString(m) } func (*WatchRequest) ProtoMessage() {} func (*WatchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{11} + return fileDescriptor_0e39fd3e4b9b6e63, []int{11} } func (m *WatchRequest) XXX_Unmarshal(b []byte) error { @@ -649,7 +647,7 @@ func (m *Event) Reset() { *m = Event{} } func (m *Event) String() string { return proto.CompactTextString(m) } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { - return fileDescriptor_2f73432195c6499a, []int{12} + return fileDescriptor_0e39fd3e4b9b6e63, []int{12} } func (m *Event) XXX_Unmarshal(b []byte) error { @@ -719,284 +717,52 @@ func init() { } func init() { - proto.RegisterFile("micro/go-micro/registry/service/proto/registry.proto", fileDescriptor_2f73432195c6499a) + proto.RegisterFile("go-micro/registry/service/proto/registry.proto", fileDescriptor_0e39fd3e4b9b6e63) } -var fileDescriptor_2f73432195c6499a = []byte{ - // 681 bytes of a gzipped FileDescriptorProto +var fileDescriptor_0e39fd3e4b9b6e63 = []byte{ + // 679 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xdd, 0x6e, 0xd3, 0x4c, 0x10, 0x8d, 0xed, 0xfc, 0x4e, 0xda, 0x7e, 0xfd, 0x46, 0x08, 0x8c, 0x5b, 0x20, 0xb2, 0x04, 0x0a, - 0x48, 0x4d, 0xaa, 0x50, 0x21, 0x7e, 0xae, 0x10, 0x0d, 0x95, 0x50, 0x0b, 0x62, 0xf9, 0xbb, 0x36, + 0x48, 0x75, 0xaa, 0x50, 0x21, 0x7e, 0xae, 0x10, 0x0d, 0x95, 0x50, 0x0b, 0x62, 0xf9, 0xbb, 0x36, 0xf1, 0xa8, 0x58, 0x24, 0xb6, 0xd9, 0xdd, 0x46, 0xca, 0x3b, 0x20, 0xf1, 0x04, 0xbc, 0x0d, 0x4f, - 0xc1, 0xd3, 0xa0, 0x5d, 0xaf, 0x93, 0x54, 0xdd, 0x04, 0xa4, 0xc2, 0xdd, 0xcc, 0xee, 0x39, 0xb3, - 0xb3, 0x67, 0xce, 0xda, 0x70, 0x30, 0x49, 0x46, 0x3c, 0xeb, 0x9f, 0x66, 0x7b, 0x45, 0xc0, 0xe9, - 0x34, 0x11, 0x92, 0xcf, 0xfa, 0x82, 0xf8, 0x34, 0x19, 0x51, 0x3f, 0xe7, 0x99, 0x5c, 0x2c, 0xf7, - 0x74, 0x8a, 0xff, 0x9f, 0x66, 0x3d, 0x8d, 0xef, 0x95, 0x1b, 0xe1, 0x4f, 0x17, 0x1a, 0x6f, 0x0a, - 0x0e, 0x22, 0x54, 0xd3, 0x68, 0x42, 0xbe, 0xd3, 0x71, 0xba, 0x2d, 0xa6, 0x63, 0xf4, 0xa1, 0x31, - 0x25, 0x2e, 0x92, 0x2c, 0xf5, 0x5d, 0xbd, 0x5c, 0xa6, 0x78, 0x08, 0xcd, 0x09, 0xc9, 0x28, 0x8e, - 0x64, 0xe4, 0x7b, 0x1d, 0xaf, 0xdb, 0x1e, 0x74, 0x7b, 0x17, 0xea, 0xf7, 0x4c, 0xed, 0xde, 0x89, - 0x81, 0x0e, 0x53, 0xc9, 0x67, 0x6c, 0xce, 0xc4, 0x47, 0xd0, 0xa2, 0x34, 0xce, 0xb3, 0x24, 0x95, - 0xc2, 0xaf, 0xea, 0x32, 0x3b, 0x96, 0x32, 0x43, 0x83, 0x61, 0x0b, 0x34, 0xee, 0x41, 0x2d, 0xcd, - 0x62, 0x12, 0x7e, 0x4d, 0xd3, 0xae, 0x59, 0x68, 0x2f, 0xb3, 0x98, 0x58, 0x81, 0xc2, 0x03, 0x68, - 0x64, 0xb9, 0x4c, 0xb2, 0x54, 0xf8, 0xf5, 0x8e, 0xd3, 0x6d, 0x0f, 0x02, 0x0b, 0xe1, 0x55, 0x81, - 0x60, 0x25, 0x34, 0x78, 0x02, 0x9b, 0xe7, 0x5a, 0xc7, 0x6d, 0xf0, 0x3e, 0xd3, 0xcc, 0x68, 0xa4, - 0x42, 0xbc, 0x02, 0xb5, 0x69, 0x34, 0x3e, 0x23, 0x23, 0x50, 0x91, 0x3c, 0x76, 0x1f, 0x3a, 0xe1, - 0x0f, 0x07, 0xaa, 0xaa, 0x05, 0xdc, 0x02, 0x37, 0x89, 0x0d, 0xc7, 0x4d, 0x62, 0xa5, 0x6a, 0x14, - 0xc7, 0x9c, 0x84, 0x28, 0x55, 0x35, 0xa9, 0x9a, 0x41, 0x9e, 0x71, 0xe9, 0x7b, 0x1d, 0xa7, 0xeb, - 0x31, 0x1d, 0xe3, 0xd3, 0x25, 0xa5, 0x0b, 0x89, 0x6e, 0xaf, 0xb8, 0xeb, 0x2a, 0x99, 0x2f, 0x77, - 0x8d, 0xaf, 0x2e, 0x34, 0xcb, 0x01, 0x58, 0x4d, 0x32, 0x80, 0x06, 0xa7, 0x2f, 0x67, 0x24, 0xa4, - 0x26, 0xb7, 0x07, 0xbe, 0xa5, 0xbf, 0xf7, 0xaa, 0x1e, 0x2b, 0x81, 0x78, 0x00, 0x4d, 0x4e, 0x22, - 0xcf, 0x52, 0x41, 0xfa, 0xb2, 0xeb, 0x48, 0x73, 0x24, 0x0e, 0x2f, 0x48, 0x71, 0x77, 0x8d, 0x5b, - 0xfe, 0x8d, 0x1c, 0x11, 0xd4, 0x74, 0x5b, 0x56, 0x29, 0x10, 0xaa, 0x72, 0x96, 0x97, 0x2c, 0x1d, - 0xe3, 0x3e, 0xd4, 0x35, 0x5b, 0x98, 0x77, 0xb2, 0xfa, 0xa2, 0x06, 0x17, 0xee, 0x40, 0xc3, 0x38, - 0x51, 0x75, 0x26, 0xe5, 0x58, 0x9f, 0xe1, 0x31, 0x15, 0x86, 0x12, 0xea, 0x8c, 0xc4, 0xd9, 0x58, - 0xe2, 0x55, 0xa8, 0x47, 0x23, 0x05, 0x33, 0x2d, 0x98, 0x4c, 0x59, 0xdd, 0x7c, 0x07, 0xcc, 0x3c, - 0x82, 0xd5, 0x2f, 0x93, 0x95, 0x50, 0xdc, 0x85, 0x96, 0x4c, 0x26, 0x24, 0x64, 0x34, 0xc9, 0x8d, - 0xff, 0x16, 0x0b, 0xe1, 0x7f, 0xb0, 0x39, 0x9c, 0xe4, 0x72, 0xc6, 0xcc, 0x28, 0xc2, 0x3b, 0x00, - 0x47, 0x24, 0x99, 0x19, 0xa7, 0xbf, 0x38, 0xb2, 0xe8, 0xa5, 0x4c, 0xc3, 0x21, 0xb4, 0x35, 0xce, - 0x4c, 0xf0, 0x01, 0x34, 0xcd, 0x8e, 0xf0, 0x1d, 0x2d, 0xc7, 0xba, 0xe6, 0xe6, 0xd8, 0x70, 0x13, - 0xda, 0xc7, 0x89, 0x28, 0xcf, 0x0b, 0x9f, 0xc3, 0x46, 0x91, 0x5e, 0xb2, 0x6c, 0x17, 0x36, 0x3e, - 0x44, 0x72, 0xf4, 0xe9, 0xf7, 0xf7, 0xf8, 0xee, 0x40, 0x6d, 0x38, 0xa5, 0x54, 0x5e, 0x78, 0xcd, - 0xfb, 0x4b, 0x33, 0xdf, 0x1a, 0xec, 0xda, 0x0c, 0xa9, 0x78, 0x6f, 0x67, 0x39, 0x19, 0x47, 0xac, - 0x95, 0x7a, 0x79, 0x7c, 0xd5, 0x3f, 0x1e, 0xdf, 0xbd, 0x3e, 0xb4, 0xe6, 0xc7, 0x20, 0x40, 0xfd, - 0x19, 0xa7, 0x48, 0xd2, 0x76, 0x45, 0xc5, 0x87, 0x34, 0x26, 0x49, 0xdb, 0x8e, 0x8a, 0xdf, 0xe5, - 0xb1, 0x5a, 0x77, 0x07, 0xdf, 0x3c, 0x68, 0x32, 0x53, 0x0e, 0x4f, 0xf4, 0x34, 0xcb, 0x3f, 0xc1, - 0x0d, 0xcb, 0x81, 0x8b, 0x61, 0x07, 0x37, 0x57, 0x6d, 0x1b, 0x6b, 0x54, 0xf0, 0x45, 0x59, 0x9a, - 0x38, 0xae, 0xe9, 0x3e, 0xe8, 0xd8, 0xc4, 0x3a, 0x67, 0xb3, 0x0a, 0x1e, 0x03, 0x1c, 0x12, 0xff, - 0x5b, 0xd5, 0x5e, 0x17, 0xc6, 0x31, 0x14, 0x81, 0xb6, 0xbb, 0x2c, 0x19, 0x2d, 0xb8, 0xb5, 0x72, - 0x7f, 0x5e, 0xf2, 0x08, 0x6a, 0xda, 0x43, 0x68, 0xc3, 0x2e, 0xbb, 0x2b, 0xb8, 0x6e, 0x01, 0x14, - 0x6f, 0x39, 0xac, 0xec, 0x3b, 0x1f, 0xeb, 0xfa, 0x37, 0x7d, 0xff, 0x57, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x69, 0x33, 0x08, 0xdb, 0xde, 0x07, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// RegistryClient is the client API for Registry service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type RegistryClient interface { - GetService(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) - Register(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) - Deregister(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) - ListServices(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) - Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (Registry_WatchClient, error) -} - -type registryClient struct { - cc *grpc.ClientConn -} - -func NewRegistryClient(cc *grpc.ClientConn) RegistryClient { - return ®istryClient{cc} -} - -func (c *registryClient) GetService(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) { - out := new(GetResponse) - err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/GetService", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *registryClient) Register(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) { - out := new(EmptyResponse) - err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/Register", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *registryClient) Deregister(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) { - out := new(EmptyResponse) - err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/Deregister", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *registryClient) ListServices(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { - out := new(ListResponse) - err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/ListServices", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *registryClient) Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (Registry_WatchClient, error) { - stream, err := c.cc.NewStream(ctx, &_Registry_serviceDesc.Streams[0], "/go.micro.registry.Registry/Watch", opts...) - if err != nil { - return nil, err - } - x := ®istryWatchClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Registry_WatchClient interface { - Recv() (*Result, error) - grpc.ClientStream -} - -type registryWatchClient struct { - grpc.ClientStream -} - -func (x *registryWatchClient) Recv() (*Result, error) { - m := new(Result) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// RegistryServer is the server API for Registry service. -type RegistryServer interface { - GetService(context.Context, *GetRequest) (*GetResponse, error) - Register(context.Context, *Service) (*EmptyResponse, error) - Deregister(context.Context, *Service) (*EmptyResponse, error) - ListServices(context.Context, *ListRequest) (*ListResponse, error) - Watch(*WatchRequest, Registry_WatchServer) error -} - -func RegisterRegistryServer(s *grpc.Server, srv RegistryServer) { - s.RegisterService(&_Registry_serviceDesc, srv) -} - -func _Registry_GetService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RegistryServer).GetService(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.registry.Registry/GetService", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RegistryServer).GetService(ctx, req.(*GetRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Registry_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Service) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RegistryServer).Register(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.registry.Registry/Register", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RegistryServer).Register(ctx, req.(*Service)) - } - return interceptor(ctx, in, info, handler) -} - -func _Registry_Deregister_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Service) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RegistryServer).Deregister(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.registry.Registry/Deregister", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RegistryServer).Deregister(ctx, req.(*Service)) - } - return interceptor(ctx, in, info, handler) -} - -func _Registry_ListServices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RegistryServer).ListServices(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.registry.Registry/ListServices", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RegistryServer).ListServices(ctx, req.(*ListRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Registry_Watch_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(WatchRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(RegistryServer).Watch(m, ®istryWatchServer{stream}) -} - -type Registry_WatchServer interface { - Send(*Result) error - grpc.ServerStream -} - -type registryWatchServer struct { - grpc.ServerStream -} - -func (x *registryWatchServer) Send(m *Result) error { - return x.ServerStream.SendMsg(m) -} - -var _Registry_serviceDesc = grpc.ServiceDesc{ - ServiceName: "go.micro.registry.Registry", - HandlerType: (*RegistryServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetService", - Handler: _Registry_GetService_Handler, - }, - { - MethodName: "Register", - Handler: _Registry_Register_Handler, - }, - { - MethodName: "Deregister", - Handler: _Registry_Deregister_Handler, - }, - { - MethodName: "ListServices", - Handler: _Registry_ListServices_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "Watch", - Handler: _Registry_Watch_Handler, - ServerStreams: true, - }, - }, - Metadata: "micro/go-micro/registry/service/proto/registry.proto", + 0xc1, 0xd3, 0xa0, 0x5d, 0xaf, 0x93, 0x54, 0xb5, 0x03, 0x52, 0xe1, 0x6e, 0x66, 0xf7, 0x9c, 0xd9, + 0xd9, 0x33, 0x67, 0x6d, 0x08, 0x4e, 0xd3, 0xbd, 0x69, 0x3c, 0xe6, 0xe9, 0x80, 0xd3, 0x69, 0x2c, + 0x24, 0x9f, 0x0f, 0x04, 0xf1, 0x59, 0x3c, 0xa6, 0x41, 0xc6, 0x53, 0xb9, 0x5c, 0x0e, 0x74, 0x8a, + 0xff, 0x9f, 0xa6, 0x81, 0xc6, 0x07, 0xc5, 0x86, 0xff, 0xd3, 0x86, 0xd6, 0x9b, 0x9c, 0x83, 0x08, + 0xf5, 0x24, 0x9c, 0x92, 0x6b, 0xf5, 0xac, 0x7e, 0x87, 0xe9, 0x18, 0x5d, 0x68, 0xcd, 0x88, 0x8b, + 0x38, 0x4d, 0x5c, 0x5b, 0x2f, 0x17, 0x29, 0x1e, 0x42, 0x7b, 0x4a, 0x32, 0x8c, 0x42, 0x19, 0xba, + 0x4e, 0xcf, 0xe9, 0x77, 0x87, 0xfd, 0xe0, 0x42, 0xfd, 0xc0, 0xd4, 0x0e, 0x4e, 0x0c, 0x74, 0x94, + 0x48, 0x3e, 0x67, 0x0b, 0x26, 0x3e, 0x82, 0x0e, 0x25, 0x51, 0x96, 0xc6, 0x89, 0x14, 0x6e, 0x5d, + 0x97, 0xd9, 0x29, 0x29, 0x33, 0x32, 0x18, 0xb6, 0x44, 0xe3, 0x1e, 0x34, 0x92, 0x34, 0x22, 0xe1, + 0x36, 0x34, 0xed, 0x5a, 0x09, 0xed, 0x65, 0x1a, 0x11, 0xcb, 0x51, 0x78, 0x00, 0xad, 0x34, 0x93, + 0x71, 0x9a, 0x08, 0xb7, 0xd9, 0xb3, 0xfa, 0xdd, 0xa1, 0x57, 0x42, 0x78, 0x95, 0x23, 0x58, 0x01, + 0xf5, 0x9e, 0xc0, 0xe6, 0xb9, 0xd6, 0x71, 0x1b, 0x9c, 0xcf, 0x34, 0x37, 0x1a, 0xa9, 0x10, 0xaf, + 0x40, 0x63, 0x16, 0x4e, 0xce, 0xc8, 0x08, 0x94, 0x27, 0x8f, 0xed, 0x87, 0x96, 0xff, 0xc3, 0x82, + 0xba, 0x6a, 0x01, 0xb7, 0xc0, 0x8e, 0x23, 0xc3, 0xb1, 0xe3, 0x48, 0xa9, 0x1a, 0x46, 0x11, 0x27, + 0x21, 0x0a, 0x55, 0x4d, 0xaa, 0x66, 0x90, 0xa5, 0x5c, 0xba, 0x4e, 0xcf, 0xea, 0x3b, 0x4c, 0xc7, + 0xf8, 0x74, 0x45, 0xe9, 0x5c, 0xa2, 0xdb, 0x15, 0x77, 0xad, 0x92, 0xf9, 0x72, 0xd7, 0xf8, 0x6a, + 0x43, 0xbb, 0x18, 0x40, 0xa9, 0x49, 0x86, 0xd0, 0xe2, 0xf4, 0xe5, 0x8c, 0x84, 0xd4, 0xe4, 0xee, + 0xd0, 0x2d, 0xe9, 0xef, 0xbd, 0xaa, 0xc7, 0x0a, 0x20, 0x1e, 0x40, 0x9b, 0x93, 0xc8, 0xd2, 0x44, + 0x90, 0xbe, 0xec, 0x3a, 0xd2, 0x02, 0x89, 0xa3, 0x0b, 0x52, 0xdc, 0x5d, 0xe3, 0x96, 0x7f, 0x23, + 0x47, 0x08, 0x0d, 0xdd, 0x56, 0xa9, 0x14, 0x08, 0x75, 0x39, 0xcf, 0x0a, 0x96, 0x8e, 0x71, 0x1f, + 0x9a, 0x9a, 0x2d, 0xcc, 0x3b, 0xa9, 0xbe, 0xa8, 0xc1, 0xf9, 0x3b, 0xd0, 0x32, 0x4e, 0x54, 0x9d, + 0x49, 0x39, 0xd1, 0x67, 0x38, 0x4c, 0x85, 0xbe, 0x84, 0x26, 0x23, 0x71, 0x36, 0x91, 0x78, 0x15, + 0x9a, 0xe1, 0x58, 0xc1, 0x4c, 0x0b, 0x26, 0x53, 0x56, 0x37, 0xdf, 0x01, 0x33, 0x0f, 0xaf, 0xfa, + 0x65, 0xb2, 0x02, 0x8a, 0xbb, 0xd0, 0x91, 0xf1, 0x94, 0x84, 0x0c, 0xa7, 0x99, 0xf1, 0xdf, 0x72, + 0xc1, 0xff, 0x0f, 0x36, 0x47, 0xd3, 0x4c, 0xce, 0x99, 0x19, 0x85, 0x7f, 0x07, 0xe0, 0x88, 0x24, + 0x33, 0xe3, 0x74, 0x97, 0x47, 0xe6, 0xbd, 0x14, 0xa9, 0x3f, 0x82, 0xae, 0xc6, 0x99, 0x09, 0x3e, + 0x80, 0xb6, 0xd9, 0x11, 0xae, 0xa5, 0xe5, 0x58, 0xd7, 0xdc, 0x02, 0xeb, 0x6f, 0x42, 0xf7, 0x38, + 0x16, 0xc5, 0x79, 0xfe, 0x73, 0xd8, 0xc8, 0xd3, 0x4b, 0x96, 0xed, 0xc3, 0xc6, 0x87, 0x50, 0x8e, + 0x3f, 0xfd, 0xfe, 0x1e, 0xdf, 0x2d, 0x68, 0x8c, 0x66, 0x94, 0xc8, 0x0b, 0xaf, 0x79, 0x7f, 0x65, + 0xe6, 0x5b, 0xc3, 0xdd, 0x32, 0x43, 0x2a, 0xde, 0xdb, 0x79, 0x46, 0xc6, 0x11, 0x6b, 0xa5, 0x5e, + 0x1d, 0x5f, 0xfd, 0x8f, 0xc7, 0x77, 0x6f, 0x00, 0x9d, 0xc5, 0x31, 0x08, 0xd0, 0x7c, 0xc6, 0x29, + 0x94, 0xb4, 0x5d, 0x53, 0xf1, 0x21, 0x4d, 0x48, 0xd2, 0xb6, 0xa5, 0xe2, 0x77, 0x59, 0xa4, 0xd6, + 0xed, 0xe1, 0x37, 0x07, 0xda, 0xcc, 0x94, 0xc3, 0x13, 0x3d, 0xcd, 0xe2, 0x4f, 0x70, 0xa3, 0xe4, + 0xc0, 0xe5, 0xb0, 0xbd, 0x9b, 0x55, 0xdb, 0xc6, 0x1a, 0x35, 0x7c, 0x51, 0x94, 0x26, 0x8e, 0x6b, + 0xba, 0xf7, 0x7a, 0x65, 0x62, 0x9d, 0xb3, 0x59, 0x0d, 0x8f, 0x01, 0x0e, 0x89, 0xff, 0xad, 0x6a, + 0xaf, 0x73, 0xe3, 0x18, 0x8a, 0xc0, 0xb2, 0xbb, 0xac, 0x18, 0xcd, 0xbb, 0x55, 0xb9, 0xbf, 0x28, + 0x79, 0x04, 0x0d, 0xed, 0x21, 0x2c, 0xc3, 0xae, 0xba, 0xcb, 0xbb, 0x5e, 0x02, 0xc8, 0xdf, 0xb2, + 0x5f, 0xdb, 0xb7, 0x3e, 0x36, 0xf5, 0x6f, 0xfa, 0xfe, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4c, + 0x3e, 0x92, 0x97, 0xd8, 0x07, 0x00, 0x00, } diff --git a/service_test.go b/service_test.go index 82195aed..3a6c3082 100644 --- a/service_test.go +++ b/service_test.go @@ -29,8 +29,7 @@ func testService(ctx context.Context, wg *sync.WaitGroup, name string) Service { // add self wg.Add(1) - r := memory.NewRegistry() - r.(*memory.Registry).Services = testData + r := memory.NewRegistry(memory.Services(testData)) // create service return NewService( From bec13a45cd0a924f519e18062667c437bb526458 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 16 Nov 2019 03:11:13 -0800 Subject: [PATCH 217/344] Attempt to fix the timing error in the memory concurrency test (#952) Only shows in travis Signed-off-by: Erik Hollensbe --- registry/memory/memory_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/memory/memory_test.go b/registry/memory/memory_test.go index 597beb38..dc83e4d3 100644 --- a/registry/memory/memory_test.go +++ b/registry/memory/memory_test.go @@ -194,7 +194,7 @@ func TestMemoryRegistryTTL(t *testing.T) { func TestMemoryRegistryTTLConcurrent(t *testing.T) { concurrency := 1000 - waitTime := ttlPruneTime * 2 + waitTime := ttlPruneTime * 4 m := NewRegistry() for _, v := range testData { From a1c6cdf193993f0d9d922f9275f1a4237535891a Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 16 Nov 2019 03:13:34 -0800 Subject: [PATCH 218/344] Now specify HandleSignal as an option to toggle signal handling. (#948) Signed-off-by: Erik Hollensbe --- options.go | 12 ++++++++++++ service.go | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/options.go b/options.go index d566a353..aa90c88f 100644 --- a/options.go +++ b/options.go @@ -31,6 +31,8 @@ type Options struct { // Other options for implementations of the interface // can be stored in a context Context context.Context + + Signal bool } func newOptions(opts ...Option) Options { @@ -42,6 +44,7 @@ func newOptions(opts ...Option) Options { Registry: registry.DefaultRegistry, Transport: transport.DefaultTransport, Context: context.Background(), + Signal: true, } for _, o := range opts { @@ -81,6 +84,15 @@ func Context(ctx context.Context) Option { } } +// HandleSignal toggles automatic installation of the signal handler that +// traps TERM, INT, and QUIT. Users of this feature to disable the signal +// handler, should control liveness of the service through the context. +func HandleSignal(b bool) Option { + return func(o *Options) { + o.Signal = b + } +} + func Server(s server.Server) Option { return func(o *Options) { o.Server = s diff --git a/service.go b/service.go index f2d9fea8..2c94387e 100644 --- a/service.go +++ b/service.go @@ -169,7 +169,9 @@ func (s *service) Run() error { } ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) + if s.opts.Signal { + signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) + } select { // wait on kill signal From 90d7a87914fd1325647432305478df3c1dee5eb3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 16 Nov 2019 18:48:24 +0000 Subject: [PATCH 219/344] Move wrapper internally since its not top level relevant --- go.sum | 2 ++ service.go | 13 ++++++------- wrapper.go => util/wrapper/wrapper.go | 16 +++++++++++++++- wrapper_test.go => util/wrapper/wrapper_test.go | 2 +- 4 files changed, 24 insertions(+), 9 deletions(-) rename wrapper.go => util/wrapper/wrapper.go (74%) rename wrapper_test.go => util/wrapper/wrapper_test.go (98%) diff --git a/go.sum b/go.sum index 245c8799..00550ff0 100644 --- a/go.sum +++ b/go.sum @@ -76,6 +76,7 @@ github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/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= @@ -522,6 +523,7 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a h1:Ob5/580gVHBJZgXnff1cZDbG+xLtMVE5mDRTe+nIsX4= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 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= diff --git a/service.go b/service.go index 2c94387e..95477231 100644 --- a/service.go +++ b/service.go @@ -12,9 +12,9 @@ import ( "github.com/micro/go-micro/debug/handler" "github.com/micro/go-micro/debug/profile" "github.com/micro/go-micro/debug/profile/pprof" - "github.com/micro/go-micro/metadata" "github.com/micro/go-micro/plugin" "github.com/micro/go-micro/server" + "github.com/micro/go-micro/util/wrapper" "github.com/micro/go-micro/util/log" ) @@ -27,12 +27,11 @@ type service struct { func newService(opts ...Option) Service { options := newOptions(opts...) - options.Client = &clientWrapper{ - options.Client, - metadata.Metadata{ - HeaderPrefix + "From-Service": options.Server.Options().Name, - }, - } + // service name + serviceName := options.Server.Options().Name + + // wrap client to inject From-Service header on any calls + options.Client = wrapper.FromService(serviceName, options.Client) return &service{ opts: options, diff --git a/wrapper.go b/util/wrapper/wrapper.go similarity index 74% rename from wrapper.go rename to util/wrapper/wrapper.go index e4977397..f80d34fb 100644 --- a/wrapper.go +++ b/util/wrapper/wrapper.go @@ -1,4 +1,4 @@ -package micro +package wrapper import ( "context" @@ -12,6 +12,10 @@ type clientWrapper struct { headers metadata.Metadata } +var ( + HeaderPrefix = "Micro-" +) + func (c *clientWrapper) setHeaders(ctx context.Context) context.Context { // copy metadata mda, _ := metadata.FromContext(ctx) @@ -41,3 +45,13 @@ func (c *clientWrapper) Publish(ctx context.Context, p client.Message, opts ...c ctx = c.setHeaders(ctx) return c.Client.Publish(ctx, p, opts...) } + +// FromService wraps a client to inject From-Service header into metadata +func FromService(name string, c client.Client) client.Client { + return &clientWrapper{ + c, + metadata.Metadata{ + HeaderPrefix + "From-Service": name, + }, + } +} diff --git a/wrapper_test.go b/util/wrapper/wrapper_test.go similarity index 98% rename from wrapper_test.go rename to util/wrapper/wrapper_test.go index 80abdc46..de777cee 100644 --- a/wrapper_test.go +++ b/util/wrapper/wrapper_test.go @@ -1,4 +1,4 @@ -package micro +package wrapper import ( "context" From eeed4937660a0809fbc6404eb52d9e957785d5a2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 16 Nov 2019 18:52:27 +0000 Subject: [PATCH 220/344] move test data --- function_test.go | 3 ++- service.go | 2 +- service_test.go | 3 ++- common_test.go => util/test/test.go | 6 +++--- util/wrapper/wrapper.go | 10 +++++----- 5 files changed, 13 insertions(+), 11 deletions(-) rename common_test.go => util/test/test.go (89%) diff --git a/function_test.go b/function_test.go index 44177cb9..c53e9cdc 100644 --- a/function_test.go +++ b/function_test.go @@ -7,13 +7,14 @@ import ( proto "github.com/micro/go-micro/debug/proto" "github.com/micro/go-micro/registry/memory" + "github.com/micro/go-micro/util/test" ) func TestFunction(t *testing.T) { var wg sync.WaitGroup wg.Add(1) - r := memory.NewRegistry(memory.Services(testData)) + r := memory.NewRegistry(memory.Services(test.Data)) // create service fn := NewFunction( diff --git a/service.go b/service.go index 95477231..3058a3b2 100644 --- a/service.go +++ b/service.go @@ -14,8 +14,8 @@ import ( "github.com/micro/go-micro/debug/profile/pprof" "github.com/micro/go-micro/plugin" "github.com/micro/go-micro/server" - "github.com/micro/go-micro/util/wrapper" "github.com/micro/go-micro/util/log" + "github.com/micro/go-micro/util/wrapper" ) type service struct { diff --git a/service_test.go b/service_test.go index 3a6c3082..f7abb15f 100644 --- a/service_test.go +++ b/service_test.go @@ -11,6 +11,7 @@ import ( proto "github.com/micro/go-micro/debug/proto" "github.com/micro/go-micro/registry/memory" "github.com/micro/go-micro/util/log" + "github.com/micro/go-micro/util/test" ) func testShutdown(wg *sync.WaitGroup, cancel func()) { @@ -29,7 +30,7 @@ func testService(ctx context.Context, wg *sync.WaitGroup, name string) Service { // add self wg.Add(1) - r := memory.NewRegistry(memory.Services(testData)) + r := memory.NewRegistry(memory.Services(test.Data)) // create service return NewService( diff --git a/common_test.go b/util/test/test.go similarity index 89% rename from common_test.go rename to util/test/test.go index 6a1ed2d8..100c8e79 100644 --- a/common_test.go +++ b/util/test/test.go @@ -1,12 +1,12 @@ -package micro +package test import ( "github.com/micro/go-micro/registry" ) var ( - // mock data - testData = map[string][]*registry.Service{ + // mock registry data + Data = map[string][]*registry.Service{ "foo": { { Name: "foo", diff --git a/util/wrapper/wrapper.go b/util/wrapper/wrapper.go index f80d34fb..cf198435 100644 --- a/util/wrapper/wrapper.go +++ b/util/wrapper/wrapper.go @@ -49,9 +49,9 @@ func (c *clientWrapper) Publish(ctx context.Context, p client.Message, opts ...c // FromService wraps a client to inject From-Service header into metadata func FromService(name string, c client.Client) client.Client { return &clientWrapper{ - c, - metadata.Metadata{ - HeaderPrefix + "From-Service": name, - }, - } + c, + metadata.Metadata{ + HeaderPrefix + "From-Service": name, + }, + } } From 342c29de7d14c594a8cce0d87842b79bcc2a942d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 16 Nov 2019 21:13:06 +0000 Subject: [PATCH 221/344] fix TestMemoryRegistryTTLConcurrent test --- registry/memory/memory_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/memory/memory_test.go b/registry/memory/memory_test.go index dc83e4d3..cab6a6f4 100644 --- a/registry/memory/memory_test.go +++ b/registry/memory/memory_test.go @@ -194,12 +194,12 @@ func TestMemoryRegistryTTL(t *testing.T) { func TestMemoryRegistryTTLConcurrent(t *testing.T) { concurrency := 1000 - waitTime := ttlPruneTime * 4 + waitTime := ttlPruneTime * 2 m := NewRegistry() for _, v := range testData { for _, service := range v { - if err := m.Register(service, registry.RegisterTTL(waitTime)); err != nil { + if err := m.Register(service, registry.RegisterTTL(waitTime/2)); err != nil { t.Fatal(err) } } From fa01cadc35bd4434b7a747f42f3e723cba1e476f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 18 Nov 2019 12:50:51 +0000 Subject: [PATCH 222/344] lower the mdns timeout to 10ms (#955) --- registry/mdns_registry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/mdns_registry.go b/registry/mdns_registry.go index 6d1c75f7..0046e9b2 100644 --- a/registry/mdns_registry.go +++ b/registry/mdns_registry.go @@ -51,7 +51,7 @@ type mdnsRegistry struct { func newRegistry(opts ...Option) Registry { options := Options{ Context: context.Background(), - Timeout: time.Millisecond * 100, + Timeout: time.Millisecond * 10, } for _, o := range opts { From 168cc06827948207dfbc3c8c8d5c4f3ca12c5327 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 18 Nov 2019 12:58:06 +0000 Subject: [PATCH 223/344] increase timeout on travis --- registry/watcher_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/registry/watcher_test.go b/registry/watcher_test.go index a564bcda..717dbde3 100644 --- a/registry/watcher_test.go +++ b/registry/watcher_test.go @@ -1,7 +1,9 @@ package registry import ( + "os" "testing" + "time" ) func TestWatcher(t *testing.T) { @@ -76,8 +78,16 @@ func TestWatcher(t *testing.T) { } } + travis := os.Getenv("TRAVIS") + + var opts []Option + + if travis == "true" { + opts = append(opts, Timeout(time.Millisecond*100)) + } + // new registry - r := NewRegistry() + r := NewRegistry(opts...) w, err := r.Watch() if err != nil { From 57440509434d7a5b513c76c802483e5cd23c6c02 Mon Sep 17 00:00:00 2001 From: Shu xian Date: Tue, 19 Nov 2019 00:37:45 +0800 Subject: [PATCH 224/344] api event supports for GET url params (#956) --- api/handler/event/event.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/api/handler/event/event.go b/api/handler/event/event.go index 6fb45ae8..8eb65aa1 100644 --- a/api/handler/event/event.go +++ b/api/handler/event/event.go @@ -2,6 +2,7 @@ package event import ( + "encoding/json" "fmt" "io/ioutil" "net/http" @@ -91,12 +92,17 @@ func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // set body - b, err := ioutil.ReadAll(r.Body) - if err != nil { - http.Error(w, err.Error(), 500) - return + if r.Method == "GET" { + bytes, _ := json.Marshal(r.URL.Query()) + ev.Data = string(bytes) + } else { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), 500) + return + } + ev.Data = string(b) } - ev.Data = string(b) // get client c := e.options.Service.Client() From 6a0082741c56821179c900d274176a3c14bb1208 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 19 Nov 2019 16:09:43 +0000 Subject: [PATCH 225/344] Packager is now builder (#958) --- .../{package/package.go => build/build.go} | 20 +++++++++---------- runtime/{package => build}/docker/docker.go | 20 +++++++++---------- runtime/{package => build}/go/golang.go | 18 ++++++++--------- runtime/{package => build}/options.go | 2 +- runtime/process/os/os.go | 4 ++-- runtime/process/process.go | 6 +++--- runtime/service.go | 5 +++-- 7 files changed, 38 insertions(+), 37 deletions(-) rename runtime/{package/package.go => build/build.go} (52%) rename runtime/{package => build}/docker/docker.go (78%) rename runtime/{package => build}/go/golang.go (74%) rename runtime/{package => build}/options.go (92%) diff --git a/runtime/package/package.go b/runtime/build/build.go similarity index 52% rename from runtime/package/package.go rename to runtime/build/build.go index 078c8a59..41a4beeb 100644 --- a/runtime/package/package.go +++ b/runtime/build/build.go @@ -1,16 +1,16 @@ -// Package packager creates a binary image. Due to package being a reserved keyword we use packager. -package packager +// Package build builds a micro runtime package +package build import ( "github.com/micro/go-micro/runtime/source" ) -// Package builds binaries -type Packager interface { - // Compile builds a binary - Compile(*Source) (*Binary, error) - // Deletes the binary - Delete(*Binary) error +// Builder builds binaries +type Builder interface { + // Build builds a package + Build(*Source) (*Package, error) + // Clean deletes the package + Clean(*Package) error } // Source is the source of a build @@ -21,8 +21,8 @@ type Source struct { Repository *source.Repository } -// Binary is the representation of a binary -type Binary struct { +// Package is micro service package +type Package struct { // Name of the binary Name string // Location of the binary diff --git a/runtime/package/docker/docker.go b/runtime/build/docker/docker.go similarity index 78% rename from runtime/package/docker/docker.go rename to runtime/build/docker/docker.go index 2f0c46c0..d71c53ef 100644 --- a/runtime/package/docker/docker.go +++ b/runtime/build/docker/docker.go @@ -8,17 +8,17 @@ import ( "os" "path/filepath" - "github.com/fsouza/go-dockerclient" - "github.com/micro/go-micro/runtime/package" + docker "github.com/fsouza/go-dockerclient" + "github.com/micro/go-micro/runtime/build" "github.com/micro/go-micro/util/log" ) -type Packager struct { - Options packager.Options +type Builder struct { + Options build.Options Client *docker.Client } -func (d *Packager) Compile(s *packager.Source) (*packager.Binary, error) { +func (d *Builder) Build(s *build.Source) (*build.Package, error) { image := filepath.Join(s.Repository.Path, s.Repository.Name) buf := new(bytes.Buffer) @@ -63,7 +63,7 @@ func (d *Packager) Compile(s *packager.Source) (*packager.Binary, error) { if err != nil { return nil, err } - return &packager.Binary{ + return &build.Package{ Name: image, Path: image, Type: "docker", @@ -71,13 +71,13 @@ func (d *Packager) Compile(s *packager.Source) (*packager.Binary, error) { }, nil } -func (d *Packager) Delete(b *packager.Binary) error { +func (d *Builder) Clean(b *build.Package) error { image := filepath.Join(b.Path, b.Name) return d.Client.RemoveImage(image) } -func NewPackager(opts ...packager.Option) packager.Packager { - options := packager.Options{} +func NewBuilder(opts ...build.Option) build.Builder { + options := build.Options{} for _, o := range opts { o(&options) } @@ -86,7 +86,7 @@ func NewPackager(opts ...packager.Option) packager.Packager { if err != nil { log.Fatal(err) } - return &Packager{ + return &Builder{ Options: options, Client: client, } diff --git a/runtime/package/go/golang.go b/runtime/build/go/golang.go similarity index 74% rename from runtime/package/go/golang.go rename to runtime/build/go/golang.go index a9a591ab..435da0b5 100644 --- a/runtime/package/go/golang.go +++ b/runtime/build/go/golang.go @@ -6,11 +6,11 @@ import ( "os/exec" "path/filepath" - "github.com/micro/go-micro/runtime/package" + "github.com/micro/go-micro/runtime/build" ) -type Packager struct { - Options packager.Options +type Builder struct { + Options build.Options Cmd string Path string } @@ -34,7 +34,7 @@ func whichGo() string { return "go" } -func (g *Packager) Compile(s *packager.Source) (*packager.Binary, error) { +func (g *Builder) Build(s *build.Source) (*build.Package, error) { binary := filepath.Join(g.Path, s.Repository.Name) source := filepath.Join(s.Repository.Path, s.Repository.Name) @@ -42,7 +42,7 @@ func (g *Packager) Compile(s *packager.Source) (*packager.Binary, error) { if err := cmd.Run(); err != nil { return nil, err } - return &packager.Binary{ + return &build.Package{ Name: s.Repository.Name, Path: binary, Type: "go", @@ -50,19 +50,19 @@ func (g *Packager) Compile(s *packager.Source) (*packager.Binary, error) { }, nil } -func (g *Packager) Delete(b *packager.Binary) error { +func (g *Builder) Clean(b *build.Package) error { binary := filepath.Join(b.Path, b.Name) return os.Remove(binary) } -func NewPackager(opts ...packager.Option) packager.Packager { - options := packager.Options{ +func NewBuild(opts ...build.Option) build.Builder { + options := build.Options{ Path: os.TempDir(), } for _, o := range opts { o(&options) } - return &Packager{ + return &Builder{ Options: options, Cmd: whichGo(), Path: options.Path, diff --git a/runtime/package/options.go b/runtime/build/options.go similarity index 92% rename from runtime/package/options.go rename to runtime/build/options.go index a308c737..65e7dd68 100644 --- a/runtime/package/options.go +++ b/runtime/build/options.go @@ -1,4 +1,4 @@ -package packager +package build type Options struct { // local path to download source diff --git a/runtime/process/os/os.go b/runtime/process/os/os.go index 83eca1f3..0e6bc79f 100644 --- a/runtime/process/os/os.go +++ b/runtime/process/os/os.go @@ -15,13 +15,13 @@ type Process struct { } func (p *Process) Exec(exe *process.Executable) error { - cmd := exec.Command(exe.Binary.Path) + cmd := exec.Command(exe.Package.Path) return cmd.Run() } func (p *Process) Fork(exe *process.Executable) (*process.PID, error) { // create command - cmd := exec.Command(exe.Binary.Path, exe.Args...) + cmd := exec.Command(exe.Package.Path, exe.Args...) // set env vars cmd.Env = append(cmd.Env, exe.Env...) diff --git a/runtime/process/process.go b/runtime/process/process.go index b5b302d8..8ab78483 100644 --- a/runtime/process/process.go +++ b/runtime/process/process.go @@ -4,7 +4,7 @@ package process import ( "io" - "github.com/micro/go-micro/runtime/package" + "github.com/micro/go-micro/runtime/build" ) // Process manages a running process @@ -20,8 +20,8 @@ type Process interface { } type Executable struct { - // The executable binary - Binary *packager.Binary + // Package containing executable + Package *build.Package // The env variables Env []string // Args to pass diff --git a/runtime/service.go b/runtime/service.go index d83d7a5f..0d2cc8e9 100644 --- a/runtime/service.go +++ b/runtime/service.go @@ -5,7 +5,8 @@ import ( "strings" "sync" - packager "github.com/micro/go-micro/runtime/package" + "github.com/micro/go-micro/runtime/build" + "github.com/micro/go-micro/runtime/process" proc "github.com/micro/go-micro/runtime/process/os" "github.com/micro/go-micro/util/log" @@ -56,7 +57,7 @@ func newService(s *Service, c CreateOptions) *service { Service: s, Process: new(proc.Process), Exec: &process.Executable{ - Binary: &packager.Binary{ + Package: &build.Package{ Name: s.Name, Path: exec, }, From fb5b358ae25733cdc4602e220babddb63da39feb Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 19 Nov 2019 16:50:16 +0000 Subject: [PATCH 226/344] fix mdns test --- registry/mdns_test.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/registry/mdns_test.go b/registry/mdns_test.go index bd544df9..0a643428 100644 --- a/registry/mdns_test.go +++ b/registry/mdns_test.go @@ -48,8 +48,16 @@ func TestMDNS(t *testing.T) { }, } + travis := os.Getenv("TRAVIS") + + var opts []Option + + if travis == "true" { + opts = append(opts, Timeout(time.Millisecond*100)) + } + // new registry - r := NewRegistry() + r := NewRegistry(opts...) for _, service := range testData { // register service From 538d3752f97c21296e23683f0c9678363105f199 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 19 Nov 2019 16:50:31 +0000 Subject: [PATCH 227/344] Added Dockerfile for go-micro (#959) --- Dockerfile | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..91caabf9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM golang:1.13-alpine +ENV GO111MODULE=on +RUN apk --no-cache add make git gcc libtool musl-dev +WORKDIR / +COPY go.mod . +COPY go.sum . +RUN go mod download From 64d5a528caf429f5965f6c0ba52236d7fe2e94ce Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 19 Nov 2019 16:55:33 +0000 Subject: [PATCH 228/344] fix broken build --- registry/mdns_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/registry/mdns_test.go b/registry/mdns_test.go index 0a643428..9656d2dc 100644 --- a/registry/mdns_test.go +++ b/registry/mdns_test.go @@ -1,6 +1,7 @@ package registry import ( + "os" "testing" "time" ) From d6e97c5970b474a19b90072867fedc94dcfc332d Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 19 Nov 2019 19:36:29 +0000 Subject: [PATCH 229/344] Service.Exec is a slice of strings (#960) --- runtime/proto/runtime.micro.go | 2 +- runtime/proto/runtime.pb.go | 165 +++++----------------------- runtime/proto/runtime.proto | 2 +- runtime/runtime.go | 2 +- runtime/service.go | 10 +- runtime/service/proto/runtime.pb.go | 42 +++---- runtime/service/proto/runtime.proto | 2 +- 7 files changed, 58 insertions(+), 167 deletions(-) diff --git a/runtime/proto/runtime.micro.go b/runtime/proto/runtime.micro.go index f494748f..91ff4f8b 100644 --- a/runtime/proto/runtime.micro.go +++ b/runtime/proto/runtime.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: micro/go-micro/runtime/proto/runtime.proto +// source: runtime.proto package go_micro_runtime diff --git a/runtime/proto/runtime.pb.go b/runtime/proto/runtime.pb.go index 50f810ab..8b6596d7 100644 --- a/runtime/proto/runtime.pb.go +++ b/runtime/proto/runtime.pb.go @@ -1,13 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: micro/go-micro/runtime/proto/runtime.proto +// source: runtime.proto package go_micro_runtime import ( - context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" math "math" ) @@ -30,7 +28,7 @@ type Service struct { // local path of the source Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` // command to execute - Exec string `protobuf:"bytes,4,opt,name=exec,proto3" json:"exec,omitempty"` + Exec []string `protobuf:"bytes,4,rep,name=exec,proto3" json:"exec,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -40,7 +38,7 @@ func (m *Service) Reset() { *m = Service{} } func (m *Service) String() string { return proto.CompactTextString(m) } func (*Service) ProtoMessage() {} func (*Service) Descriptor() ([]byte, []int) { - return fileDescriptor_efcf18966add108e, []int{0} + return fileDescriptor_86e2dd377c869464, []int{0} } func (m *Service) XXX_Unmarshal(b []byte) error { @@ -82,11 +80,11 @@ func (m *Service) GetPath() string { return "" } -func (m *Service) GetExec() string { +func (m *Service) GetExec() []string { if m != nil { return m.Exec } - return "" + return nil } type CreateRequest struct { @@ -100,7 +98,7 @@ func (m *CreateRequest) Reset() { *m = CreateRequest{} } func (m *CreateRequest) String() string { return proto.CompactTextString(m) } func (*CreateRequest) ProtoMessage() {} func (*CreateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_efcf18966add108e, []int{1} + return fileDescriptor_86e2dd377c869464, []int{1} } func (m *CreateRequest) XXX_Unmarshal(b []byte) error { @@ -138,7 +136,7 @@ func (m *CreateResponse) Reset() { *m = CreateResponse{} } func (m *CreateResponse) String() string { return proto.CompactTextString(m) } func (*CreateResponse) ProtoMessage() {} func (*CreateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_efcf18966add108e, []int{2} + return fileDescriptor_86e2dd377c869464, []int{2} } func (m *CreateResponse) XXX_Unmarshal(b []byte) error { @@ -170,7 +168,7 @@ func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } func (*DeleteRequest) ProtoMessage() {} func (*DeleteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_efcf18966add108e, []int{3} + return fileDescriptor_86e2dd377c869464, []int{3} } func (m *DeleteRequest) XXX_Unmarshal(b []byte) error { @@ -208,7 +206,7 @@ func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } func (*DeleteResponse) ProtoMessage() {} func (*DeleteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_efcf18966add108e, []int{4} + return fileDescriptor_86e2dd377c869464, []int{4} } func (m *DeleteResponse) XXX_Unmarshal(b []byte) error { @@ -237,130 +235,23 @@ func init() { proto.RegisterType((*DeleteResponse)(nil), "go.micro.runtime.DeleteResponse") } -func init() { - proto.RegisterFile("micro/go-micro/runtime/proto/runtime.proto", fileDescriptor_efcf18966add108e) -} - -var fileDescriptor_efcf18966add108e = []byte{ - // 240 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x91, 0x41, 0x4b, 0xc4, 0x30, - 0x14, 0x84, 0xb7, 0xba, 0xb4, 0xf8, 0x44, 0x59, 0x72, 0x90, 0xe8, 0xc5, 0x25, 0x27, 0x11, 0xcc, - 0x42, 0xfb, 0x13, 0xec, 0xd5, 0x4b, 0x3c, 0x7b, 0xa8, 0xe1, 0x51, 0x0b, 0xb6, 0xa9, 0x49, 0x2a, - 0xfe, 0x23, 0xff, 0xa6, 0x24, 0x2f, 0x15, 0xaa, 0xf5, 0xe4, 0x6d, 0xde, 0x30, 0x7c, 0x33, 0x21, - 0x70, 0xdb, 0x77, 0xda, 0x9a, 0x43, 0x6b, 0xee, 0x48, 0xd8, 0x69, 0xf0, 0x5d, 0x8f, 0x87, 0xd1, - 0x1a, 0xff, 0x7d, 0xc9, 0x78, 0xb1, 0x5d, 0x6b, 0x64, 0x4c, 0xc9, 0xe4, 0x8b, 0x27, 0x28, 0x1e, - 0xd1, 0xbe, 0x77, 0x1a, 0x19, 0x83, 0xed, 0xd0, 0xf4, 0xc8, 0xb3, 0x7d, 0x76, 0x73, 0xa2, 0xa2, - 0x66, 0x17, 0x90, 0x3b, 0x33, 0x59, 0x8d, 0xfc, 0x28, 0xba, 0xe9, 0x0a, 0xd9, 0xb1, 0xf1, 0x2f, - 0xfc, 0x98, 0xb2, 0x41, 0x07, 0x0f, 0x3f, 0x50, 0xf3, 0x2d, 0x79, 0x41, 0x8b, 0x1a, 0xce, 0xee, - 0x2d, 0x36, 0x1e, 0x15, 0xbe, 0x4d, 0xe8, 0x3c, 0xab, 0xa0, 0x70, 0xd4, 0x17, 0x7b, 0x4e, 0xcb, - 0x4b, 0xf9, 0x73, 0x93, 0x4c, 0x83, 0xd4, 0x9c, 0x14, 0x3b, 0x38, 0x9f, 0x29, 0x6e, 0x34, 0x83, - 0xc3, 0xc0, 0xad, 0xf1, 0x15, 0xff, 0xcf, 0x9d, 0x29, 0xc4, 0x2d, 0x3f, 0x33, 0x28, 0x14, 0xc5, - 0xd9, 0x03, 0xe4, 0xd4, 0xca, 0xae, 0x7f, 0xb3, 0x16, 0xaf, 0xba, 0xda, 0xff, 0x1d, 0x48, 0x83, - 0x37, 0x01, 0x47, 0x65, 0x6b, 0xb8, 0xc5, 0x63, 0xd6, 0x70, 0xcb, 0x9d, 0x62, 0xf3, 0x9c, 0xc7, - 0x1f, 0xad, 0xbe, 0x02, 0x00, 0x00, 0xff, 0xff, 0x9a, 0xb6, 0x5a, 0xe7, 0xff, 0x01, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// RuntimeClient is the client API for Runtime service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type RuntimeClient interface { - Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) - Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) -} - -type runtimeClient struct { - cc *grpc.ClientConn -} - -func NewRuntimeClient(cc *grpc.ClientConn) RuntimeClient { - return &runtimeClient{cc} -} - -func (c *runtimeClient) Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) { - out := new(CreateResponse) - err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Create", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *runtimeClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) { - out := new(DeleteResponse) - err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Delete", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// RuntimeServer is the server API for Runtime service. -type RuntimeServer interface { - Create(context.Context, *CreateRequest) (*CreateResponse, error) - Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) -} - -func RegisterRuntimeServer(s *grpc.Server, srv RuntimeServer) { - s.RegisterService(&_Runtime_serviceDesc, srv) -} - -func _Runtime_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RuntimeServer).Create(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.runtime.Runtime/Create", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RuntimeServer).Create(ctx, req.(*CreateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Runtime_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RuntimeServer).Delete(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.runtime.Runtime/Delete", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RuntimeServer).Delete(ctx, req.(*DeleteRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Runtime_serviceDesc = grpc.ServiceDesc{ - ServiceName: "go.micro.runtime.Runtime", - HandlerType: (*RuntimeServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Create", - Handler: _Runtime_Create_Handler, - }, - { - MethodName: "Delete", - Handler: _Runtime_Delete_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "micro/go-micro/runtime/proto/runtime.proto", +func init() { proto.RegisterFile("runtime.proto", fileDescriptor_86e2dd377c869464) } + +var fileDescriptor_86e2dd377c869464 = []byte{ + // 229 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x91, 0xbf, 0x4e, 0x86, 0x30, + 0x14, 0xc5, 0x41, 0x08, 0xc4, 0x6b, 0x30, 0xa4, 0x83, 0xa9, 0x2e, 0x92, 0x4e, 0x4e, 0x1d, 0xe0, + 0x11, 0x64, 0x75, 0xa9, 0xb3, 0x03, 0x36, 0x37, 0x4a, 0x22, 0x14, 0xdb, 0x62, 0x7c, 0x23, 0x5f, + 0xd3, 0xf4, 0x0f, 0x03, 0xca, 0x37, 0x7d, 0xdb, 0xe9, 0xc9, 0xc9, 0xef, 0x9c, 0x9b, 0x42, 0xa5, + 0xd7, 0xd9, 0x8e, 0x13, 0xf2, 0x45, 0x2b, 0xab, 0x48, 0xfd, 0xa6, 0xf8, 0x34, 0x4a, 0xad, 0x78, + 0xf4, 0xd9, 0x0b, 0x94, 0xcf, 0xa8, 0xbf, 0x46, 0x89, 0x84, 0x40, 0x3e, 0x0f, 0x13, 0xd2, 0xb4, + 0x49, 0x1f, 0x2e, 0x85, 0xd7, 0xe4, 0x06, 0x0a, 0xa3, 0x56, 0x2d, 0x91, 0x5e, 0x78, 0x37, 0xbe, + 0x5c, 0x76, 0x19, 0xec, 0x3b, 0xcd, 0x42, 0xd6, 0x69, 0xe7, 0xe1, 0x37, 0x4a, 0x9a, 0x37, 0x99, + 0xf3, 0x9c, 0x66, 0x3d, 0x54, 0x8f, 0x1a, 0x07, 0x8b, 0x02, 0x3f, 0x57, 0x34, 0x96, 0x74, 0x50, + 0x9a, 0xd0, 0xe7, 0x7b, 0xae, 0xda, 0x5b, 0xfe, 0x77, 0x13, 0x8f, 0x83, 0xc4, 0x96, 0x64, 0x35, + 0x5c, 0x6f, 0x14, 0xb3, 0xa8, 0xd9, 0xa0, 0xe3, 0xf6, 0xf8, 0x81, 0xe7, 0x73, 0x37, 0x4a, 0xe0, + 0xb6, 0x3f, 0x29, 0x94, 0x22, 0xc4, 0xc9, 0x13, 0x14, 0xa1, 0x95, 0xdc, 0xff, 0x67, 0xed, 0xae, + 0xba, 0x6b, 0x4e, 0x07, 0xe2, 0xe0, 0xc4, 0xe1, 0x42, 0xd9, 0x11, 0x6e, 0x77, 0xcc, 0x11, 0x6e, + 0xbf, 0x93, 0x25, 0xaf, 0x85, 0xff, 0xd1, 0xee, 0x37, 0x00, 0x00, 0xff, 0xff, 0x99, 0xc5, 0x97, + 0x12, 0xe2, 0x01, 0x00, 0x00, } diff --git a/runtime/proto/runtime.proto b/runtime/proto/runtime.proto index 6a3759e3..bce613e3 100644 --- a/runtime/proto/runtime.proto +++ b/runtime/proto/runtime.proto @@ -15,7 +15,7 @@ message Service { // local path of the source string path = 3; // command to execute - string exec = 4; + repeated string exec = 4; } message CreateRequest { diff --git a/runtime/runtime.go b/runtime/runtime.go index 36836392..1cd3ae34 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -83,7 +83,7 @@ type Service struct { // Path to store source Path string // Exec command - Exec string + Exec []string // Version of the service Version string } diff --git a/runtime/service.go b/runtime/service.go index 0d2cc8e9..cf142c16 100644 --- a/runtime/service.go +++ b/runtime/service.go @@ -2,7 +2,6 @@ package runtime import ( "io" - "strings" "sync" "github.com/micro/go-micro/runtime/build" @@ -37,12 +36,13 @@ func newService(s *Service, c CreateOptions) *service { var args []string if len(s.Exec) > 0 { - parts := strings.Split(s.Exec, " ") - exec = parts[0] + if len(s.Exec) > 0 { + exec = s.Exec[0] + } args = []string{} - if len(parts) > 1 { - args = parts[1:] + if len(s.Exec) > 1 { + args = s.Exec[1:] } } else { // set command diff --git a/runtime/service/proto/runtime.pb.go b/runtime/service/proto/runtime.pb.go index b34df91d..7a9d2bc1 100644 --- a/runtime/service/proto/runtime.pb.go +++ b/runtime/service/proto/runtime.pb.go @@ -30,7 +30,7 @@ type Service struct { // local path of the source Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` // command to execute - Exec string `protobuf:"bytes,5,opt,name=exec,proto3" json:"exec,omitempty"` + Exec []string `protobuf:"bytes,5,rep,name=exec,proto3" json:"exec,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -89,11 +89,11 @@ func (m *Service) GetPath() string { return "" } -func (m *Service) GetExec() string { +func (m *Service) GetExec() []string { if m != nil { return m.Exec } - return "" + return nil } type CreateOptions struct { @@ -597,22 +597,22 @@ var fileDescriptor_86e2dd377c869464 = []byte{ 0x25, 0x12, 0x02, 0xb3, 0xa6, 0xa8, 0x91, 0x4e, 0x96, 0x93, 0x37, 0x8f, 0x72, 0xfd, 0x26, 0x14, 0xa2, 0x03, 0x76, 0xa2, 0xe2, 0x0d, 0x9d, 0xea, 0xb6, 0x2b, 0xc9, 0x53, 0x08, 0x05, 0xef, 0xbb, 0x12, 0x69, 0xa0, 0x07, 0xb6, 0x52, 0x28, 0x6d, 0x21, 0x7f, 0xd0, 0x99, 0x41, 0x51, 0x6f, 0xd5, - 0xc3, 0x3f, 0x58, 0xd2, 0x07, 0xa6, 0xa7, 0xde, 0x6c, 0x07, 0xc9, 0x87, 0x0e, 0x0b, 0x89, 0x9f, - 0x5b, 0x59, 0xf1, 0x46, 0xa8, 0x53, 0x25, 0xaf, 0xeb, 0xa2, 0xd9, 0xd3, 0xc9, 0x32, 0x50, 0xa7, - 0x6c, 0x49, 0xe6, 0x10, 0x60, 0x73, 0xa0, 0x53, 0xdd, 0x55, 0x4f, 0x75, 0x9c, 0xf7, 0xb2, 0xed, - 0xa5, 0x3b, 0x6e, 0x2a, 0xf6, 0xd7, 0x81, 0xe6, 0xf8, 0xab, 0x47, 0x21, 0xc9, 0x1a, 0x22, 0x61, - 0xe4, 0x69, 0x59, 0xf1, 0xea, 0x59, 0x3a, 0xb4, 0x20, 0xb5, 0xfa, 0x73, 0xb7, 0x49, 0xde, 0x43, - 0xc4, 0x0d, 0x29, 0x2d, 0x3a, 0x5e, 0xbd, 0xba, 0xfe, 0xd1, 0x05, 0xf7, 0xdc, 0xed, 0xb3, 0x39, - 0x3c, 0x71, 0x04, 0x44, 0xcb, 0x1b, 0x81, 0xec, 0x35, 0xc0, 0x06, 0xe5, 0x99, 0x48, 0xbf, 0x9f, - 0xec, 0xab, 0xde, 0x73, 0xbc, 0x7d, 0x59, 0xbc, 0x1b, 0xd2, 0x7a, 0x7e, 0x4d, 0xeb, 0x74, 0xea, - 0xc4, 0x29, 0x83, 0x58, 0x23, 0x1b, 0x42, 0xe4, 0x2d, 0x3c, 0xb4, 0x42, 0x85, 0x36, 0xfa, 0x5e, - 0x4f, 0x8e, 0xab, 0x2c, 0x83, 0x24, 0xc3, 0x9f, 0x78, 0x9b, 0xb5, 0xca, 0x1f, 0x87, 0x62, 0xfd, - 0xc9, 0x20, 0xf9, 0xd2, 0xee, 0x8b, 0xdb, 0x71, 0x1d, 0x8a, 0xc5, 0x4d, 0x20, 0xfe, 0x54, 0x09, - 0x67, 0x28, 0xfb, 0x08, 0x8f, 0x4d, 0x79, 0x93, 0x0b, 0xab, 0x7f, 0x01, 0x44, 0xb9, 0x99, 0x92, - 0x2d, 0x84, 0x26, 0x6b, 0x32, 0xfa, 0xff, 0xb0, 0xd7, 0x17, 0xcb, 0xf1, 0x05, 0x4b, 0xf7, 0x8e, - 0x64, 0x10, 0x6c, 0x50, 0x12, 0x7f, 0xa8, 0x0e, 0xe8, 0xc5, 0xc8, 0xf4, 0x88, 0xb2, 0x85, 0xd0, - 0x18, 0xec, 0x23, 0x75, 0x11, 0xa0, 0x8f, 0xd4, 0x20, 0x1b, 0x0d, 0x67, 0x7c, 0xf5, 0xc1, 0x5d, - 0xe4, 0xe6, 0x83, 0x1b, 0x44, 0x72, 0x47, 0x36, 0x30, 0x53, 0x29, 0x10, 0x8f, 0x8c, 0xb3, 0xb0, - 0x16, 0x2f, 0xc7, 0xc6, 0x0e, 0xe8, 0x5b, 0xa8, 0xbf, 0x67, 0xeb, 0xff, 0x01, 0x00, 0x00, 0xff, - 0xff, 0x19, 0x21, 0xd3, 0xfb, 0xe0, 0x04, 0x00, 0x00, + 0xc3, 0x3f, 0x58, 0xd2, 0x07, 0xcb, 0x40, 0xf5, 0xd4, 0x9b, 0xed, 0x20, 0xf9, 0xd0, 0x61, 0x21, + 0xf1, 0x73, 0x2b, 0x2b, 0xde, 0x08, 0x75, 0xaa, 0xe4, 0x75, 0x5d, 0x34, 0x7b, 0x3a, 0xd1, 0x7b, + 0xae, 0x24, 0x73, 0x08, 0xb0, 0x39, 0xd0, 0xa9, 0xee, 0xaa, 0xa7, 0x3a, 0xce, 0x7b, 0xd9, 0xf6, + 0xd2, 0x1d, 0x37, 0x15, 0xfb, 0xeb, 0x40, 0x73, 0xfc, 0xd5, 0xa3, 0x90, 0x64, 0x0d, 0x91, 0x30, + 0xf2, 0xb4, 0xac, 0x78, 0xf5, 0x2c, 0x1d, 0x5a, 0x90, 0x5a, 0xfd, 0xb9, 0xdb, 0x24, 0xef, 0x21, + 0xe2, 0x86, 0x94, 0x16, 0x1d, 0xaf, 0x5e, 0x5d, 0xff, 0xe8, 0x82, 0x7b, 0xee, 0xf6, 0xd9, 0x1c, + 0x9e, 0x38, 0x02, 0xa2, 0xe5, 0x8d, 0x40, 0xf6, 0x1a, 0x60, 0x83, 0xf2, 0x4c, 0xa4, 0xdf, 0x4f, + 0xf6, 0x55, 0xef, 0x39, 0xde, 0xbe, 0x2c, 0xde, 0x0d, 0x69, 0x3d, 0xbf, 0xa6, 0x75, 0x3a, 0x75, + 0xe2, 0x94, 0x41, 0xac, 0x91, 0x0d, 0x21, 0xf2, 0x16, 0x1e, 0x5a, 0xa1, 0x42, 0x1b, 0x7d, 0xaf, + 0x27, 0xc7, 0x55, 0x96, 0x41, 0x92, 0xe1, 0x4f, 0xbc, 0xcd, 0x5a, 0xe5, 0x8f, 0x43, 0xb1, 0xfe, + 0x64, 0x90, 0x7c, 0x69, 0xf7, 0xc5, 0xed, 0xb8, 0x0e, 0xc5, 0xe2, 0x26, 0x10, 0x7f, 0xaa, 0x84, + 0x33, 0x94, 0x7d, 0x84, 0xc7, 0xa6, 0xbc, 0xc9, 0x85, 0xd5, 0xbf, 0x00, 0xa2, 0xdc, 0x4c, 0xc9, + 0x16, 0x42, 0x93, 0x35, 0x19, 0xfd, 0x7f, 0xd8, 0xeb, 0x8b, 0xe5, 0xf8, 0x82, 0xa5, 0x7b, 0x47, + 0x32, 0x08, 0x36, 0x28, 0x89, 0x3f, 0x54, 0x07, 0xf4, 0x62, 0x64, 0x7a, 0x44, 0xd9, 0x42, 0x68, + 0x0c, 0xf6, 0x91, 0xba, 0x08, 0xd0, 0x47, 0x6a, 0x90, 0x8d, 0x86, 0x33, 0xbe, 0xfa, 0xe0, 0x2e, + 0x72, 0xf3, 0xc1, 0x0d, 0x22, 0xb9, 0x23, 0x1b, 0x98, 0xa9, 0x14, 0x88, 0x47, 0xc6, 0x59, 0x58, + 0x8b, 0x97, 0x63, 0x63, 0x07, 0xf4, 0x2d, 0xd4, 0xdf, 0xb3, 0xf5, 0xff, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x2f, 0x63, 0x84, 0x1c, 0xe0, 0x04, 0x00, 0x00, } diff --git a/runtime/service/proto/runtime.proto b/runtime/service/proto/runtime.proto index 4a6b1046..6abd1638 100644 --- a/runtime/service/proto/runtime.proto +++ b/runtime/service/proto/runtime.proto @@ -20,7 +20,7 @@ message Service { // local path of the source string path = 4; // command to execute - string exec = 5; + repeated string exec = 5; } message CreateOptions { From 94d409b180faf1d54395a37d65c36205c067d7c5 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 19 Nov 2019 20:49:01 +0000 Subject: [PATCH 230/344] Change DefaultImage to micro/go-micro --- runtime/kubernetes/client/kubernetes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index 4c378ea1..556237b8 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -17,7 +17,7 @@ const ( var ( // DefaultImage is default micro image - DefaultImage = "micro/micro" + DefaultImage = "micro/go-micro" // ServiceRegexp is used to validate service name ServiceRegexp = regexp.MustCompile("^" + dns1123LabelFmt + "$") ) From da6c1be607440ed828c6b7d9eab2de4b40e8982e Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Wed, 20 Nov 2019 10:55:47 +0300 Subject: [PATCH 231/344] dont panic on missing headers in broker event (#963) Signed-off-by: Vasiliy Tolstov --- server/subscriber.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/subscriber.go b/server/subscriber.go index e3f29286..f0f85cf8 100644 --- a/server/subscriber.go +++ b/server/subscriber.go @@ -169,6 +169,11 @@ func (s *rpcServer) createSubHandler(sb *subscriber, opts Options) broker.Handle return func(p broker.Event) error { msg := p.Message() + if msg.Header == nil { + // create empty map in case of headers empty to avoid panic later + msg.Header = make(map[string]string) + } + // get codec ct := msg.Header["Content-Type"] From 49d73faa5fd2d269afface92269192ee50811ee6 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Wed, 20 Nov 2019 13:28:30 +0300 Subject: [PATCH 232/344] return error to caller on grpc server request processing (#962) Signed-off-by: Vasiliy Tolstov --- server/grpc/grpc.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index ef613084..a09dd594 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -339,20 +339,26 @@ func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service, // define the handler func fn := func(ctx context.Context, req server.Request, rsp interface{}) error { + ch := make(chan error, 1) + defer close(ch) + defer func() { if r := recover(); r != nil { log.Log("panic recovered: ", r) log.Logf(string(debug.Stack())) + ch <- errors.InternalServerError("go.micro.server", "panic recovered: %v", r) } }() returnValues = function.Call([]reflect.Value{service.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 { - return err.(error) + ch <- err.(error) } - return nil + ch <- nil + + return <-ch } // wrap the handler func From c87a58db0acc6c0025e0d746d6a3ff19a626b57c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 20 Nov 2019 12:43:43 +0000 Subject: [PATCH 233/344] add ability to set web icon --- web/options.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/options.go b/web/options.go index 1c9bd6ee..9a31f6d0 100644 --- a/web/options.go +++ b/web/options.go @@ -72,6 +72,16 @@ func Name(n string) Option { } } +// Icon specifies an icon url to load in the UI +func Icon(ico string) Option { + return func(o *Options) { + if o.Metadata == nil { + o.Metadata = make(map[string]string) + } + o.Metadata["icon"] = ico + } +} + // Unique server id func Id(id string) Option { return func(o *Options) { From 55252cbc32a0ba4229ea522a2b3d1ab88f9d0597 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 20 Nov 2019 14:53:12 +0000 Subject: [PATCH 234/344] Fix the router test; get rid of time dependency (#964) --- router/default_test.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/router/default_test.go b/router/default_test.go index 4c3c933e..2d12a14f 100644 --- a/router/default_test.go +++ b/router/default_test.go @@ -75,12 +75,14 @@ func TestRouterAdvertise(t *testing.T) { var advertErr error + createDone := make(chan bool) errChan := make(chan error) var wg sync.WaitGroup wg.Add(1) go func() { wg.Done() + defer close(createDone) for _, route := range routes { log.Debugf("Creating route %v", route) if err := r.Table().Create(route); err != nil { @@ -92,13 +94,13 @@ func TestRouterAdvertise(t *testing.T) { }() var adverts int - doneChan := make(chan bool) + readDone := make(chan bool) wg.Add(1) go func() { defer func() { wg.Done() - doneChan <- true + readDone <- true }() for advert := range ch { select { @@ -113,7 +115,10 @@ func TestRouterAdvertise(t *testing.T) { } }() - <-doneChan + // done adding routes to routing table + <-createDone + // done reading adverts from the routing table + <-readDone if adverts != nrRoutes { t.Errorf("Expected %d adverts, received: %d", nrRoutes, adverts) From 11d81221cc90d1927004854854dc91ee861a8f27 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 20 Nov 2019 14:54:42 +0000 Subject: [PATCH 235/344] Runtime service implementation (#965) --- runtime/runtime.go | 2 + runtime/service/service.go | 185 +++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 runtime/service/service.go diff --git a/runtime/runtime.go b/runtime/runtime.go index 1cd3ae34..9b241e02 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -6,6 +6,8 @@ import "time" var ( // DefaultRuntime is default micro runtime DefaultRuntime Runtime = NewRuntime() + // DefaultName is default runtime service name + DefaultName = "go.micro.runtime" ) // Runtime is a service runtime manager diff --git a/runtime/service/service.go b/runtime/service/service.go new file mode 100644 index 00000000..347086fd --- /dev/null +++ b/runtime/service/service.go @@ -0,0 +1,185 @@ +package service + +import ( + "context" + "sync" + + "github.com/micro/go-micro/client" + "github.com/micro/go-micro/runtime" + pb "github.com/micro/go-micro/runtime/service/proto" +) + +type svc struct { + sync.RWMutex + options runtime.Options + runtime pb.RuntimeService +} + +// NewRuntime creates new service runtime and returns it +func NewRuntime(opts ...runtime.Option) runtime.Runtime { + // get default options + options := runtime.Options{} + + // apply requested options + for _, o := range opts { + o(&options) + } + + // create default client + cli := client.DefaultClient + + return &svc{ + options: options, + runtime: pb.NewRuntimeService(runtime.DefaultName, cli), + } +} + +// Init initializes runtime with given options +func (s *svc) Init(opts ...runtime.Option) error { + s.Lock() + defer s.Unlock() + + for _, o := range opts { + o(&s.options) + } + + return nil +} + +// Create registers a service in the runtime +func (s *svc) Create(svc *runtime.Service, opts ...runtime.CreateOption) error { + options := runtime.CreateOptions{} + // apply requested options + for _, o := range opts { + o(&options) + } + + // runtime service create request + req := &pb.CreateRequest{ + Service: &pb.Service{ + Name: svc.Name, + Version: svc.Version, + Source: svc.Source, + }, + Options: &pb.CreateOptions{ + Command: options.Command, + Env: options.Env, + }, + } + + if _, err := s.runtime.Create(context.Background(), req); err != nil { + return err + } + + return nil +} + +// Get returns the service with the given name from the runtime +func (s *svc) Get(name string, opts ...runtime.GetOption) ([]*runtime.Service, error) { + options := runtime.GetOptions{} + // apply requested options + for _, o := range opts { + o(&options) + } + + // runtime service create request + req := &pb.GetRequest{ + Name: name, + Options: &pb.GetOptions{ + Version: options.Version, + }, + } + + resp, err := s.runtime.Get(context.Background(), req) + if err != nil { + return nil, err + } + + services := make([]*runtime.Service, 0, len(resp.Services)) + for _, service := range resp.Services { + svc := &runtime.Service{ + Name: service.Name, + Version: service.Version, + Source: service.Source, + Path: service.Path, + Exec: service.Exec, + } + services = append(services, svc) + } + + return services, nil +} + +// Update updates the running service +func (s *svc) Update(svc *runtime.Service) error { + // runtime service create request + req := &pb.UpdateRequest{ + Service: &pb.Service{ + Name: svc.Name, + Version: svc.Version, + }, + } + + if _, err := s.runtime.Update(context.Background(), req); err != nil { + return err + } + + return nil +} + +// Delete stops and removes the service from the runtime +func (s *svc) Delete(svc *runtime.Service) error { + // runtime service create request + req := &pb.DeleteRequest{ + Service: &pb.Service{ + Name: svc.Name, + Version: svc.Version, + }, + } + + if _, err := s.runtime.Delete(context.Background(), req); err != nil { + return err + } + + return nil +} + +// List lists all services managed by the runtime +func (s *svc) List() ([]*runtime.Service, error) { + // list all services managed by the runtime + resp, err := s.runtime.List(context.Background(), &pb.ListRequest{}) + if err != nil { + return nil, err + } + + services := make([]*runtime.Service, 0, len(resp.Services)) + for _, service := range resp.Services { + svc := &runtime.Service{ + Name: service.Name, + Version: service.Version, + Source: service.Source, + Path: service.Path, + Exec: service.Exec, + } + services = append(services, svc) + } + + return services, nil +} + +// Start starts the runtime +func (s *svc) Start() error { + // NOTE: nothing to be done here + return nil +} + +// Stop stops the runtime +func (s *svc) Stop() error { + // NOTE: nothing to be done here + return nil +} + +// Returns the runtime service implementation +func (s *svc) String() string { + return "service" +} From 212144d6587a5881d2cbc69fca3fed974fb60303 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 21 Nov 2019 11:19:52 +0000 Subject: [PATCH 236/344] fix windows compilation error --- runtime/process/os/os_windows.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/runtime/process/os/os_windows.go b/runtime/process/os/os_windows.go index 8c5a4a02..a77f83e5 100644 --- a/runtime/process/os/os_windows.go +++ b/runtime/process/os/os_windows.go @@ -6,7 +6,6 @@ import ( "os" "os/exec" "strconv" - "syscall" "github.com/micro/go-micro/runtime/process" ) @@ -15,13 +14,13 @@ type Process struct { } func (p *Process) Exec(exe *process.Executable) error { - cmd := exec.Command(exe.Binary.Path) + cmd := exec.Command(exe.Package.Path) return cmd.Run() } func (p *Process) Fork(exe *process.Executable) (*process.PID, error) { // create command - cmd := exec.Command(exe.Binary.Path, exe.Args...) + cmd := exec.Command(exe.Package.Path, exe.Args...) // set env vars cmd.Env = append(cmd.Env, exe.Env...) From 8dc3fb964eaaf8587a1e431fc49f5ab1f85734f6 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 21 Nov 2019 17:31:13 +0000 Subject: [PATCH 237/344] Pass source of service to Deployment API; render templates properly (#969) * Pass source of service to Deployment API; render templates properly * Enable Go modules by default. Honor runtime.Service.Exec * Make sure you remove go.mod and go.sum --- Dockerfile | 2 +- runtime/kubernetes/client/kubernetes.go | 17 +++++++++++++---- runtime/kubernetes/client/templates.go | 4 ++-- runtime/kubernetes/client/utils.go | 6 +++--- runtime/kubernetes/client/utils_test.go | 9 +++++---- runtime/kubernetes/service.go | 17 ++++++++++------- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/Dockerfile b/Dockerfile index 91caabf9..975cca65 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,4 +4,4 @@ RUN apk --no-cache add make git gcc libtool musl-dev WORKDIR / COPY go.mod . COPY go.sum . -RUN go mod download +RUN go mod download && rm go.mod go.sum diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index 556237b8..ab8731b8 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -38,6 +38,8 @@ type Kubernetes interface { // DefaultService returns default micro kubernetes service definition func DefaultService(name, version string) *Service { + log.Debugf("kubernetes default service: name: %s, version: %s", name, version) + Labels := map[string]string{ "name": name, "version": version, @@ -73,7 +75,9 @@ func DefaultService(name, version string) *Service { } // DefaultService returns default micro kubernetes deployment definition -func DefaultDeployment(name, version string) *Deployment { +func DefaultDeployment(name, version, source string) *Deployment { + log.Debugf("kubernetes default deployment: name: %s, version: %s, source: %s", name, version, source) + Labels := map[string]string{ "name": name, "version": version, @@ -102,7 +106,12 @@ func DefaultDeployment(name, version string) *Deployment { log.Debugf("Runtime could not parse build: %v", err) } - // TODO: change the image name here + // enable go modules by default + env := EnvVar{ + Name: "GO111MODULE", + Value: "on", + } + Spec := &DeploymentSpec{ Replicas: 1, Selector: &LabelSelector{ @@ -114,8 +123,8 @@ func DefaultDeployment(name, version string) *Deployment { Containers: []Container{{ Name: name, Image: DefaultImage, - Env: []EnvVar{}, - Command: []string{"go", "run", "main.go"}, + Env: []EnvVar{env}, + Command: []string{"go", "run", source}, Ports: []ContainerPort{{ Name: name + "-port", ContainerPort: 8080, diff --git a/runtime/kubernetes/client/templates.go b/runtime/kubernetes/client/templates.go index 5292ac4f..48ae6efc 100644 --- a/runtime/kubernetes/client/templates.go +++ b/runtime/kubernetes/client/templates.go @@ -1,8 +1,8 @@ package client var templates = map[string]string{ - "deployments": deploymentTmpl, - "services": serviceTmpl, + "deployment": deploymentTmpl, + "service": serviceTmpl, } var deploymentTmpl = ` diff --git a/runtime/kubernetes/client/utils.go b/runtime/kubernetes/client/utils.go index b70ca44f..6174c522 100644 --- a/runtime/kubernetes/client/utils.go +++ b/runtime/kubernetes/client/utils.go @@ -10,9 +10,9 @@ import ( "text/template" ) -// renderTemplateFile renders template file in path into writer w with supplied data -func renderTemplate(text string, w io.Writer, data interface{}) error { - t := template.Must(template.New("kubernetes").Parse(text)) +// renderTemplateFile renders template for a given resource into writer w +func renderTemplate(resource string, w io.Writer, data interface{}) error { + t := template.Must(template.New("kubernetes").Parse(templates[resource])) if err := t.Execute(w, data); err != nil { return err diff --git a/runtime/kubernetes/client/utils_test.go b/runtime/kubernetes/client/utils_test.go index 0e69c012..a364debc 100644 --- a/runtime/kubernetes/client/utils_test.go +++ b/runtime/kubernetes/client/utils_test.go @@ -7,19 +7,20 @@ import ( func TestTemplates(t *testing.T) { name := "foo" - version := "1.2.3" + version := "123" + source := "github.com/foo/bar" // Render default service s := DefaultService(name, version) bs := new(bytes.Buffer) - if err := renderTemplate(serviceTmpl, bs, s); err != nil { + if err := renderTemplate(templates["service"], bs, s); err != nil { t.Errorf("Failed to render kubernetes service: %v", err) } // Render default deployment - d := DefaultDeployment(name, version) + d := DefaultDeployment(name, version, source) bd := new(bytes.Buffer) - if err := renderTemplate(deploymentTmpl, bd, d); err != nil { + if err := renderTemplate(templates["deployment"], bd, d); err != nil { t.Errorf("Failed to render kubernetes deployment: %v", err) } } diff --git a/runtime/kubernetes/service.go b/runtime/kubernetes/service.go index 0c02d1b9..7b7d2004 100644 --- a/runtime/kubernetes/service.go +++ b/runtime/kubernetes/service.go @@ -19,7 +19,7 @@ type service struct { func newService(s *runtime.Service, c runtime.CreateOptions) *service { kservice := client.DefaultService(s.Name, s.Version) - kdeploy := client.DefaultDeployment(s.Name, s.Version) + kdeploy := client.DefaultDeployment(s.Name, s.Version, s.Source) env := make([]client.EnvVar, 0, len(c.Env)) for _, evar := range c.Env { @@ -27,15 +27,18 @@ func newService(s *runtime.Service, c runtime.CreateOptions) *service { env = append(env, client.EnvVar{Name: evarPair[0], Value: evarPair[1]}) } - // TODO: should we append instead of overriding? - // if environment has been supplied update deployment + // if environment has been supplied update deployment default environment if len(env) > 0 { - kdeploy.Spec.Template.PodSpec.Containers[0].Env = env + kdeploy.Spec.Template.PodSpec.Containers[0].Env = append(kdeploy.Spec.Template.PodSpec.Containers[0].Env, env...) } - // if Command has been supplied override the default command - if len(c.Command) > 0 { - kdeploy.Spec.Template.PodSpec.Containers[0].Command = c.Command + // if Exec/Command has been supplied override the default command + if len(s.Exec) > 0 { + kdeploy.Spec.Template.PodSpec.Containers[0].Command = s.Exec + } else { + if len(c.Command) > 0 { + kdeploy.Spec.Template.PodSpec.Containers[0].Command = c.Command + } } return &service{ From 38e29c510192f1dd5b20721c53ffe9578e7f66de Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Fri, 22 Nov 2019 17:10:00 +0000 Subject: [PATCH 238/344] Svc metadata (#972) * Added service metadata * Added metadata to runtime service * Add Annotations metadata to service metadata * Add micro/micro as default service owners * Update runtime/kubernetes/client/kubernetes.go Change comment Co-Authored-By: Jake Sanders --- runtime/kubernetes/client/client.go | 7 +- runtime/kubernetes/client/kubernetes.go | 21 ++-- runtime/kubernetes/client/templates.go | 6 + runtime/kubernetes/client/types.go | 18 ++- runtime/kubernetes/kubernetes.go | 148 ++++++++++++++++-------- runtime/runtime.go | 2 + runtime/service/handler/handler.go | 22 ++-- runtime/service/proto/runtime.pb.go | 78 ++++++++----- runtime/service/proto/runtime.proto | 2 + runtime/service/service.go | 29 ++--- 10 files changed, 209 insertions(+), 124 deletions(-) diff --git a/runtime/kubernetes/client/client.go b/runtime/kubernetes/client/client.go index bfebad9b..6206ea15 100644 --- a/runtime/kubernetes/client/client.go +++ b/runtime/kubernetes/client/client.go @@ -152,10 +152,5 @@ func (c *client) List(r *Resource) error { "micro": "service", } - return api.NewRequest(c.opts). - Get(). - Resource(r.Kind). - Params(&api.Params{LabelSelector: labels}). - Do(). - Into(r.Value) + return c.Get(r, labels) } diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index ab8731b8..0de53b59 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -50,7 +50,6 @@ func DefaultService(name, version string) *Service { if len(version) > 0 { // API service object name joins name and version over "-" svcName = strings.Join([]string{name, version}, "-") - } Metadata := &Metadata{ @@ -84,26 +83,32 @@ func DefaultDeployment(name, version, source string) *Deployment { "micro": "service", } - // API deployment object name joins name and version over "=" - depName := strings.Join([]string{name, version}, "-") + depName := name + if len(version) > 0 { + // API deployment object name joins name and version over "-" + depName = strings.Join([]string{name, version}, "-") + } Metadata := &Metadata{ Name: depName, Namespace: "default", Version: version, Labels: Labels, + Annotations: map[string]string{ + "source": source, + "owner": "micro", + "group": "micro", + }, } // TODO: we need to figure out this version stuff - // might be worth adding Build to runtime.Service + // might have to add Build to runtime.Service buildTime, err := strconv.ParseInt(version, 10, 64) if err == nil { buildUnixTimeUTC := time.Unix(buildTime, 0) - Metadata.Annotations = map[string]string{ - "build": buildUnixTimeUTC.Format(time.RFC3339), - } + Metadata.Annotations["build"] = buildUnixTimeUTC.Format(time.RFC3339) } else { - log.Debugf("Runtime could not parse build: %v", err) + log.Debugf("could not parse build: %v", err) } // enable go modules by default diff --git a/runtime/kubernetes/client/templates.go b/runtime/kubernetes/client/templates.go index 48ae6efc..8f960051 100644 --- a/runtime/kubernetes/client/templates.go +++ b/runtime/kubernetes/client/templates.go @@ -17,6 +17,12 @@ metadata: {{ $key }}: "{{ $value }}" {{- end }} {{- end }} + annotations: + {{- with .Metadata.Annotations }} + {{- range $key, $value := . }} + {{ $key }}: "{{ $value }}" + {{- end }} + {{- end }} spec: replicas: {{ .Spec.Replicas }} selector: diff --git a/runtime/kubernetes/client/types.go b/runtime/kubernetes/client/types.go index 882b826e..b9bfa4a3 100644 --- a/runtime/kubernetes/client/types.go +++ b/runtime/kubernetes/client/types.go @@ -103,13 +103,21 @@ type DeploymentSpec struct { Template *Template `json:"template,omitempty"` } +// DeploymentCondition describes the state of deployment +type DeploymentCondition struct { + Type string `json:"type"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + // DeploymentStatus is returned when querying deployment type DeploymentStatus struct { - Replicas int `json:"replicas,omitempty"` - UpdatedReplicas int `json:"updatedReplicas,omitempty"` - ReadyReplicas int `json:"readyReplicas,omitempty"` - AvailableReplicas int `json:"availableReplicas,omitempty"` - UnavailableReplicas int `json:"unavailableReplicas,omitempty"` + Replicas int `json:"replicas,omitempty"` + UpdatedReplicas int `json:"updatedReplicas,omitempty"` + ReadyReplicas int `json:"readyReplicas,omitempty"` + AvailableReplicas int `json:"availableReplicas,omitempty"` + UnavailableReplicas int `json:"unavailableReplicas,omitempty"` + Conditions []DeploymentCondition `json:"conditions,omitempty"` } // Deployment is Kubernetes deployment diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 1939c46a..26956856 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -109,6 +109,90 @@ func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) er return nil } +// getMicroService queries kubernetes for micro service +// NOTE: this function is not thread-safe +func (k *kubernetes) getMicroService(labels map[string]string) ([]*runtime.Service, error) { + // get the service status + serviceList := new(client.ServiceList) + r := &client.Resource{ + Kind: "service", + Value: serviceList, + } + if err := k.client.Get(r, labels); err != nil { + return nil, err + } + + // get the deployment status + depList := new(client.DeploymentList) + d := &client.Resource{ + Kind: "deployment", + Value: depList, + } + if err := k.client.Get(d, labels); err != nil { + return nil, err + } + + // service map + svcMap := make(map[string]*runtime.Service) + + // collect info from kubernetes service + for _, kservice := range serviceList.Items { + name := kservice.Metadata.Labels["name"] + version := kservice.Metadata.Labels["version"] + svcMap[name] = &runtime.Service{ + Name: name, + Version: version, + Metadata: make(map[string]string), + } + // copy annotations metadata into service metadata + for k, v := range kservice.Metadata.Annotations { + svcMap[name].Metadata[k] = v + } + } + + // collect additional info from kubernetes deployment + for _, kdep := range depList.Items { + name := kdep.Metadata.Labels["name"] + if svc, ok := svcMap[name]; ok { + // set the service source + svc.Source = kdep.Metadata.Annotations["source"] + // copy all annotations metadata into service metadata + for k, v := range kdep.Metadata.Annotations { + svc.Metadata[k] = v + } + + // parse out deployment status + if len(kdep.Status.Conditions) > 0 { + status := kdep.Status.Conditions[0].Type + // pick the last known condition type and mark the service status with it + log.Debugf("Runtime setting %s service deployment status: %v", name, status) + svc.Metadata["status"] = status + } + + // parse out deployment build + if build, ok := kdep.Metadata.Annotations["build"]; ok { + buildTime, err := time.Parse(time.RFC3339, build) + if err != nil { + log.Debugf("Runtime failed parsing build time for %s: %v", name, err) + continue + } + svc.Metadata["build"] = fmt.Sprintf("%d", buildTime.Unix()) + continue + } + // if no build annotation is found, set it to current time + svc.Metadata["build"] = fmt.Sprintf("%d", time.Now().Unix()) + } + } + + // collect all the services and return + services := make([]*runtime.Service, 0, len(serviceList.Items)) + for _, service := range svcMap { + services = append(services, service) + } + + return services, nil +} + // Get returns all instances of given service func (k *kubernetes) Get(name string, opts ...runtime.GetOption) ([]*runtime.Service, error) { k.Lock() @@ -119,11 +203,12 @@ func (k *kubernetes) Get(name string, opts ...runtime.GetOption) ([]*runtime.Ser return nil, errors.New("missing service name") } - // set the default label + // set the default labels labels := map[string]string{ "micro": "service", "name": name, } + var options runtime.GetOptions for _, o := range opts { o(&options) @@ -136,25 +221,21 @@ func (k *kubernetes) Get(name string, opts ...runtime.GetOption) ([]*runtime.Ser log.Debugf("Runtime querying service %s", name) - serviceList := new(client.ServiceList) - r := &client.Resource{ - Kind: "service", - Value: serviceList, - } - if err := k.client.Get(r, labels); err != nil { - return nil, err + return k.getMicroService(labels) +} + +// List the managed services +func (k *kubernetes) List() ([]*runtime.Service, error) { + k.Lock() + defer k.Unlock() + + labels := map[string]string{ + "micro": "service", } - services := make([]*runtime.Service, 0, len(serviceList.Items)) - for _, kservice := range serviceList.Items { - service := &runtime.Service{ - Name: kservice.Metadata.Name, - Version: kservice.Metadata.Version, - } - services = append(services, service) - } + log.Debugf("Runtime listing all micro services") - return services, nil + return k.getMicroService(labels) } // Update the service in place @@ -202,39 +283,6 @@ func (k *kubernetes) Delete(s *runtime.Service) error { return nil } -// List the managed services -func (k *kubernetes) List() ([]*runtime.Service, error) { - serviceList := new(client.ServiceList) - r := &client.Resource{ - Kind: "service", - Value: serviceList, - } - - if err := k.client.List(r); err != nil { - return nil, err - } - - log.Debugf("Runtime found %d micro services", len(serviceList.Items)) - - services := make([]*runtime.Service, 0, len(serviceList.Items)) - - for _, service := range serviceList.Items { - buildTime, err := time.Parse(time.RFC3339, service.Metadata.Annotations["build"]) - if err != nil { - log.Debugf("Runtime error parsing build time for %s: %v", service.Metadata.Name, err) - continue - } - // add the service to the list of services - svc := &runtime.Service{ - Name: service.Metadata.Name, - Version: fmt.Sprintf("%d", buildTime.Unix()), - } - services = append(services, svc) - } - - return services, nil -} - // run runs the runtime management loop func (k *kubernetes) run(events <-chan runtime.Event) { t := time.NewTicker(time.Second * 10) diff --git a/runtime/runtime.go b/runtime/runtime.go index 9b241e02..e323614d 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -88,4 +88,6 @@ type Service struct { Exec []string // Version of the service Version string + // Metadata stores metadata + Metadata map[string]string } diff --git a/runtime/service/handler/handler.go b/runtime/service/handler/handler.go index aecef40b..f7694d79 100644 --- a/runtime/service/handler/handler.go +++ b/runtime/service/handler/handler.go @@ -14,21 +14,23 @@ type Runtime struct { func toProto(s *runtime.Service) *pb.Service { return &pb.Service{ - Name: s.Name, - Version: s.Version, - Source: s.Source, - Path: s.Path, - Exec: s.Exec, + Name: s.Name, + Version: s.Version, + Source: s.Source, + Path: s.Path, + Exec: s.Exec, + Metadata: s.Metadata, } } func toService(s *pb.Service) *runtime.Service { return &runtime.Service{ - Name: s.Name, - Version: s.Version, - Source: s.Source, - Path: s.Path, - Exec: s.Exec, + Name: s.Name, + Version: s.Version, + Source: s.Source, + Path: s.Path, + Exec: s.Exec, + Metadata: s.Metadata, } } diff --git a/runtime/service/proto/runtime.pb.go b/runtime/service/proto/runtime.pb.go index 7a9d2bc1..5e7d8938 100644 --- a/runtime/service/proto/runtime.pb.go +++ b/runtime/service/proto/runtime.pb.go @@ -30,10 +30,12 @@ type Service struct { // local path of the source Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` // command to execute - Exec []string `protobuf:"bytes,5,rep,name=exec,proto3" json:"exec,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Exec []string `protobuf:"bytes,5,rep,name=exec,proto3" json:"exec,omitempty"` + // service metadata + 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"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Service) Reset() { *m = Service{} } @@ -96,6 +98,13 @@ func (m *Service) GetExec() []string { return nil } +func (m *Service) GetMetadata() map[string]string { + if m != nil { + return m.Metadata + } + return nil +} + type CreateOptions struct { // command to pass in Command []string `protobuf:"bytes,1,rep,name=command,proto3" json:"command,omitempty"` @@ -570,6 +579,7 @@ func (m *ListResponse) GetServices() []*Service { func init() { proto.RegisterType((*Service)(nil), "go.micro.runtime.Service") + proto.RegisterMapType((map[string]string)(nil), "go.micro.runtime.Service.MetadataEntry") proto.RegisterType((*CreateOptions)(nil), "go.micro.runtime.CreateOptions") proto.RegisterType((*CreateRequest)(nil), "go.micro.runtime.CreateRequest") proto.RegisterType((*CreateResponse)(nil), "go.micro.runtime.CreateResponse") @@ -587,32 +597,36 @@ func init() { func init() { proto.RegisterFile("runtime.proto", fileDescriptor_86e2dd377c869464) } var fileDescriptor_86e2dd377c869464 = []byte{ - // 425 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xc9, 0xcb, 0xd3, 0x40, - 0x14, 0xff, 0xda, 0xd4, 0x44, 0x5f, 0x8c, 0x94, 0x39, 0xc8, 0x58, 0x5c, 0xca, 0x1c, 0xc4, 0x53, - 0x0e, 0x2d, 0x0a, 0x9e, 0x8d, 0xf4, 0x62, 0x11, 0x52, 0x04, 0xaf, 0x31, 0x7d, 0x68, 0xc0, 0x64, - 0x62, 0x66, 0x52, 0xbd, 0x79, 0xf2, 0xff, 0x96, 0xd9, 0xba, 0xa4, 0x93, 0xef, 0xd2, 0xdb, 0xbc, - 0xa5, 0xbf, 0xf7, 0x5b, 0x4a, 0x20, 0xe9, 0xfa, 0x46, 0x56, 0x35, 0xa6, 0x6d, 0xc7, 0x25, 0x27, - 0xf3, 0xef, 0x3c, 0xad, 0xab, 0xb2, 0xe3, 0xa9, 0xed, 0xb3, 0xdf, 0x10, 0xed, 0xb0, 0x3b, 0x54, - 0x25, 0x12, 0x02, 0xb3, 0xa6, 0xa8, 0x91, 0x4e, 0x96, 0x93, 0x37, 0x8f, 0x72, 0xfd, 0x26, 0x14, - 0xa2, 0x03, 0x76, 0xa2, 0xe2, 0x0d, 0x9d, 0xea, 0xb6, 0x2b, 0xc9, 0x53, 0x08, 0x05, 0xef, 0xbb, - 0x12, 0x69, 0xa0, 0x07, 0xb6, 0x52, 0x28, 0x6d, 0x21, 0x7f, 0xd0, 0x99, 0x41, 0x51, 0x6f, 0xd5, - 0xc3, 0x3f, 0x58, 0xd2, 0x07, 0xcb, 0x40, 0xf5, 0xd4, 0x9b, 0xed, 0x20, 0xf9, 0xd0, 0x61, 0x21, - 0xf1, 0x73, 0x2b, 0x2b, 0xde, 0x08, 0x75, 0xaa, 0xe4, 0x75, 0x5d, 0x34, 0x7b, 0x3a, 0xd1, 0x7b, - 0xae, 0x24, 0x73, 0x08, 0xb0, 0x39, 0xd0, 0xa9, 0xee, 0xaa, 0xa7, 0x3a, 0xce, 0x7b, 0xd9, 0xf6, - 0xd2, 0x1d, 0x37, 0x15, 0xfb, 0xeb, 0x40, 0x73, 0xfc, 0xd5, 0xa3, 0x90, 0x64, 0x0d, 0x91, 0x30, - 0xf2, 0xb4, 0xac, 0x78, 0xf5, 0x2c, 0x1d, 0x5a, 0x90, 0x5a, 0xfd, 0xb9, 0xdb, 0x24, 0xef, 0x21, - 0xe2, 0x86, 0x94, 0x16, 0x1d, 0xaf, 0x5e, 0x5d, 0xff, 0xe8, 0x82, 0x7b, 0xee, 0xf6, 0xd9, 0x1c, - 0x9e, 0x38, 0x02, 0xa2, 0xe5, 0x8d, 0x40, 0xf6, 0x1a, 0x60, 0x83, 0xf2, 0x4c, 0xa4, 0xdf, 0x4f, - 0xf6, 0x55, 0xef, 0x39, 0xde, 0xbe, 0x2c, 0xde, 0x0d, 0x69, 0x3d, 0xbf, 0xa6, 0x75, 0x3a, 0x75, - 0xe2, 0x94, 0x41, 0xac, 0x91, 0x0d, 0x21, 0xf2, 0x16, 0x1e, 0x5a, 0xa1, 0x42, 0x1b, 0x7d, 0xaf, - 0x27, 0xc7, 0x55, 0x96, 0x41, 0x92, 0xe1, 0x4f, 0xbc, 0xcd, 0x5a, 0xe5, 0x8f, 0x43, 0xb1, 0xfe, - 0x64, 0x90, 0x7c, 0x69, 0xf7, 0xc5, 0xed, 0xb8, 0x0e, 0xc5, 0xe2, 0x26, 0x10, 0x7f, 0xaa, 0x84, - 0x33, 0x94, 0x7d, 0x84, 0xc7, 0xa6, 0xbc, 0xc9, 0x85, 0xd5, 0xbf, 0x00, 0xa2, 0xdc, 0x4c, 0xc9, - 0x16, 0x42, 0x93, 0x35, 0x19, 0xfd, 0x7f, 0xd8, 0xeb, 0x8b, 0xe5, 0xf8, 0x82, 0xa5, 0x7b, 0x47, - 0x32, 0x08, 0x36, 0x28, 0x89, 0x3f, 0x54, 0x07, 0xf4, 0x62, 0x64, 0x7a, 0x44, 0xd9, 0x42, 0x68, - 0x0c, 0xf6, 0x91, 0xba, 0x08, 0xd0, 0x47, 0x6a, 0x90, 0x8d, 0x86, 0x33, 0xbe, 0xfa, 0xe0, 0x2e, - 0x72, 0xf3, 0xc1, 0x0d, 0x22, 0xb9, 0x23, 0x1b, 0x98, 0xa9, 0x14, 0x88, 0x47, 0xc6, 0x59, 0x58, - 0x8b, 0x97, 0x63, 0x63, 0x07, 0xf4, 0x2d, 0xd4, 0xdf, 0xb3, 0xf5, 0xff, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x2f, 0x63, 0x84, 0x1c, 0xe0, 0x04, 0x00, 0x00, + // 485 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcb, 0x6f, 0x94, 0x40, + 0x18, 0x2f, 0xcb, 0x16, 0xea, 0x87, 0x98, 0xcd, 0xc4, 0x98, 0x71, 0xe3, 0x63, 0xc3, 0x41, 0x7b, + 0xe2, 0xb0, 0x8d, 0xc6, 0xc7, 0xb1, 0x34, 0x7b, 0x71, 0x63, 0x42, 0x63, 0xe2, 0x75, 0x64, 0xbf, + 0x28, 0xb1, 0x30, 0xc8, 0x0c, 0x1b, 0x7b, 0xf2, 0xe4, 0x1f, 0xed, 0xcd, 0xcc, 0x6b, 0xdb, 0xa5, + 0xd0, 0xcb, 0xde, 0xbe, 0x17, 0x3f, 0x7e, 0x0f, 0x02, 0xc4, 0x6d, 0x57, 0xcb, 0xb2, 0xc2, 0xb4, + 0x69, 0xb9, 0xe4, 0x64, 0xf6, 0x9d, 0xa7, 0x55, 0x59, 0xb4, 0x3c, 0xb5, 0xf3, 0xe4, 0x9f, 0x07, + 0xe1, 0x25, 0xb6, 0xdb, 0xb2, 0x40, 0x42, 0x60, 0x5a, 0xb3, 0x0a, 0xa9, 0xb7, 0xf0, 0x4e, 0x1f, + 0xe4, 0xba, 0x26, 0x14, 0xc2, 0x2d, 0xb6, 0xa2, 0xe4, 0x35, 0x9d, 0xe8, 0xb1, 0x6b, 0xc9, 0x13, + 0x08, 0x04, 0xef, 0xda, 0x02, 0xa9, 0xaf, 0x17, 0xb6, 0x53, 0x28, 0x0d, 0x93, 0x3f, 0xe8, 0xd4, + 0xa0, 0xa8, 0x5a, 0xcd, 0xf0, 0x37, 0x16, 0xf4, 0x78, 0xe1, 0xab, 0x99, 0xaa, 0xc9, 0x39, 0x9c, + 0x54, 0x28, 0xd9, 0x86, 0x49, 0x46, 0x83, 0x85, 0x7f, 0x1a, 0x2d, 0x5f, 0xa7, 0x7d, 0x7a, 0xa9, + 0xa5, 0x96, 0xae, 0xed, 0xe5, 0x45, 0x2d, 0xdb, 0xeb, 0x7c, 0xf7, 0xe0, 0xfc, 0x23, 0xc4, 0x7b, + 0x2b, 0x32, 0x03, 0xff, 0x27, 0x5e, 0x5b, 0x09, 0xaa, 0x24, 0x8f, 0xe1, 0x78, 0xcb, 0xae, 0x3a, + 0xb4, 0xfc, 0x4d, 0xf3, 0x61, 0xf2, 0xce, 0x4b, 0x2e, 0x21, 0x3e, 0x6f, 0x91, 0x49, 0xfc, 0xdc, + 0xc8, 0x92, 0xd7, 0x42, 0x89, 0x2d, 0x78, 0x55, 0xb1, 0x7a, 0x43, 0x3d, 0xcd, 0xd4, 0xb5, 0x0a, + 0x16, 0xeb, 0x2d, 0x9d, 0xe8, 0xa9, 0x2a, 0x95, 0x7c, 0xde, 0xc9, 0xa6, 0x93, 0x4e, 0xbe, 0xe9, + 0x92, 0x3f, 0x0e, 0x34, 0xc7, 0x5f, 0x1d, 0x0a, 0x49, 0xce, 0x20, 0x14, 0x46, 0x85, 0x66, 0x15, + 0x2d, 0x9f, 0x8e, 0xca, 0xcc, 0xdd, 0x25, 0x79, 0x0f, 0x21, 0x37, 0xa4, 0x34, 0xed, 0x68, 0xf9, + 0xf2, 0xee, 0x43, 0x7b, 0xdc, 0x73, 0x77, 0x9f, 0xcc, 0xe0, 0x91, 0x23, 0x20, 0x1a, 0x5e, 0x0b, + 0x4c, 0x5e, 0x01, 0xac, 0x50, 0xde, 0x12, 0x39, 0x9c, 0x68, 0xf2, 0x55, 0xdf, 0x39, 0xde, 0x43, + 0x5f, 0xc3, 0xdb, 0x3e, 0xad, 0x67, 0x77, 0x69, 0xdd, 0xbc, 0xea, 0x86, 0x53, 0x06, 0x91, 0x46, + 0x36, 0x84, 0xc8, 0x1b, 0x38, 0xb1, 0x42, 0x85, 0x36, 0xfa, 0x5e, 0x4f, 0x76, 0xa7, 0x49, 0x06, + 0x71, 0x86, 0x57, 0x78, 0x98, 0xb5, 0xca, 0x1f, 0x87, 0x62, 0xfd, 0xc9, 0x20, 0xfe, 0xd2, 0x6c, + 0xd8, 0xe1, 0xb8, 0x0e, 0xc5, 0xe2, 0xc6, 0x10, 0x7d, 0x2a, 0x85, 0x33, 0x34, 0xb9, 0x80, 0x87, + 0xa6, 0x3d, 0xc8, 0x85, 0xe5, 0x5f, 0x1f, 0xc2, 0xdc, 0x6c, 0xc9, 0x1a, 0x02, 0x93, 0x35, 0x19, + 0xfd, 0x3e, 0xec, 0xdb, 0xe7, 0x8b, 0xf1, 0x03, 0x4b, 0xf7, 0x88, 0x64, 0xe0, 0xaf, 0x50, 0x92, + 0xe1, 0x50, 0x1d, 0xd0, 0xf3, 0x91, 0xed, 0x0e, 0x65, 0x0d, 0x81, 0x31, 0x78, 0x88, 0xd4, 0x5e, + 0x80, 0x43, 0xa4, 0x7a, 0xd9, 0x68, 0x38, 0xe3, 0xeb, 0x10, 0xdc, 0x5e, 0x6e, 0x43, 0x70, 0xbd, + 0x48, 0x8e, 0xc8, 0x0a, 0xa6, 0x2a, 0x05, 0x32, 0x20, 0xe3, 0x56, 0x58, 0xf3, 0x17, 0x63, 0x6b, + 0x07, 0xf4, 0x2d, 0xd0, 0xbf, 0xd4, 0xb3, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbc, 0xce, 0x6e, + 0x31, 0x63, 0x05, 0x00, 0x00, } diff --git a/runtime/service/proto/runtime.proto b/runtime/service/proto/runtime.proto index 6abd1638..44a83df4 100644 --- a/runtime/service/proto/runtime.proto +++ b/runtime/service/proto/runtime.proto @@ -21,6 +21,8 @@ message Service { string path = 4; // command to execute repeated string exec = 5; + // service metadata + map metadata = 6; } message CreateOptions { diff --git a/runtime/service/service.go b/runtime/service/service.go index 347086fd..00752989 100644 --- a/runtime/service/service.go +++ b/runtime/service/service.go @@ -57,9 +57,10 @@ func (s *svc) Create(svc *runtime.Service, opts ...runtime.CreateOption) error { // runtime service create request req := &pb.CreateRequest{ Service: &pb.Service{ - Name: svc.Name, - Version: svc.Version, - Source: svc.Source, + Name: svc.Name, + Version: svc.Version, + Source: svc.Source, + Metadata: svc.Metadata, }, Options: &pb.CreateOptions{ Command: options.Command, @@ -98,11 +99,12 @@ func (s *svc) Get(name string, opts ...runtime.GetOption) ([]*runtime.Service, e services := make([]*runtime.Service, 0, len(resp.Services)) for _, service := range resp.Services { svc := &runtime.Service{ - Name: service.Name, - Version: service.Version, - Source: service.Source, - Path: service.Path, - Exec: service.Exec, + Name: service.Name, + Version: service.Version, + Source: service.Source, + Path: service.Path, + Exec: service.Exec, + Metadata: service.Metadata, } services = append(services, svc) } @@ -155,11 +157,12 @@ func (s *svc) List() ([]*runtime.Service, error) { services := make([]*runtime.Service, 0, len(resp.Services)) for _, service := range resp.Services { svc := &runtime.Service{ - Name: service.Name, - Version: service.Version, - Source: service.Source, - Path: service.Path, - Exec: service.Exec, + Name: service.Name, + Version: service.Version, + Source: service.Source, + Path: service.Path, + Exec: service.Exec, + Metadata: service.Metadata, } services = append(services, svc) } From cae4148594da4d13ba2fed0f991476cdc065592f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 23 Nov 2019 08:25:56 +0000 Subject: [PATCH 239/344] Fix platform specific os/process build --- runtime/process/os/os.go | 9 ++------- runtime/process/os/os_windows.go | 7 ------- runtime/process/os/process.go | 12 ++++++++++++ 3 files changed, 14 insertions(+), 14 deletions(-) create mode 100644 runtime/process/os/process.go diff --git a/runtime/process/os/os.go b/runtime/process/os/os.go index 0e6bc79f..dda05ab9 100644 --- a/runtime/process/os/os.go +++ b/runtime/process/os/os.go @@ -1,3 +1,5 @@ +// +build !windows + // Package os runs processes locally package os @@ -11,9 +13,6 @@ import ( "github.com/micro/go-micro/runtime/process" ) -type Process struct { -} - func (p *Process) Exec(exe *process.Executable) error { cmd := exec.Command(exe.Package.Path) return cmd.Run() @@ -99,7 +98,3 @@ func (p *Process) Wait(pid *process.PID) error { return fmt.Errorf(ps.String()) } - -func NewProcess(opts ...process.Option) process.Process { - return &Process{} -} diff --git a/runtime/process/os/os_windows.go b/runtime/process/os/os_windows.go index a77f83e5..d4420968 100644 --- a/runtime/process/os/os_windows.go +++ b/runtime/process/os/os_windows.go @@ -10,9 +10,6 @@ import ( "github.com/micro/go-micro/runtime/process" ) -type Process struct { -} - func (p *Process) Exec(exe *process.Executable) error { cmd := exec.Command(exe.Package.Path) return cmd.Run() @@ -90,7 +87,3 @@ func (p *Process) Wait(pid *process.PID) error { return fmt.Errorf(ps.String()) } - -func NewProcess(opts ...process.Option) process.Process { - return &Process{} -} diff --git a/runtime/process/os/process.go b/runtime/process/os/process.go new file mode 100644 index 00000000..e756a84c --- /dev/null +++ b/runtime/process/os/process.go @@ -0,0 +1,12 @@ +// Package os runs processes locally +package os + +import ( + "github.com/micro/go-micro/runtime/process" +) + +type Process struct{} + +func NewProcess(opts ...process.Option) process.Process { + return &Process{} +} From 64a251d69a7c643aa2ef9c13b0ccaf435c96b175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E6=B3=BD=E8=BD=A9?= Date: Sat, 23 Nov 2019 22:13:17 +0800 Subject: [PATCH 240/344] improve the syncMap.Iterate test to make it 100% reproducible (#970) * improve the syncMap.Iterate test to make it 100% reproducible * rename store/mocks/Store.go * rename mocks/store to mock/store --- go.mod | 1 + go.sum | 1 + store/mock/store.go | 103 ++++++++++++++++++++++++++++++++++++++++++++ sync/map_test.go | 17 ++++---- 4 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 store/mock/store.go diff --git a/go.mod b/go.mod index 48696ba9..0812f043 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( github.com/nlopes/slack v0.6.0 github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c github.com/pkg/errors v0.8.1 + github.com/stretchr/testify v1.4.0 go.uber.org/zap v1.12.0 // indirect golang.org/x/crypto v0.0.0-20191108234033-bd318be0434a golang.org/x/net v0.0.0-20191109021931-daa7c04131f5 diff --git a/go.sum b/go.sum index 00550ff0..1be95770 100644 --- a/go.sum +++ b/go.sum @@ -360,6 +360,7 @@ github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/store/mock/store.go b/store/mock/store.go new file mode 100644 index 00000000..fe296b02 --- /dev/null +++ b/store/mock/store.go @@ -0,0 +1,103 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mock + +import mock "github.com/stretchr/testify/mock" +import store "github.com/micro/go-micro/store" + +// Store is an autogenerated mock type for the Store type +type Store struct { + mock.Mock +} + +// Delete provides a mock function with given fields: key +func (_m *Store) Delete(key ...string) error { + _va := make([]interface{}, len(key)) + for _i := range key { + _va[_i] = key[_i] + } + var _ca []interface{} + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(...string) error); ok { + r0 = rf(key...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// List provides a mock function with given fields: +func (_m *Store) List() ([]*store.Record, error) { + ret := _m.Called() + + var r0 []*store.Record + if rf, ok := ret.Get(0).(func() []*store.Record); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*store.Record) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Read provides a mock function with given fields: key +func (_m *Store) Read(key ...string) ([]*store.Record, error) { + _va := make([]interface{}, len(key)) + for _i := range key { + _va[_i] = key[_i] + } + var _ca []interface{} + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 []*store.Record + if rf, ok := ret.Get(0).(func(...string) []*store.Record); ok { + r0 = rf(key...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*store.Record) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(...string) error); ok { + r1 = rf(key...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Write provides a mock function with given fields: rec +func (_m *Store) Write(rec ...*store.Record) error { + _va := make([]interface{}, len(rec)) + for _i := range rec { + _va[_i] = rec[_i] + } + var _ca []interface{} + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(...*store.Record) error); ok { + r0 = rf(rec...) + } else { + r0 = ret.Error(0) + } + + return r0 +} diff --git a/sync/map_test.go b/sync/map_test.go index 8e3e0574..fa54cd2c 100644 --- a/sync/map_test.go +++ b/sync/map_test.go @@ -4,14 +4,13 @@ import ( "testing" "time" - store "github.com/micro/go-micro/store" - mem_store "github.com/micro/go-micro/store/memory" + "github.com/micro/go-micro/store" + store_mock "github.com/micro/go-micro/store/mock" mem_lock "github.com/micro/go-micro/sync/lock/memory" + "github.com/stretchr/testify/mock" ) func TestIterate(t *testing.T) { - s1 := mem_store.NewStore() - s2 := mem_store.NewStore() recA := &store.Record{ Key: "A", Value: nil, @@ -20,10 +19,12 @@ func TestIterate(t *testing.T) { Key: "B", Value: nil, } - s1.Write(recA) - s1.Write(recB) - s2.Write(recB) - s2.Write(recA) + s1 := &store_mock.Store{} + s2 := &store_mock.Store{} + s1.On("List").Return([]*store.Record{recA, recB}, nil) + s2.On("List").Return([]*store.Record{recB, recA}, nil) + s1.On("Write", mock.Anything).Return(nil) + s2.On("Write", mock.Anything).Return(nil) f := func(key, val interface{}) error { time.Sleep(1 * time.Millisecond) From 52ccd900c7a2baa60eaf29663299c4ac04d1d8bf Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 23 Nov 2019 22:50:13 +0000 Subject: [PATCH 241/344] reorder service struct fields --- runtime/runtime.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/runtime.go b/runtime/runtime.go index e323614d..8f7a4406 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -80,14 +80,14 @@ type Event struct { type Service struct { // Name of the service Name string + // Version of the service + Version string // url location of source Source string // Path to store source Path string // Exec command Exec []string - // Version of the service - Version string // Metadata stores metadata Metadata map[string]string } From 61fe552ac492ccbff62391ca0842d641475630be Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Mon, 25 Nov 2019 14:58:12 +0000 Subject: [PATCH 242/344] First commit: Outline of tunnel encryption code --- tunnel/crypto.go | 72 +++++++++++++++++++++++++++++++++++++++++++ tunnel/crypto_test.go | 41 ++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 tunnel/crypto.go create mode 100644 tunnel/crypto_test.go diff --git a/tunnel/crypto.go b/tunnel/crypto.go new file mode 100644 index 00000000..89a0bdbf --- /dev/null +++ b/tunnel/crypto.go @@ -0,0 +1,72 @@ +package tunnel + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha256" + "io" +) + +// Encrypt encrypts data and returns encrypted payload +func Encrypt(data []byte, key string) ([]byte, error) { + // generate a new AES cipher using our 32 byte key + c, err := aes.NewCipher(hash(key)) + if err != nil { + return nil, err + } + + // gcm or Galois/Counter Mode, is a mode of operation + // for symmetric key cryptographic block ciphers + // - https://en.wikipedia.org/wiki/Galois/Counter_Mode + gcm, err := cipher.NewGCM(c) + if err != nil { + return nil, err + } + + // create a new byte array the size of the nonce + // NOTE: we might use smaller nonce size in the future + nonce := make([]byte, gcm.NonceSize()) + if _, err = io.ReadFull(rand.Reader, nonce); err != nil { + return nil, err + } + + // NOTE: we prepend the nonce to the payload + // we need to do this as we need the same nonce + // to decrypt the payload when receiving it + return gcm.Seal(nonce, nonce, data, nil), nil +} + +// Decrypt decrypts the payload and returns decrypted data +func Decrypt(data []byte, key string) ([]byte, error) { + // generate AES cipher for decrypting the message + c, err := aes.NewCipher(hash(key)) + if err != nil { + return nil, err + } + + // we use GCM to encrypt the payload + gcm, err := cipher.NewGCM(c) + if err != nil { + return nil, err + } + + nonceSize := gcm.NonceSize() + // NOTE: we need to parse out nonce from the payload + // we prepend the nonce to every encrypted payload + nonce, ciphertext := data[:nonceSize], data[nonceSize:] + plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) + if err != nil { + return nil, err + } + + return plaintext, nil +} + +// hash hahes the data into 32 bytes key and returns it +// hash uses sha256 to hash the passed in string. +func hash(key string) []byte { + hasher := sha256.New() + hasher.Write([]byte(key)) + return hasher.Sum(nil) +} diff --git a/tunnel/crypto_test.go b/tunnel/crypto_test.go new file mode 100644 index 00000000..6f8498b9 --- /dev/null +++ b/tunnel/crypto_test.go @@ -0,0 +1,41 @@ +package tunnel + +import ( + "bytes" + "testing" +) + +func TestEncrypt(t *testing.T) { + key := "tokenpassphrase" + data := []byte("supersecret") + + cipherText, err := Encrypt(data, key) + if err != nil { + t.Errorf("failed to encrypt data: %v", err) + } + + // verify the cipherText is not the same as data + if bytes.Equal(data, cipherText) { + t.Error("encrypted data are the same as plaintext") + } +} + +func TestDecrypt(t *testing.T) { + key := "tokenpassphrase" + data := []byte("supersecret") + + cipherText, err := Encrypt(data, key) + if err != nil { + t.Errorf("failed to encrypt data: %v", err) + } + + plainText, err := Decrypt(cipherText, key) + if err != nil { + t.Errorf("failed to decrypt data: %v", err) + } + + // verify the plainText is the same as data + if !bytes.Equal(data, plainText) { + t.Error("decrypted data not the same as plaintext") + } +} From f82c267d8141013f2af6910bc960278540d883bd Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Mon, 25 Nov 2019 15:34:41 +0000 Subject: [PATCH 243/344] Encrypt session communication --- tunnel/crypto.go | 6 +++--- tunnel/session.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/tunnel/crypto.go b/tunnel/crypto.go index 89a0bdbf..f34f9c15 100644 --- a/tunnel/crypto.go +++ b/tunnel/crypto.go @@ -8,7 +8,7 @@ import ( "io" ) -// Encrypt encrypts data and returns encrypted payload +// Encrypt encrypts data and returns the encrypted data func Encrypt(data []byte, key string) ([]byte, error) { // generate a new AES cipher using our 32 byte key c, err := aes.NewCipher(hash(key)) @@ -37,7 +37,7 @@ func Encrypt(data []byte, key string) ([]byte, error) { return gcm.Seal(nonce, nonce, data, nil), nil } -// Decrypt decrypts the payload and returns decrypted data +// Decrypt decrypts the payload and returns the decrypted data func Decrypt(data []byte, key string) ([]byte, error) { // generate AES cipher for decrypting the message c, err := aes.NewCipher(hash(key)) @@ -64,7 +64,7 @@ func Decrypt(data []byte, key string) ([]byte, error) { } // hash hahes the data into 32 bytes key and returns it -// hash uses sha256 to hash the passed in string. +// hash uses sha256 underneath to hash the supplied key func hash(key string) []byte { hasher := sha256.New() hasher.Write([]byte(key)) diff --git a/tunnel/session.go b/tunnel/session.go index 59cbdb5e..09042fd1 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -301,13 +301,27 @@ func (s *session) Send(m *transport.Message) error { // no op } + // get the token + token, ok := m.Header["Micro-Tunnel-Token"] + if !ok { + // TODO: should we continue or return error + log.Debugf("no token found, insecure channel") + } + + // encrypt the transport message payload + body, err := Encrypt(m.Body, token+s.channel+s.session) + if err != nil { + return err + } + // make copy data := &transport.Message{ Header: make(map[string]string), - Body: m.Body, + Body: body, } for k, v := range m.Header { + // TODO: should we also encrypt headers? data.Header[k] = v } @@ -352,7 +366,22 @@ func (s *session) Recv(m *transport.Message) error { default: } + // TODO: if we encrypt headers we will have to decrypt them here + token, ok := msg.data.Header["Micro-Tunnel-Token"] + if !ok { + // TODO: should we continue or return error + log.Debugf("no token found, insecure channel") + } + log.Tracef("Received %+v from recv backlog", msg) + + // decrypt the received payload using the token + body, err := Decrypt(msg.data.Body, token+s.channel+s.session) + if err != nil { + return err + } + msg.data.Body = body + // set message *m = *msg.data // return nil From 252667398e2cebf52281b691157f701fe9dbea12 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 25 Nov 2019 16:31:14 +0000 Subject: [PATCH 244/344] Update the runtime for k8s name formatting and move Get to Read endpoint (#978) * Update the runtime for k8s name formatting and move Get to Read endpoint * strip regex validation --- go.sum | 3 + runtime/default.go | 6 +- runtime/kubernetes/client/kubernetes.go | 33 +-- .../kubernetes/client/{utils.go => util.go} | 15 + .../client/{utils_test.go => util_test.go} | 25 +- runtime/kubernetes/kubernetes.go | 65 +++-- runtime/kubernetes/service.go | 27 +- runtime/options.go | 10 +- runtime/proto/runtime.micro.go | 108 -------- runtime/proto/runtime.pb.go | 257 ------------------ runtime/proto/runtime.proto | 31 --- runtime/runtime.go | 4 +- runtime/service/handler/handler.go | 12 +- runtime/service/proto/runtime.pb.go | 221 +++++++-------- .../{runtime.micro.go => runtime.pb.micro.go} | 18 +- runtime/service/proto/runtime.proto | 10 +- runtime/service/service.go | 12 +- 17 files changed, 268 insertions(+), 589 deletions(-) rename runtime/kubernetes/client/{utils.go => util.go} (89%) rename runtime/kubernetes/client/{utils_test.go => util_test.go} (50%) delete mode 100644 runtime/proto/runtime.micro.go delete mode 100644 runtime/proto/runtime.pb.go delete mode 100644 runtime/proto/runtime.proto rename runtime/service/proto/{runtime.micro.go => runtime.pb.micro.go} (87%) diff --git a/go.sum b/go.sum index 1be95770..113e6bd2 100644 --- a/go.sum +++ b/go.sum @@ -84,6 +84,7 @@ github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMEl github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -321,6 +322,7 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= @@ -364,6 +366,7 @@ 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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= diff --git a/runtime/default.go b/runtime/default.go index 18d8d7a9..c9c198e1 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -176,9 +176,9 @@ func (r *runtime) Create(s *Service, opts ...CreateOption) error { return nil } -// Get returns all instances of requested service +// Read returns all instances of requested service // If no service name is provided we return all the track services. -func (r *runtime) Get(name string, opts ...GetOption) ([]*Service, error) { +func (r *runtime) Read(name string, opts ...ReadOption) ([]*Service, error) { r.Lock() defer r.Unlock() @@ -186,7 +186,7 @@ func (r *runtime) Get(name string, opts ...GetOption) ([]*Service, error) { return nil, errors.New("missing service name") } - gopts := GetOptions{} + gopts := ReadOptions{} for _, o := range opts { o(&gopts) } diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index 0de53b59..e75862f8 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -2,7 +2,6 @@ package client import ( - "regexp" "strconv" "strings" "time" @@ -18,8 +17,6 @@ const ( var ( // DefaultImage is default micro image DefaultImage = "micro/go-micro" - // ServiceRegexp is used to validate service name - ServiceRegexp = regexp.MustCompile("^" + dns1123LabelFmt + "$") ) // Kubernetes client @@ -36,9 +33,9 @@ type Kubernetes interface { List(*Resource) error } -// DefaultService returns default micro kubernetes service definition -func DefaultService(name, version string) *Service { - log.Debugf("kubernetes default service: name: %s, version: %s", name, version) +// NewService returns default micro kubernetes service definition +func NewService(name, version string) *Service { + log.Tracef("kubernetes default service: name: %s, version: %s", name, version) Labels := map[string]string{ "name": name, @@ -73,9 +70,9 @@ func DefaultService(name, version string) *Service { } } -// DefaultService returns default micro kubernetes deployment definition -func DefaultDeployment(name, version, source string) *Deployment { - log.Debugf("kubernetes default deployment: name: %s, version: %s, source: %s", name, version, source) +// NewService returns default micro kubernetes deployment definition +func NewDeployment(name, version string) *Deployment { + log.Tracef("kubernetes default deployment: name: %s, version: %s", name, version) Labels := map[string]string{ "name": name, @@ -90,15 +87,11 @@ func DefaultDeployment(name, version, source string) *Deployment { } Metadata := &Metadata{ - Name: depName, - Namespace: "default", - Version: version, - Labels: Labels, - Annotations: map[string]string{ - "source": source, - "owner": "micro", - "group": "micro", - }, + Name: depName, + Namespace: "default", + Version: version, + Labels: Labels, + Annotations: map[string]string{}, } // TODO: we need to figure out this version stuff @@ -108,7 +101,7 @@ func DefaultDeployment(name, version, source string) *Deployment { buildUnixTimeUTC := time.Unix(buildTime, 0) Metadata.Annotations["build"] = buildUnixTimeUTC.Format(time.RFC3339) } else { - log.Debugf("could not parse build: %v", err) + log.Tracef("could not parse build: %v", err) } // enable go modules by default @@ -129,7 +122,7 @@ func DefaultDeployment(name, version, source string) *Deployment { Name: name, Image: DefaultImage, Env: []EnvVar{env}, - Command: []string{"go", "run", source}, + Command: []string{"go", "run", "main.go"}, Ports: []ContainerPort{{ Name: name + "-port", ContainerPort: 8080, diff --git a/runtime/kubernetes/client/utils.go b/runtime/kubernetes/client/util.go similarity index 89% rename from runtime/kubernetes/client/utils.go rename to runtime/kubernetes/client/util.go index 6174c522..83e17b11 100644 --- a/runtime/kubernetes/client/utils.go +++ b/runtime/kubernetes/client/util.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "io/ioutil" + "strings" "text/template" ) @@ -85,3 +86,17 @@ func CertsFromPEM(pemCerts []byte) ([]*x509.Certificate, error) { } return certs, nil } + +// Format is used to format a string value into a k8s valid name +func Format(v string) string { + // to lower case + v = strings.ToLower(v) + // dots to dashes + v = strings.ReplaceAll(v, ".", "-") + // limit to 253 chars + if len(v) > 253 { + v = v[:253] + } + // return new name + return v +} diff --git a/runtime/kubernetes/client/utils_test.go b/runtime/kubernetes/client/util_test.go similarity index 50% rename from runtime/kubernetes/client/utils_test.go rename to runtime/kubernetes/client/util_test.go index a364debc..39fb3e0c 100644 --- a/runtime/kubernetes/client/utils_test.go +++ b/runtime/kubernetes/client/util_test.go @@ -8,19 +8,38 @@ import ( func TestTemplates(t *testing.T) { name := "foo" version := "123" - source := "github.com/foo/bar" // Render default service - s := DefaultService(name, version) + s := NewService(name, version) bs := new(bytes.Buffer) if err := renderTemplate(templates["service"], bs, s); err != nil { t.Errorf("Failed to render kubernetes service: %v", err) } // Render default deployment - d := DefaultDeployment(name, version, source) + d := NewDeployment(name, version) bd := new(bytes.Buffer) if err := renderTemplate(templates["deployment"], bd, d); err != nil { t.Errorf("Failed to render kubernetes deployment: %v", err) } } + +func TestFormatName(t *testing.T) { + testCases := []struct { + name string + expect string + }{ + {"foobar", "foobar"}, + {"foo-bar", "foo-bar"}, + {"foo.bar", "foo-bar"}, + {"Foo.Bar", "foo-bar"}, + {"go.micro.foo.bar", "go-micro-foo-bar"}, + } + + for _, test := range testCases { + v := Format(test.name) + if v != test.expect { + t.Fatalf("Expected name %s for %s got: %s", test.expect, test.name, v) + } + } +} diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 26956856..91b224bc 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "strconv" - "strings" "sync" "time" @@ -86,19 +85,19 @@ func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) er o(&options) } - svcName := s.Name + // quickly prevalidate the name and version + name := s.Name if len(s.Version) > 0 { - svcName = strings.Join([]string{s.Name, s.Version}, "-") + name = name + "-" + s.Version } - if !client.ServiceRegexp.MatchString(svcName) { - return fmt.Errorf("invalid service name: %s", svcName) - } + // format as we'll format in the deployment + name = client.Format(name) // create new kubernetes micro service service := newService(s, options) - log.Debugf("Runtime queueing service %s for start action", service.Name) + log.Debugf("Runtime queueing service %s version %s for start action", service.Name, service.Version) // push into start queue k.queue <- &task{ @@ -109,9 +108,9 @@ func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) er return nil } -// getMicroService queries kubernetes for micro service +// getService queries kubernetes for micro service // NOTE: this function is not thread-safe -func (k *kubernetes) getMicroService(labels map[string]string) ([]*runtime.Service, error) { +func (k *kubernetes) getService(labels map[string]string) ([]*runtime.Service, error) { // get the service status serviceList := new(client.ServiceList) r := &client.Resource{ @@ -137,31 +136,55 @@ func (k *kubernetes) getMicroService(labels map[string]string) ([]*runtime.Servi // collect info from kubernetes service for _, kservice := range serviceList.Items { + // name of the service name := kservice.Metadata.Labels["name"] + // version of the service version := kservice.Metadata.Labels["version"] - svcMap[name] = &runtime.Service{ + + // save as service + svcMap[name+version] = &runtime.Service{ Name: name, Version: version, Metadata: make(map[string]string), } + // copy annotations metadata into service metadata for k, v := range kservice.Metadata.Annotations { - svcMap[name].Metadata[k] = v + svcMap[name+version].Metadata[k] = v } } // collect additional info from kubernetes deployment for _, kdep := range depList.Items { + // name of the service name := kdep.Metadata.Labels["name"] - if svc, ok := svcMap[name]; ok { - // set the service source + // versio of the service + version := kdep.Metadata.Labels["version"] + + // access existing service map based on name + version + if svc, ok := svcMap[name+version]; ok { + // we're expecting our own service name in metadata + if _, ok := kdep.Metadata.Annotations["name"]; !ok { + continue + } + + // set the service name, version and source + // based on existing annotations we stored + svc.Name = kdep.Metadata.Annotations["name"] + svc.Version = kdep.Metadata.Annotations["version"] svc.Source = kdep.Metadata.Annotations["source"] + + // delete from metadata + delete(kdep.Metadata.Annotations, "name") + delete(kdep.Metadata.Annotations, "version") + delete(kdep.Metadata.Annotations, "source") + // copy all annotations metadata into service metadata for k, v := range kdep.Metadata.Annotations { svc.Metadata[k] = v } - // parse out deployment status + // parse out deployment status and inject into service metadata if len(kdep.Status.Conditions) > 0 { status := kdep.Status.Conditions[0].Type // pick the last known condition type and mark the service status with it @@ -186,6 +209,7 @@ func (k *kubernetes) getMicroService(labels map[string]string) ([]*runtime.Servi // collect all the services and return services := make([]*runtime.Service, 0, len(serviceList.Items)) + for _, service := range svcMap { services = append(services, service) } @@ -193,8 +217,8 @@ func (k *kubernetes) getMicroService(labels map[string]string) ([]*runtime.Servi return services, nil } -// Get returns all instances of given service -func (k *kubernetes) Get(name string, opts ...runtime.GetOption) ([]*runtime.Service, error) { +// Read returns all instances of given service +func (k *kubernetes) Read(name string, opts ...runtime.ReadOption) ([]*runtime.Service, error) { k.Lock() defer k.Unlock() @@ -203,13 +227,16 @@ func (k *kubernetes) Get(name string, opts ...runtime.GetOption) ([]*runtime.Ser return nil, errors.New("missing service name") } + // format the name + name = client.Format(name) + // set the default labels labels := map[string]string{ "micro": "service", "name": name, } - var options runtime.GetOptions + var options runtime.ReadOptions for _, o := range opts { o(&options) } @@ -221,7 +248,7 @@ func (k *kubernetes) Get(name string, opts ...runtime.GetOption) ([]*runtime.Ser log.Debugf("Runtime querying service %s", name) - return k.getMicroService(labels) + return k.getService(labels) } // List the managed services @@ -235,7 +262,7 @@ func (k *kubernetes) List() ([]*runtime.Service, error) { log.Debugf("Runtime listing all micro services") - return k.getMicroService(labels) + return k.getService(labels) } // Update the service in place diff --git a/runtime/kubernetes/service.go b/runtime/kubernetes/service.go index 7b7d2004..2a73071c 100644 --- a/runtime/kubernetes/service.go +++ b/runtime/kubernetes/service.go @@ -18,9 +18,23 @@ type service struct { } func newService(s *runtime.Service, c runtime.CreateOptions) *service { - kservice := client.DefaultService(s.Name, s.Version) - kdeploy := client.DefaultDeployment(s.Name, s.Version, s.Source) + // use pre-formatted name/version + name := client.Format(s.Name) + version := client.Format(s.Version) + kservice := client.NewService(name, version) + kdeploy := client.NewDeployment(name, version) + + // attach our values to the deployment; name, version, source + kdeploy.Metadata.Annotations["name"] = s.Name + kdeploy.Metadata.Annotations["version"] = s.Version + kdeploy.Metadata.Annotations["source"] = s.Source + + // associate owner:group to be later augmented + kdeploy.Metadata.Annotations["owner"] = "micro" + kdeploy.Metadata.Annotations["group"] = "micro" + + // define the environment values used by the container env := make([]client.EnvVar, 0, len(c.Env)) for _, evar := range c.Env { evarPair := strings.Split(evar, "=") @@ -35,10 +49,11 @@ func newService(s *runtime.Service, c runtime.CreateOptions) *service { // if Exec/Command has been supplied override the default command if len(s.Exec) > 0 { kdeploy.Spec.Template.PodSpec.Containers[0].Command = s.Exec - } else { - if len(c.Command) > 0 { - kdeploy.Spec.Template.PodSpec.Containers[0].Command = c.Command - } + } else if len(c.Command) > 0 { + kdeploy.Spec.Template.PodSpec.Containers[0].Command = c.Command + } else if len(s.Source) > 0 { + // default command for our k8s service should be source + kdeploy.Spec.Template.PodSpec.Containers[0].Command = []string{"go", "run", s.Source} } return &service{ diff --git a/runtime/options.go b/runtime/options.go index e031656d..cbc93952 100644 --- a/runtime/options.go +++ b/runtime/options.go @@ -55,17 +55,17 @@ func WithOutput(out io.Writer) CreateOption { } } -type GetOption func(o *GetOptions) +type ReadOption func(o *ReadOptions) -// GetOptions queries runtime services -type GetOptions struct { +// ReadOptions queries runtime services +type ReadOptions struct { // Version queries services with given version Version string } // WithVersion confifgures service version -func WithVersion(version string) GetOption { - return func(o *GetOptions) { +func WithVersion(version string) ReadOption { + return func(o *ReadOptions) { o.Version = version } } diff --git a/runtime/proto/runtime.micro.go b/runtime/proto/runtime.micro.go deleted file mode 100644 index 91ff4f8b..00000000 --- a/runtime/proto/runtime.micro.go +++ /dev/null @@ -1,108 +0,0 @@ -// Code generated by protoc-gen-micro. DO NOT EDIT. -// source: runtime.proto - -package go_micro_runtime - -import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - math "math" -) - -import ( - context "context" - client "github.com/micro/go-micro/client" - server "github.com/micro/go-micro/server" -) - -// 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.ProtoPackageIsVersion3 // please upgrade the proto package - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ client.Option -var _ server.Option - -// Client API for Runtime service - -type RuntimeService interface { - Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) - Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) -} - -type runtimeService struct { - c client.Client - name string -} - -func NewRuntimeService(name string, c client.Client) RuntimeService { - if c == nil { - c = client.NewClient() - } - if len(name) == 0 { - name = "go.micro.runtime" - } - return &runtimeService{ - c: c, - name: name, - } -} - -func (c *runtimeService) Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) { - req := c.c.NewRequest(c.name, "Runtime.Create", in) - out := new(CreateResponse) - err := c.c.Call(ctx, req, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *runtimeService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) { - req := c.c.NewRequest(c.name, "Runtime.Delete", in) - out := new(DeleteResponse) - err := c.c.Call(ctx, req, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// Server API for Runtime service - -type RuntimeHandler interface { - Create(context.Context, *CreateRequest, *CreateResponse) error - Delete(context.Context, *DeleteRequest, *DeleteResponse) error -} - -func RegisterRuntimeHandler(s server.Server, hdlr RuntimeHandler, opts ...server.HandlerOption) error { - type runtime interface { - Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error - Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error - } - type Runtime struct { - runtime - } - h := &runtimeHandler{hdlr} - return s.Handle(s.NewHandler(&Runtime{h}, opts...)) -} - -type runtimeHandler struct { - RuntimeHandler -} - -func (h *runtimeHandler) Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error { - return h.RuntimeHandler.Create(ctx, in, out) -} - -func (h *runtimeHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error { - return h.RuntimeHandler.Delete(ctx, in, out) -} diff --git a/runtime/proto/runtime.pb.go b/runtime/proto/runtime.pb.go deleted file mode 100644 index 8b6596d7..00000000 --- a/runtime/proto/runtime.pb.go +++ /dev/null @@ -1,257 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: runtime.proto - -package go_micro_runtime - -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 -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.ProtoPackageIsVersion3 // please upgrade the proto package - -type Service struct { - // name of the service - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // git url of the source - Source string `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"` - // local path of the source - Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` - // command to execute - Exec []string `protobuf:"bytes,4,rep,name=exec,proto3" json:"exec,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Service) Reset() { *m = Service{} } -func (m *Service) String() string { return proto.CompactTextString(m) } -func (*Service) ProtoMessage() {} -func (*Service) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{0} -} - -func (m *Service) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Service.Unmarshal(m, b) -} -func (m *Service) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Service.Marshal(b, m, deterministic) -} -func (m *Service) XXX_Merge(src proto.Message) { - xxx_messageInfo_Service.Merge(m, src) -} -func (m *Service) XXX_Size() int { - return xxx_messageInfo_Service.Size(m) -} -func (m *Service) XXX_DiscardUnknown() { - xxx_messageInfo_Service.DiscardUnknown(m) -} - -var xxx_messageInfo_Service proto.InternalMessageInfo - -func (m *Service) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func (m *Service) GetSource() string { - if m != nil { - return m.Source - } - return "" -} - -func (m *Service) GetPath() string { - if m != nil { - return m.Path - } - return "" -} - -func (m *Service) GetExec() []string { - if m != nil { - return m.Exec - } - return nil -} - -type CreateRequest struct { - Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CreateRequest) Reset() { *m = CreateRequest{} } -func (m *CreateRequest) String() string { return proto.CompactTextString(m) } -func (*CreateRequest) ProtoMessage() {} -func (*CreateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{1} -} - -func (m *CreateRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CreateRequest.Unmarshal(m, b) -} -func (m *CreateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CreateRequest.Marshal(b, m, deterministic) -} -func (m *CreateRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_CreateRequest.Merge(m, src) -} -func (m *CreateRequest) XXX_Size() int { - return xxx_messageInfo_CreateRequest.Size(m) -} -func (m *CreateRequest) XXX_DiscardUnknown() { - xxx_messageInfo_CreateRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_CreateRequest proto.InternalMessageInfo - -func (m *CreateRequest) GetService() *Service { - if m != nil { - return m.Service - } - return nil -} - -type CreateResponse struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CreateResponse) Reset() { *m = CreateResponse{} } -func (m *CreateResponse) String() string { return proto.CompactTextString(m) } -func (*CreateResponse) ProtoMessage() {} -func (*CreateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{2} -} - -func (m *CreateResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CreateResponse.Unmarshal(m, b) -} -func (m *CreateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CreateResponse.Marshal(b, m, deterministic) -} -func (m *CreateResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_CreateResponse.Merge(m, src) -} -func (m *CreateResponse) XXX_Size() int { - return xxx_messageInfo_CreateResponse.Size(m) -} -func (m *CreateResponse) XXX_DiscardUnknown() { - xxx_messageInfo_CreateResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_CreateResponse proto.InternalMessageInfo - -type DeleteRequest struct { - Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } -func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } -func (*DeleteRequest) ProtoMessage() {} -func (*DeleteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{3} -} - -func (m *DeleteRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DeleteRequest.Unmarshal(m, b) -} -func (m *DeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DeleteRequest.Marshal(b, m, deterministic) -} -func (m *DeleteRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_DeleteRequest.Merge(m, src) -} -func (m *DeleteRequest) XXX_Size() int { - return xxx_messageInfo_DeleteRequest.Size(m) -} -func (m *DeleteRequest) XXX_DiscardUnknown() { - xxx_messageInfo_DeleteRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_DeleteRequest proto.InternalMessageInfo - -func (m *DeleteRequest) GetService() *Service { - if m != nil { - return m.Service - } - return nil -} - -type DeleteResponse struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } -func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } -func (*DeleteResponse) ProtoMessage() {} -func (*DeleteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{4} -} - -func (m *DeleteResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DeleteResponse.Unmarshal(m, b) -} -func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DeleteResponse.Marshal(b, m, deterministic) -} -func (m *DeleteResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_DeleteResponse.Merge(m, src) -} -func (m *DeleteResponse) XXX_Size() int { - return xxx_messageInfo_DeleteResponse.Size(m) -} -func (m *DeleteResponse) XXX_DiscardUnknown() { - xxx_messageInfo_DeleteResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo - -func init() { - proto.RegisterType((*Service)(nil), "go.micro.runtime.Service") - proto.RegisterType((*CreateRequest)(nil), "go.micro.runtime.CreateRequest") - proto.RegisterType((*CreateResponse)(nil), "go.micro.runtime.CreateResponse") - proto.RegisterType((*DeleteRequest)(nil), "go.micro.runtime.DeleteRequest") - proto.RegisterType((*DeleteResponse)(nil), "go.micro.runtime.DeleteResponse") -} - -func init() { proto.RegisterFile("runtime.proto", fileDescriptor_86e2dd377c869464) } - -var fileDescriptor_86e2dd377c869464 = []byte{ - // 229 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x91, 0xbf, 0x4e, 0x86, 0x30, - 0x14, 0xc5, 0x41, 0x08, 0xc4, 0x6b, 0x30, 0xa4, 0x83, 0xa9, 0x2e, 0x92, 0x4e, 0x4e, 0x1d, 0xe0, - 0x11, 0x64, 0x75, 0xa9, 0xb3, 0x03, 0x36, 0x37, 0x4a, 0x22, 0x14, 0xdb, 0x62, 0x7c, 0x23, 0x5f, - 0xd3, 0xf4, 0x0f, 0x03, 0xca, 0x37, 0x7d, 0xdb, 0xe9, 0xc9, 0xc9, 0xef, 0x9c, 0x9b, 0x42, 0xa5, - 0xd7, 0xd9, 0x8e, 0x13, 0xf2, 0x45, 0x2b, 0xab, 0x48, 0xfd, 0xa6, 0xf8, 0x34, 0x4a, 0xad, 0x78, - 0xf4, 0xd9, 0x0b, 0x94, 0xcf, 0xa8, 0xbf, 0x46, 0x89, 0x84, 0x40, 0x3e, 0x0f, 0x13, 0xd2, 0xb4, - 0x49, 0x1f, 0x2e, 0x85, 0xd7, 0xe4, 0x06, 0x0a, 0xa3, 0x56, 0x2d, 0x91, 0x5e, 0x78, 0x37, 0xbe, - 0x5c, 0x76, 0x19, 0xec, 0x3b, 0xcd, 0x42, 0xd6, 0x69, 0xe7, 0xe1, 0x37, 0x4a, 0x9a, 0x37, 0x99, - 0xf3, 0x9c, 0x66, 0x3d, 0x54, 0x8f, 0x1a, 0x07, 0x8b, 0x02, 0x3f, 0x57, 0x34, 0x96, 0x74, 0x50, - 0x9a, 0xd0, 0xe7, 0x7b, 0xae, 0xda, 0x5b, 0xfe, 0x77, 0x13, 0x8f, 0x83, 0xc4, 0x96, 0x64, 0x35, - 0x5c, 0x6f, 0x14, 0xb3, 0xa8, 0xd9, 0xa0, 0xe3, 0xf6, 0xf8, 0x81, 0xe7, 0x73, 0x37, 0x4a, 0xe0, - 0xb6, 0x3f, 0x29, 0x94, 0x22, 0xc4, 0xc9, 0x13, 0x14, 0xa1, 0x95, 0xdc, 0xff, 0x67, 0xed, 0xae, - 0xba, 0x6b, 0x4e, 0x07, 0xe2, 0xe0, 0xc4, 0xe1, 0x42, 0xd9, 0x11, 0x6e, 0x77, 0xcc, 0x11, 0x6e, - 0xbf, 0x93, 0x25, 0xaf, 0x85, 0xff, 0xd1, 0xee, 0x37, 0x00, 0x00, 0xff, 0xff, 0x99, 0xc5, 0x97, - 0x12, 0xe2, 0x01, 0x00, 0x00, -} diff --git a/runtime/proto/runtime.proto b/runtime/proto/runtime.proto deleted file mode 100644 index bce613e3..00000000 --- a/runtime/proto/runtime.proto +++ /dev/null @@ -1,31 +0,0 @@ -syntax = "proto3"; - -package go.micro.runtime; - -service Runtime { - rpc Create(CreateRequest) returns (CreateResponse) {}; - rpc Delete(DeleteRequest) returns (DeleteResponse) {}; -} - -message Service { - // name of the service - string name = 1; - // git url of the source - string source = 2; - // local path of the source - string path = 3; - // command to execute - repeated string exec = 4; -} - -message CreateRequest { - Service service = 1; -} - -message CreateResponse {} - -message DeleteRequest { - Service service = 1; -} - -message DeleteResponse {} diff --git a/runtime/runtime.go b/runtime/runtime.go index 8f7a4406..b6e17c31 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -16,8 +16,8 @@ type Runtime interface { Init(...Option) error // Create registers a service Create(*Service, ...CreateOption) error - // Get returns service or fails with error - Get(string, ...GetOption) ([]*Service, error) + // Read returns the service + Read(string, ...ReadOption) ([]*Service, error) // Update the service in place Update(*Service) error // Remove a service diff --git a/runtime/service/handler/handler.go b/runtime/service/handler/handler.go index f7694d79..48c714ef 100644 --- a/runtime/service/handler/handler.go +++ b/runtime/service/handler/handler.go @@ -54,8 +54,8 @@ func toCreateOptions(opts *pb.CreateOptions) []runtime.CreateOption { return options } -func toGetOptions(opts *pb.GetOptions) []runtime.GetOption { - options := []runtime.GetOption{} +func toReadOptions(opts *pb.ReadOptions) []runtime.ReadOption { + options := []runtime.ReadOption{} // version options if len(opts.Version) > 0 { options = append(options, runtime.WithVersion(opts.Version)) @@ -83,17 +83,17 @@ func (r *Runtime) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.Cre return nil } -func (r *Runtime) Get(ctx context.Context, req *pb.GetRequest, rsp *pb.GetResponse) error { +func (r *Runtime) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error { if len(req.Name) == 0 { return errors.BadRequest("go.micro.runtime", "blank service") } - var options []runtime.GetOption + var options []runtime.ReadOption if req.Options != nil { - options = toGetOptions(req.Options) + options = toReadOptions(req.Options) } - services, err := r.Runtime.Get(req.Name, options...) + services, err := r.Runtime.Read(req.Name, options...) if err != nil { return errors.InternalServerError("go.micro.runtime", err.Error()) } diff --git a/runtime/service/proto/runtime.pb.go b/runtime/service/proto/runtime.pb.go index 5e7d8938..f6610a97 100644 --- a/runtime/service/proto/runtime.pb.go +++ b/runtime/service/proto/runtime.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: runtime.proto +// source: micro/go-micro/runtime/service/proto/runtime.proto package go_micro_runtime @@ -42,7 +42,7 @@ func (m *Service) Reset() { *m = Service{} } func (m *Service) String() string { return proto.CompactTextString(m) } func (*Service) ProtoMessage() {} func (*Service) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{0} + return fileDescriptor_4bc91a8efec81434, []int{0} } func (m *Service) XXX_Unmarshal(b []byte) error { @@ -121,7 +121,7 @@ func (m *CreateOptions) Reset() { *m = CreateOptions{} } func (m *CreateOptions) String() string { return proto.CompactTextString(m) } func (*CreateOptions) ProtoMessage() {} func (*CreateOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{1} + return fileDescriptor_4bc91a8efec81434, []int{1} } func (m *CreateOptions) XXX_Unmarshal(b []byte) error { @@ -175,7 +175,7 @@ func (m *CreateRequest) Reset() { *m = CreateRequest{} } func (m *CreateRequest) String() string { return proto.CompactTextString(m) } func (*CreateRequest) ProtoMessage() {} func (*CreateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{2} + return fileDescriptor_4bc91a8efec81434, []int{2} } func (m *CreateRequest) XXX_Unmarshal(b []byte) error { @@ -220,7 +220,7 @@ func (m *CreateResponse) Reset() { *m = CreateResponse{} } func (m *CreateResponse) String() string { return proto.CompactTextString(m) } func (*CreateResponse) ProtoMessage() {} func (*CreateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{3} + return fileDescriptor_4bc91a8efec81434, []int{3} } func (m *CreateResponse) XXX_Unmarshal(b []byte) error { @@ -241,7 +241,7 @@ func (m *CreateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_CreateResponse proto.InternalMessageInfo -type GetOptions struct { +type ReadOptions struct { // version of the service Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -249,118 +249,118 @@ type GetOptions struct { XXX_sizecache int32 `json:"-"` } -func (m *GetOptions) Reset() { *m = GetOptions{} } -func (m *GetOptions) String() string { return proto.CompactTextString(m) } -func (*GetOptions) ProtoMessage() {} -func (*GetOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{4} +func (m *ReadOptions) Reset() { *m = ReadOptions{} } +func (m *ReadOptions) String() string { return proto.CompactTextString(m) } +func (*ReadOptions) ProtoMessage() {} +func (*ReadOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{4} } -func (m *GetOptions) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetOptions.Unmarshal(m, b) +func (m *ReadOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ReadOptions.Unmarshal(m, b) } -func (m *GetOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetOptions.Marshal(b, m, deterministic) +func (m *ReadOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ReadOptions.Marshal(b, m, deterministic) } -func (m *GetOptions) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetOptions.Merge(m, src) +func (m *ReadOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_ReadOptions.Merge(m, src) } -func (m *GetOptions) XXX_Size() int { - return xxx_messageInfo_GetOptions.Size(m) +func (m *ReadOptions) XXX_Size() int { + return xxx_messageInfo_ReadOptions.Size(m) } -func (m *GetOptions) XXX_DiscardUnknown() { - xxx_messageInfo_GetOptions.DiscardUnknown(m) +func (m *ReadOptions) XXX_DiscardUnknown() { + xxx_messageInfo_ReadOptions.DiscardUnknown(m) } -var xxx_messageInfo_GetOptions proto.InternalMessageInfo +var xxx_messageInfo_ReadOptions proto.InternalMessageInfo -func (m *GetOptions) GetVersion() string { +func (m *ReadOptions) GetVersion() string { if m != nil { return m.Version } return "" } -type GetRequest struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Options *GetOptions `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type ReadRequest struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Options *ReadOptions `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *GetRequest) Reset() { *m = GetRequest{} } -func (m *GetRequest) String() string { return proto.CompactTextString(m) } -func (*GetRequest) ProtoMessage() {} -func (*GetRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{5} +func (m *ReadRequest) Reset() { *m = ReadRequest{} } +func (m *ReadRequest) String() string { return proto.CompactTextString(m) } +func (*ReadRequest) ProtoMessage() {} +func (*ReadRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{5} } -func (m *GetRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetRequest.Unmarshal(m, b) +func (m *ReadRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ReadRequest.Unmarshal(m, b) } -func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetRequest.Marshal(b, m, deterministic) +func (m *ReadRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ReadRequest.Marshal(b, m, deterministic) } -func (m *GetRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetRequest.Merge(m, src) +func (m *ReadRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ReadRequest.Merge(m, src) } -func (m *GetRequest) XXX_Size() int { - return xxx_messageInfo_GetRequest.Size(m) +func (m *ReadRequest) XXX_Size() int { + return xxx_messageInfo_ReadRequest.Size(m) } -func (m *GetRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetRequest.DiscardUnknown(m) +func (m *ReadRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ReadRequest.DiscardUnknown(m) } -var xxx_messageInfo_GetRequest proto.InternalMessageInfo +var xxx_messageInfo_ReadRequest proto.InternalMessageInfo -func (m *GetRequest) GetName() string { +func (m *ReadRequest) GetName() string { if m != nil { return m.Name } return "" } -func (m *GetRequest) GetOptions() *GetOptions { +func (m *ReadRequest) GetOptions() *ReadOptions { if m != nil { return m.Options } return nil } -type GetResponse struct { +type ReadResponse struct { Services []*Service `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } -func (m *GetResponse) Reset() { *m = GetResponse{} } -func (m *GetResponse) String() string { return proto.CompactTextString(m) } -func (*GetResponse) ProtoMessage() {} -func (*GetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{6} +func (m *ReadResponse) Reset() { *m = ReadResponse{} } +func (m *ReadResponse) String() string { return proto.CompactTextString(m) } +func (*ReadResponse) ProtoMessage() {} +func (*ReadResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_4bc91a8efec81434, []int{6} } -func (m *GetResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetResponse.Unmarshal(m, b) +func (m *ReadResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ReadResponse.Unmarshal(m, b) } -func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetResponse.Marshal(b, m, deterministic) +func (m *ReadResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ReadResponse.Marshal(b, m, deterministic) } -func (m *GetResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetResponse.Merge(m, src) +func (m *ReadResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ReadResponse.Merge(m, src) } -func (m *GetResponse) XXX_Size() int { - return xxx_messageInfo_GetResponse.Size(m) +func (m *ReadResponse) XXX_Size() int { + return xxx_messageInfo_ReadResponse.Size(m) } -func (m *GetResponse) XXX_DiscardUnknown() { - xxx_messageInfo_GetResponse.DiscardUnknown(m) +func (m *ReadResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ReadResponse.DiscardUnknown(m) } -var xxx_messageInfo_GetResponse proto.InternalMessageInfo +var xxx_messageInfo_ReadResponse proto.InternalMessageInfo -func (m *GetResponse) GetServices() []*Service { +func (m *ReadResponse) GetServices() []*Service { if m != nil { return m.Services } @@ -378,7 +378,7 @@ func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } func (*DeleteRequest) ProtoMessage() {} func (*DeleteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{7} + return fileDescriptor_4bc91a8efec81434, []int{7} } func (m *DeleteRequest) XXX_Unmarshal(b []byte) error { @@ -416,7 +416,7 @@ func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } func (*DeleteResponse) ProtoMessage() {} func (*DeleteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{8} + return fileDescriptor_4bc91a8efec81434, []int{8} } func (m *DeleteResponse) XXX_Unmarshal(b []byte) error { @@ -448,7 +448,7 @@ func (m *UpdateRequest) Reset() { *m = UpdateRequest{} } func (m *UpdateRequest) String() string { return proto.CompactTextString(m) } func (*UpdateRequest) ProtoMessage() {} func (*UpdateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{9} + return fileDescriptor_4bc91a8efec81434, []int{9} } func (m *UpdateRequest) XXX_Unmarshal(b []byte) error { @@ -486,7 +486,7 @@ func (m *UpdateResponse) Reset() { *m = UpdateResponse{} } func (m *UpdateResponse) String() string { return proto.CompactTextString(m) } func (*UpdateResponse) ProtoMessage() {} func (*UpdateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{10} + return fileDescriptor_4bc91a8efec81434, []int{10} } func (m *UpdateResponse) XXX_Unmarshal(b []byte) error { @@ -517,7 +517,7 @@ func (m *ListRequest) Reset() { *m = ListRequest{} } func (m *ListRequest) String() string { return proto.CompactTextString(m) } func (*ListRequest) ProtoMessage() {} func (*ListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{11} + return fileDescriptor_4bc91a8efec81434, []int{11} } func (m *ListRequest) XXX_Unmarshal(b []byte) error { @@ -549,7 +549,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} } func (m *ListResponse) String() string { return proto.CompactTextString(m) } func (*ListResponse) ProtoMessage() {} func (*ListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_86e2dd377c869464, []int{12} + return fileDescriptor_4bc91a8efec81434, []int{12} } func (m *ListResponse) XXX_Unmarshal(b []byte) error { @@ -583,9 +583,9 @@ func init() { proto.RegisterType((*CreateOptions)(nil), "go.micro.runtime.CreateOptions") proto.RegisterType((*CreateRequest)(nil), "go.micro.runtime.CreateRequest") proto.RegisterType((*CreateResponse)(nil), "go.micro.runtime.CreateResponse") - proto.RegisterType((*GetOptions)(nil), "go.micro.runtime.GetOptions") - proto.RegisterType((*GetRequest)(nil), "go.micro.runtime.GetRequest") - proto.RegisterType((*GetResponse)(nil), "go.micro.runtime.GetResponse") + proto.RegisterType((*ReadOptions)(nil), "go.micro.runtime.ReadOptions") + proto.RegisterType((*ReadRequest)(nil), "go.micro.runtime.ReadRequest") + proto.RegisterType((*ReadResponse)(nil), "go.micro.runtime.ReadResponse") proto.RegisterType((*DeleteRequest)(nil), "go.micro.runtime.DeleteRequest") proto.RegisterType((*DeleteResponse)(nil), "go.micro.runtime.DeleteResponse") proto.RegisterType((*UpdateRequest)(nil), "go.micro.runtime.UpdateRequest") @@ -594,39 +594,42 @@ func init() { proto.RegisterType((*ListResponse)(nil), "go.micro.runtime.ListResponse") } -func init() { proto.RegisterFile("runtime.proto", fileDescriptor_86e2dd377c869464) } - -var fileDescriptor_86e2dd377c869464 = []byte{ - // 485 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcb, 0x6f, 0x94, 0x40, - 0x18, 0x2f, 0xcb, 0x16, 0xea, 0x87, 0x98, 0xcd, 0xc4, 0x98, 0x71, 0xe3, 0x63, 0xc3, 0x41, 0x7b, - 0xe2, 0xb0, 0x8d, 0xc6, 0xc7, 0xb1, 0x34, 0x7b, 0x71, 0x63, 0x42, 0x63, 0xe2, 0x75, 0x64, 0xbf, - 0x28, 0xb1, 0x30, 0xc8, 0x0c, 0x1b, 0x7b, 0xf2, 0xe4, 0x1f, 0xed, 0xcd, 0xcc, 0x6b, 0xdb, 0xa5, - 0xd0, 0xcb, 0xde, 0xbe, 0x17, 0x3f, 0x7e, 0x0f, 0x02, 0xc4, 0x6d, 0x57, 0xcb, 0xb2, 0xc2, 0xb4, - 0x69, 0xb9, 0xe4, 0x64, 0xf6, 0x9d, 0xa7, 0x55, 0x59, 0xb4, 0x3c, 0xb5, 0xf3, 0xe4, 0x9f, 0x07, - 0xe1, 0x25, 0xb6, 0xdb, 0xb2, 0x40, 0x42, 0x60, 0x5a, 0xb3, 0x0a, 0xa9, 0xb7, 0xf0, 0x4e, 0x1f, - 0xe4, 0xba, 0x26, 0x14, 0xc2, 0x2d, 0xb6, 0xa2, 0xe4, 0x35, 0x9d, 0xe8, 0xb1, 0x6b, 0xc9, 0x13, - 0x08, 0x04, 0xef, 0xda, 0x02, 0xa9, 0xaf, 0x17, 0xb6, 0x53, 0x28, 0x0d, 0x93, 0x3f, 0xe8, 0xd4, - 0xa0, 0xa8, 0x5a, 0xcd, 0xf0, 0x37, 0x16, 0xf4, 0x78, 0xe1, 0xab, 0x99, 0xaa, 0xc9, 0x39, 0x9c, - 0x54, 0x28, 0xd9, 0x86, 0x49, 0x46, 0x83, 0x85, 0x7f, 0x1a, 0x2d, 0x5f, 0xa7, 0x7d, 0x7a, 0xa9, - 0xa5, 0x96, 0xae, 0xed, 0xe5, 0x45, 0x2d, 0xdb, 0xeb, 0x7c, 0xf7, 0xe0, 0xfc, 0x23, 0xc4, 0x7b, - 0x2b, 0x32, 0x03, 0xff, 0x27, 0x5e, 0x5b, 0x09, 0xaa, 0x24, 0x8f, 0xe1, 0x78, 0xcb, 0xae, 0x3a, - 0xb4, 0xfc, 0x4d, 0xf3, 0x61, 0xf2, 0xce, 0x4b, 0x2e, 0x21, 0x3e, 0x6f, 0x91, 0x49, 0xfc, 0xdc, - 0xc8, 0x92, 0xd7, 0x42, 0x89, 0x2d, 0x78, 0x55, 0xb1, 0x7a, 0x43, 0x3d, 0xcd, 0xd4, 0xb5, 0x0a, - 0x16, 0xeb, 0x2d, 0x9d, 0xe8, 0xa9, 0x2a, 0x95, 0x7c, 0xde, 0xc9, 0xa6, 0x93, 0x4e, 0xbe, 0xe9, - 0x92, 0x3f, 0x0e, 0x34, 0xc7, 0x5f, 0x1d, 0x0a, 0x49, 0xce, 0x20, 0x14, 0x46, 0x85, 0x66, 0x15, - 0x2d, 0x9f, 0x8e, 0xca, 0xcc, 0xdd, 0x25, 0x79, 0x0f, 0x21, 0x37, 0xa4, 0x34, 0xed, 0x68, 0xf9, - 0xf2, 0xee, 0x43, 0x7b, 0xdc, 0x73, 0x77, 0x9f, 0xcc, 0xe0, 0x91, 0x23, 0x20, 0x1a, 0x5e, 0x0b, - 0x4c, 0x5e, 0x01, 0xac, 0x50, 0xde, 0x12, 0x39, 0x9c, 0x68, 0xf2, 0x55, 0xdf, 0x39, 0xde, 0x43, - 0x5f, 0xc3, 0xdb, 0x3e, 0xad, 0x67, 0x77, 0x69, 0xdd, 0xbc, 0xea, 0x86, 0x53, 0x06, 0x91, 0x46, - 0x36, 0x84, 0xc8, 0x1b, 0x38, 0xb1, 0x42, 0x85, 0x36, 0xfa, 0x5e, 0x4f, 0x76, 0xa7, 0x49, 0x06, - 0x71, 0x86, 0x57, 0x78, 0x98, 0xb5, 0xca, 0x1f, 0x87, 0x62, 0xfd, 0xc9, 0x20, 0xfe, 0xd2, 0x6c, - 0xd8, 0xe1, 0xb8, 0x0e, 0xc5, 0xe2, 0xc6, 0x10, 0x7d, 0x2a, 0x85, 0x33, 0x34, 0xb9, 0x80, 0x87, - 0xa6, 0x3d, 0xc8, 0x85, 0xe5, 0x5f, 0x1f, 0xc2, 0xdc, 0x6c, 0xc9, 0x1a, 0x02, 0x93, 0x35, 0x19, - 0xfd, 0x3e, 0xec, 0xdb, 0xe7, 0x8b, 0xf1, 0x03, 0x4b, 0xf7, 0x88, 0x64, 0xe0, 0xaf, 0x50, 0x92, - 0xe1, 0x50, 0x1d, 0xd0, 0xf3, 0x91, 0xed, 0x0e, 0x65, 0x0d, 0x81, 0x31, 0x78, 0x88, 0xd4, 0x5e, - 0x80, 0x43, 0xa4, 0x7a, 0xd9, 0x68, 0x38, 0xe3, 0xeb, 0x10, 0xdc, 0x5e, 0x6e, 0x43, 0x70, 0xbd, - 0x48, 0x8e, 0xc8, 0x0a, 0xa6, 0x2a, 0x05, 0x32, 0x20, 0xe3, 0x56, 0x58, 0xf3, 0x17, 0x63, 0x6b, - 0x07, 0xf4, 0x2d, 0xd0, 0xbf, 0xd4, 0xb3, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbc, 0xce, 0x6e, - 0x31, 0x63, 0x05, 0x00, 0x00, +func init() { + proto.RegisterFile("micro/go-micro/runtime/service/proto/runtime.proto", fileDescriptor_4bc91a8efec81434) +} + +var fileDescriptor_4bc91a8efec81434 = []byte{ + // 498 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4b, 0x6f, 0xd3, 0x40, + 0x10, 0xae, 0xe3, 0xd4, 0x2e, 0x63, 0x8c, 0xa2, 0x15, 0x42, 0x4b, 0x25, 0x20, 0xf2, 0xa5, 0xbd, + 0xe0, 0x48, 0xae, 0x10, 0xaf, 0x63, 0x53, 0x71, 0x21, 0x42, 0x72, 0xc5, 0x85, 0xdb, 0xe2, 0x8c, + 0x8a, 0x45, 0xed, 0x35, 0xde, 0x75, 0x44, 0x4f, 0x5c, 0xf9, 0xcb, 0xdc, 0xd0, 0xbe, 0x42, 0xe2, + 0xda, 0x5c, 0x72, 0x9b, 0x99, 0x9d, 0xfd, 0xfc, 0x3d, 0x56, 0x86, 0xac, 0x2a, 0x8b, 0x96, 0x2f, + 0x6e, 0xf8, 0x4b, 0x53, 0xb4, 0x5d, 0x2d, 0xcb, 0x0a, 0x17, 0x02, 0xdb, 0x4d, 0x59, 0xe0, 0xa2, + 0x69, 0xb9, 0xdc, 0x4e, 0x53, 0xdd, 0x91, 0xd9, 0x0d, 0x4f, 0xf5, 0x76, 0x6a, 0xe7, 0xc9, 0x1f, + 0x0f, 0xc2, 0x6b, 0x73, 0x83, 0x10, 0x98, 0xd6, 0xac, 0x42, 0xea, 0xcd, 0xbd, 0xf3, 0x07, 0xb9, + 0xae, 0x09, 0x85, 0x70, 0x83, 0xad, 0x28, 0x79, 0x4d, 0x27, 0x7a, 0xec, 0x5a, 0xf2, 0x04, 0x02, + 0xc1, 0xbb, 0xb6, 0x40, 0xea, 0xeb, 0x03, 0xdb, 0x29, 0x94, 0x86, 0xc9, 0x6f, 0x74, 0x6a, 0x50, + 0x54, 0xad, 0x66, 0xf8, 0x13, 0x0b, 0x7a, 0x3c, 0xf7, 0xd5, 0x4c, 0xd5, 0xe4, 0x12, 0x4e, 0x2a, + 0x94, 0x6c, 0xcd, 0x24, 0xa3, 0xc1, 0xdc, 0x3f, 0x8f, 0xb2, 0xb3, 0xb4, 0x4f, 0x2f, 0xb5, 0xd4, + 0xd2, 0x95, 0xdd, 0xbc, 0xaa, 0x65, 0x7b, 0x97, 0x6f, 0x2f, 0x9e, 0xbe, 0x87, 0x78, 0xef, 0x88, + 0xcc, 0xc0, 0xff, 0x8e, 0x77, 0x56, 0x82, 0x2a, 0xc9, 0x63, 0x38, 0xde, 0xb0, 0xdb, 0x0e, 0x2d, + 0x7f, 0xd3, 0xbc, 0x9b, 0xbc, 0xf1, 0x92, 0x6b, 0x88, 0x2f, 0x5b, 0x64, 0x12, 0x3f, 0x35, 0xb2, + 0xe4, 0xb5, 0x50, 0x62, 0x0b, 0x5e, 0x55, 0xac, 0x5e, 0x53, 0x4f, 0x33, 0x75, 0xad, 0x82, 0xc5, + 0x7a, 0x43, 0x27, 0x7a, 0xaa, 0x4a, 0x25, 0x9f, 0x77, 0xb2, 0xe9, 0xa4, 0x93, 0x6f, 0xba, 0xe4, + 0x97, 0x03, 0xcd, 0xf1, 0x47, 0x87, 0x42, 0x92, 0x0b, 0x08, 0x6d, 0x24, 0x9a, 0x55, 0x94, 0x3d, + 0x1d, 0x95, 0x99, 0xbb, 0x4d, 0xf2, 0x16, 0x42, 0x6e, 0x48, 0x69, 0xda, 0x51, 0xf6, 0xe2, 0xfe, + 0xa5, 0x3d, 0xee, 0xb9, 0xdb, 0x4f, 0x66, 0xf0, 0xc8, 0x11, 0x10, 0x0d, 0xaf, 0x05, 0x26, 0x67, + 0x10, 0xe5, 0xc8, 0xd6, 0x3b, 0x2a, 0x87, 0x23, 0x4d, 0xbe, 0x98, 0x45, 0xc7, 0x7c, 0xe8, 0x3d, + 0xbc, 0xee, 0x13, 0x7b, 0x76, 0x9f, 0xd8, 0xce, 0xc7, 0xfe, 0xd1, 0xba, 0x82, 0x87, 0x06, 0xdb, + 0x90, 0x22, 0xaf, 0xe0, 0xc4, 0x8a, 0x15, 0xda, 0xec, 0xff, 0xfa, 0xb2, 0x5d, 0x4d, 0x96, 0x10, + 0x2f, 0xf1, 0x16, 0x0f, 0xb3, 0x57, 0x79, 0xe4, 0x50, 0xac, 0x47, 0x4b, 0x88, 0x3f, 0x37, 0x6b, + 0x76, 0x38, 0xae, 0x43, 0xb1, 0xb8, 0x31, 0x44, 0x1f, 0x4b, 0x21, 0x2d, 0xaa, 0x72, 0xc1, 0xb4, + 0x07, 0xb9, 0x90, 0xfd, 0xf6, 0x21, 0xcc, 0xcd, 0x29, 0x59, 0x41, 0x60, 0xf2, 0x26, 0xa3, 0x6f, + 0xc4, 0x7e, 0xfd, 0x74, 0x3e, 0xbe, 0x60, 0xe9, 0x1e, 0x91, 0x0f, 0x30, 0x55, 0x39, 0x91, 0x91, + 0x5c, 0x1d, 0xd4, 0xf3, 0xb1, 0xe3, 0x2d, 0xd0, 0x0a, 0x02, 0xe3, 0xf1, 0x10, 0xaf, 0xbd, 0x0c, + 0x87, 0x78, 0xf5, 0xe2, 0xd1, 0x70, 0xc6, 0xda, 0x21, 0xb8, 0xbd, 0xe8, 0x86, 0xe0, 0x7a, 0xa9, + 0x68, 0x99, 0x2a, 0x88, 0x21, 0x99, 0x3b, 0x79, 0x0d, 0xc9, 0xdc, 0xcd, 0x2f, 0x39, 0xfa, 0x1a, + 0xe8, 0x3f, 0xeb, 0xc5, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbe, 0x95, 0xdf, 0xf9, 0x8f, 0x05, + 0x00, 0x00, } diff --git a/runtime/service/proto/runtime.micro.go b/runtime/service/proto/runtime.pb.micro.go similarity index 87% rename from runtime/service/proto/runtime.micro.go rename to runtime/service/proto/runtime.pb.micro.go index b5a3c4f5..38f340d4 100644 --- a/runtime/service/proto/runtime.micro.go +++ b/runtime/service/proto/runtime.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: runtime.proto +// source: micro/go-micro/runtime/service/proto/runtime.proto package go_micro_runtime @@ -35,7 +35,7 @@ var _ server.Option type RuntimeService interface { Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) - Get(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error) + Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) @@ -69,9 +69,9 @@ func (c *runtimeService) Create(ctx context.Context, in *CreateRequest, opts ... return out, nil } -func (c *runtimeService) Get(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error) { - req := c.c.NewRequest(c.name, "Runtime.Get", in) - out := new(GetResponse) +func (c *runtimeService) Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) { + req := c.c.NewRequest(c.name, "Runtime.Read", in) + out := new(ReadResponse) err := c.c.Call(ctx, req, out, opts...) if err != nil { return nil, err @@ -113,7 +113,7 @@ func (c *runtimeService) List(ctx context.Context, in *ListRequest, opts ...clie type RuntimeHandler interface { Create(context.Context, *CreateRequest, *CreateResponse) error - Get(context.Context, *GetRequest, *GetResponse) error + Read(context.Context, *ReadRequest, *ReadResponse) error Delete(context.Context, *DeleteRequest, *DeleteResponse) error Update(context.Context, *UpdateRequest, *UpdateResponse) error List(context.Context, *ListRequest, *ListResponse) error @@ -122,7 +122,7 @@ type RuntimeHandler interface { func RegisterRuntimeHandler(s server.Server, hdlr RuntimeHandler, opts ...server.HandlerOption) error { type runtime interface { Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error - Get(ctx context.Context, in *GetRequest, out *GetResponse) error + Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error List(ctx context.Context, in *ListRequest, out *ListResponse) error @@ -142,8 +142,8 @@ func (h *runtimeHandler) Create(ctx context.Context, in *CreateRequest, out *Cre return h.RuntimeHandler.Create(ctx, in, out) } -func (h *runtimeHandler) Get(ctx context.Context, in *GetRequest, out *GetResponse) error { - return h.RuntimeHandler.Get(ctx, in, out) +func (h *runtimeHandler) Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error { + return h.RuntimeHandler.Read(ctx, in, out) } func (h *runtimeHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error { diff --git a/runtime/service/proto/runtime.proto b/runtime/service/proto/runtime.proto index 44a83df4..86814f9d 100644 --- a/runtime/service/proto/runtime.proto +++ b/runtime/service/proto/runtime.proto @@ -4,7 +4,7 @@ package go.micro.runtime; service Runtime { rpc Create(CreateRequest) returns (CreateResponse) {}; - rpc Get(GetRequest) returns (GetResponse) {}; + rpc Read(ReadRequest) returns (ReadResponse) {}; rpc Delete(DeleteRequest) returns (DeleteResponse) {}; rpc Update(UpdateRequest) returns (UpdateResponse) {}; rpc List(ListRequest) returns (ListResponse) {}; @@ -41,17 +41,17 @@ message CreateRequest { message CreateResponse {} -message GetOptions { +message ReadOptions { // version of the service string version = 2; } -message GetRequest { +message ReadRequest { string name = 1; - GetOptions options = 2; + ReadOptions options = 2; } -message GetResponse { +message ReadResponse { repeated Service services = 1; } diff --git a/runtime/service/service.go b/runtime/service/service.go index 00752989..769f0d69 100644 --- a/runtime/service/service.go +++ b/runtime/service/service.go @@ -75,23 +75,23 @@ func (s *svc) Create(svc *runtime.Service, opts ...runtime.CreateOption) error { return nil } -// Get returns the service with the given name from the runtime -func (s *svc) Get(name string, opts ...runtime.GetOption) ([]*runtime.Service, error) { - options := runtime.GetOptions{} +// Read returns the service with the given name from the runtime +func (s *svc) Read(name string, opts ...runtime.ReadOption) ([]*runtime.Service, error) { + options := runtime.ReadOptions{} // apply requested options for _, o := range opts { o(&options) } // runtime service create request - req := &pb.GetRequest{ + req := &pb.ReadRequest{ Name: name, - Options: &pb.GetOptions{ + Options: &pb.ReadOptions{ Version: options.Version, }, } - resp, err := s.runtime.Get(context.Background(), req) + resp, err := s.runtime.Read(context.Background(), req) if err != nil { return nil, err } From 080363e8c41527619825d35ef606391d28488aae Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 25 Nov 2019 16:31:43 +0000 Subject: [PATCH 245/344] The mega cruft proxy PR (#974) * the mega cruft proxy PR * Rename broker id * add protocol=grpc * fix compilation breaks * Add the tunnel broker to the network * fix broker id * continue to be backwards compatible in the protocol --- broker/http_broker.go | 11 +-- client/common_test.go | 12 +++ client/grpc/grpc.go | 45 ++++++++-- client/grpc/grpc_test.go | 3 + client/rpc_client.go | 43 +++++++--- client/rpc_client_test.go | 3 + client/rpc_codec.go | 5 ++ network/default.go | 8 ++ proxy/grpc/grpc.go | 11 ++- proxy/http/http.go | 66 ++++++++++++++- proxy/mucp/mucp.go | 32 +++++++- proxy/proxy.go | 6 +- server/grpc/grpc.go | 9 +- server/grpc/request.go | 15 ++++ server/grpc/subscriber.go | 3 +- server/rpc_codec.go | 6 ++ server/rpc_event.go | 33 ++++++++ server/rpc_request.go | 19 +++++ server/rpc_router.go | 169 ++++++++++++++++++++++++++++++++++++-- server/rpc_server.go | 149 +++++++++++++++++++++++++++------ server/server.go | 11 +++ server/subscriber.go | 125 ---------------------------- util/mux/mux.go | 7 ++ 23 files changed, 595 insertions(+), 196 deletions(-) create mode 100644 server/rpc_event.go diff --git a/broker/http_broker.go b/broker/http_broker.go index 3e9fbc54..385c7fa0 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -126,7 +126,7 @@ func newHttpBroker(opts ...Option) Broker { } h := &httpBroker{ - id: "broker-" + uuid.New().String(), + id: "go.micro.http.broker-" + uuid.New().String(), address: addr, opts: options, r: reg, @@ -472,7 +472,7 @@ func (h *httpBroker) Init(opts ...Option) error { } if len(h.id) == 0 { - h.id = "broker-" + uuid.New().String() + h.id = "go.micro.http.broker-" + uuid.New().String() } // get registry @@ -648,9 +648,6 @@ func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO return nil, err } - // create unique id - id := h.id + "." + uuid.New().String() - var secure bool if h.opts.Secure || h.opts.TLSConfig != nil { @@ -659,7 +656,7 @@ func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO // register service node := ®istry.Node{ - Id: id, + Id: h.id, Address: mnet.HostPort(addr, port), Metadata: map[string]string{ "secure": fmt.Sprintf("%t", secure), @@ -684,7 +681,7 @@ func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO subscriber := &httpSubscriber{ opts: options, hb: h, - id: id, + id: h.id, topic: topic, fn: handler, svc: service, diff --git a/client/common_test.go b/client/common_test.go index 42d1ed87..25b2b09c 100644 --- a/client/common_test.go +++ b/client/common_test.go @@ -15,10 +15,16 @@ var ( { Id: "foo-1.0.0-123", Address: "localhost:9999", + Metadata: map[string]string{ + "protocol": "mucp", + }, }, { Id: "foo-1.0.0-321", Address: "localhost:9999", + Metadata: map[string]string{ + "protocol": "mucp", + }, }, }, }, @@ -29,6 +35,9 @@ var ( { Id: "foo-1.0.1-321", Address: "localhost:6666", + Metadata: map[string]string{ + "protocol": "mucp", + }, }, }, }, @@ -39,6 +48,9 @@ var ( { Id: "foo-1.0.3-345", Address: "localhost:8888", + Metadata: map[string]string{ + "protocol": "mucp", + }, }, }, }, diff --git a/client/grpc/grpc.go b/client/grpc/grpc.go index fd5bc853..6ca92586 100644 --- a/client/grpc/grpc.go +++ b/client/grpc/grpc.go @@ -13,6 +13,7 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/client/selector" "github.com/micro/go-micro/codec" + raw "github.com/micro/go-micro/codec/bytes" "github.com/micro/go-micro/errors" "github.com/micro/go-micro/metadata" "github.com/micro/go-micro/registry" @@ -70,8 +71,13 @@ func (g *grpcClient) next(request client.Request, opts client.CallOptions) (sele }, nil } + // only get the things that are of grpc protocol + selectOptions := append(opts.SelectOptions, selector.WithFilter( + selector.FilterLabel("protocol", "grpc"), + )) + // get next nodes from the selector - next, err := g.opts.Selector.Select(service, opts.SelectOptions...) + next, err := g.opts.Selector.Select(service, selectOptions...) if err != nil { if err == selector.ErrNotFound { return nil, errors.InternalServerError("go.micro.client", "service %s: %s", service, err.Error()) @@ -510,29 +516,56 @@ func (g *grpcClient) Stream(ctx context.Context, req client.Request, opts ...cli } func (g *grpcClient) Publish(ctx context.Context, p client.Message, opts ...client.PublishOption) error { + var options client.PublishOptions + for _, o := range opts { + o(&options) + } + md, ok := metadata.FromContext(ctx) if !ok { md = make(map[string]string) } md["Content-Type"] = p.ContentType() + md["Micro-Topic"] = p.Topic() cf, err := g.newGRPCCodec(p.ContentType()) if err != nil { return errors.InternalServerError("go.micro.client", err.Error()) } - b, err := cf.Marshal(p.Payload()) - if err != nil { - return errors.InternalServerError("go.micro.client", err.Error()) + var body []byte + + // passed in raw data + if d, ok := p.Payload().(*raw.Frame); ok { + body = d.Data + } else { + // set the body + b, err := cf.Marshal(p.Payload()) + if err != nil { + return errors.InternalServerError("go.micro.client", err.Error()) + } + body = b } g.once.Do(func() { g.opts.Broker.Connect() }) - return g.opts.Broker.Publish(p.Topic(), &broker.Message{ + topic := p.Topic() + + // get proxy topic + if prx := os.Getenv("MICRO_PROXY"); len(prx) > 0 { + options.Exchange = prx + } + + // get the exchange + if len(options.Exchange) > 0 { + topic = options.Exchange + } + + return g.opts.Broker.Publish(topic, &broker.Message{ Header: md, - Body: b, + Body: body, }) } diff --git a/client/grpc/grpc_test.go b/client/grpc/grpc_test.go index e437c0ef..6d975ca3 100644 --- a/client/grpc/grpc_test.go +++ b/client/grpc/grpc_test.go @@ -45,6 +45,9 @@ func TestGRPCClient(t *testing.T) { { Id: "test-1", Address: l.Addr().String(), + Metadata: map[string]string{ + "protocol": "grpc", + }, }, }, }) diff --git a/client/rpc_client.go b/client/rpc_client.go index 0a5a0580..71f55708 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -13,6 +13,7 @@ import ( "github.com/micro/go-micro/client/pool" "github.com/micro/go-micro/client/selector" "github.com/micro/go-micro/codec" + raw "github.com/micro/go-micro/codec/bytes" "github.com/micro/go-micro/errors" "github.com/micro/go-micro/metadata" "github.com/micro/go-micro/registry" @@ -349,8 +350,13 @@ func (r *rpcClient) next(request Request, opts CallOptions) (selector.Next, erro }, nil } + // only get the things that are of mucp protocol + selectOptions := append(opts.SelectOptions, selector.WithFilter( + selector.FilterLabel("protocol", "mucp"), + )) + // get next nodes from the selector - next, err := r.opts.Selector.Select(service, opts.SelectOptions...) + next, err := r.opts.Selector.Select(service, selectOptions...) if err != nil { if err == selector.ErrNotFound { return nil, errors.InternalServerError("go.micro.client", "service %s: %s", service, err.Error()) @@ -583,26 +589,37 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt return errors.InternalServerError("go.micro.client", err.Error()) } - // new buffer - b := buf.New(nil) + var body []byte - if err := cf(b).Write(&codec.Message{ - Target: topic, - Type: codec.Event, - Header: map[string]string{ - "Micro-Id": id, - "Micro-Topic": msg.Topic(), - }, - }, msg.Payload()); err != nil { - return errors.InternalServerError("go.micro.client", err.Error()) + // passed in raw data + if d, ok := msg.Payload().(*raw.Frame); ok { + body = d.Data + } else { + // new buffer + b := buf.New(nil) + + if err := cf(b).Write(&codec.Message{ + Target: topic, + Type: codec.Event, + Header: map[string]string{ + "Micro-Id": id, + "Micro-Topic": msg.Topic(), + }, + }, msg.Payload()); err != nil { + return errors.InternalServerError("go.micro.client", err.Error()) + } + + // set the body + body = b.Bytes() } + r.once.Do(func() { r.opts.Broker.Connect() }) return r.opts.Broker.Publish(topic, &broker.Message{ Header: md, - Body: b.Bytes(), + Body: body, }) } diff --git a/client/rpc_client_test.go b/client/rpc_client_test.go index f9dbc04d..ace08fff 100644 --- a/client/rpc_client_test.go +++ b/client/rpc_client_test.go @@ -143,6 +143,9 @@ func TestCallWrapper(t *testing.T) { { Id: id, Address: address, + Metadata: map[string]string{ + "protocol": "mucp", + }, }, }, }) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index c20537ea..60dc02b5 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -145,6 +145,11 @@ func setupProtocol(msg *transport.Message, node *registry.Node) codec.NewCodec { return nil } + // processing topic publishing + if len(msg.Header["Micro-Topic"]) > 0 { + return nil + } + // no protocol use old codecs switch msg.Header["Content-Type"] { case "application/json": diff --git a/network/default.go b/network/default.go index 7c37517d..5d4a9711 100644 --- a/network/default.go +++ b/network/default.go @@ -19,6 +19,7 @@ import ( "github.com/micro/go-micro/server" "github.com/micro/go-micro/transport" "github.com/micro/go-micro/tunnel" + bun "github.com/micro/go-micro/tunnel/broker" tun "github.com/micro/go-micro/tunnel/transport" "github.com/micro/go-micro/util/backoff" "github.com/micro/go-micro/util/log" @@ -112,6 +113,11 @@ func newNetwork(opts ...Option) Network { tun.WithTunnel(options.Tunnel), ) + // create the tunnel broker + tunBroker := bun.NewBroker( + bun.WithTunnel(options.Tunnel), + ) + // server is network server server := server.NewServer( server.Id(options.Id), @@ -119,10 +125,12 @@ func newNetwork(opts ...Option) Network { server.Advertise(advertise), server.Name(options.Name), server.Transport(tunTransport), + server.Broker(tunBroker), ) // client is network client client := client.NewClient( + client.Broker(tunBroker), client.Transport(tunTransport), client.Selector( rtr.NewSelector( diff --git a/proxy/grpc/grpc.go b/proxy/grpc/grpc.go index 89947054..91333662 100644 --- a/proxy/grpc/grpc.go +++ b/proxy/grpc/grpc.go @@ -10,7 +10,6 @@ import ( "github.com/micro/go-micro/client/grpc" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/config/options" - "github.com/micro/go-micro/errors" "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/server" ) @@ -62,8 +61,14 @@ func readLoop(r server.Request, s client.Stream) error { } } -func (p *Proxy) SendRequest(ctx context.Context, req client.Request, rsp client.Response) error { - return errors.InternalServerError("go.micro.proxy.grpc", "SendRequest is unsupported") +// ProcessMessage acts as a message exchange and forwards messages to ongoing topics +// TODO: should we look at p.Endpoint and only send to the local endpoint? probably +func (p *Proxy) ProcessMessage(ctx context.Context, msg server.Message) error { + // TODO: check that we're not broadcast storming by sending to the same topic + // that we're actually subscribed to + + // directly publish to the local client + return p.Client.Publish(ctx, msg) } // ServeRequest honours the server.Proxy interface diff --git a/proxy/http/http.go b/proxy/http/http.go index 0df61927..9bcf01db 100644 --- a/proxy/http/http.go +++ b/proxy/http/http.go @@ -10,7 +10,6 @@ import ( "net/url" "path" - "github.com/micro/go-micro/client" "github.com/micro/go-micro/config/options" "github.com/micro/go-micro/errors" "github.com/micro/go-micro/proxy" @@ -45,8 +44,69 @@ func getEndpoint(hdr map[string]string) string { return "" } -func (p *Proxy) SendRequest(ctx context.Context, req client.Request, rsp client.Response) error { - return errors.InternalServerError("go.micro.proxy.http", "SendRequest is unsupported") +func getTopic(hdr map[string]string) string { + ep := hdr["Micro-Topic"] + if len(ep) > 0 && ep[0] == '/' { + return ep + } + return "/" + hdr["Micro-Topic"] +} + +// ProcessMessage handles incoming asynchronous messages +func (p *Proxy) ProcessMessage(ctx context.Context, msg server.Message) error { + if p.Endpoint == "" { + p.Endpoint = proxy.DefaultEndpoint + } + + // get the header + hdr := msg.Header() + + // get topic + // use /topic as endpoint + endpoint := getTopic(hdr) + + // set the endpoint + if len(endpoint) == 0 { + endpoint = p.Endpoint + } else { + // add endpoint to backend + u, err := url.Parse(p.Endpoint) + if err != nil { + return errors.InternalServerError(msg.Topic(), err.Error()) + } + u.Path = path.Join(u.Path, endpoint) + endpoint = u.String() + } + + // send to backend + hreq, err := http.NewRequest("POST", endpoint, bytes.NewReader(msg.Body())) + if err != nil { + return errors.InternalServerError(msg.Topic(), err.Error()) + } + + // set the headers + for k, v := range hdr { + hreq.Header.Set(k, v) + } + + // make the call + hrsp, err := http.DefaultClient.Do(hreq) + if err != nil { + return errors.InternalServerError(msg.Topic(), err.Error()) + } + + // read body + b, err := ioutil.ReadAll(hrsp.Body) + hrsp.Body.Close() + if err != nil { + return errors.InternalServerError(msg.Topic(), err.Error()) + } + + if hrsp.StatusCode != 200 { + return errors.New(msg.Topic(), string(b), int32(hrsp.StatusCode)) + } + + return nil } // ServeRequest honours the server.Router interface diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index d0738358..1036f722 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -281,8 +281,34 @@ func (p *Proxy) watchRoutes() { } } -func (p *Proxy) SendRequest(ctx context.Context, req client.Request, rsp client.Response) error { - return errors.InternalServerError("go.micro.proxy", "SendRequest is unsupported") +// ProcessMessage acts as a message exchange and forwards messages to ongoing topics +// TODO: should we look at p.Endpoint and only send to the local endpoint? probably +func (p *Proxy) ProcessMessage(ctx context.Context, msg server.Message) error { + // TODO: check that we're not broadcast storming by sending to the same topic + // that we're actually subscribed to + + log.Tracef("Received message for %s", msg.Topic()) + + var errors []string + + // directly publish to the local client + if err := p.Client.Publish(ctx, msg); err != nil { + errors = append(errors, err.Error()) + } + + // publish to all links + for _, client := range p.Links { + if err := client.Publish(ctx, msg); err != nil { + errors = append(errors, err.Error()) + } + } + + if len(errors) == 0 { + return nil + } + + // there is no error...muahaha + return fmt.Errorf("Message processing error: %s", strings.Join(errors, "\n")) } // ServeRequest honours the server.Router interface @@ -302,6 +328,8 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server return errors.BadRequest("go.micro.proxy", "service name is blank") } + log.Tracef("Received request for %s", service) + // are we network routing or local routing if len(p.Links) == 0 { local = true diff --git a/proxy/proxy.go b/proxy/proxy.go index e91eaf0f..e08926e9 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -13,9 +13,9 @@ import ( // Proxy can be used as a proxy server for go-micro services type Proxy interface { options.Options - // SendRequest honours the client.Router interface - SendRequest(context.Context, client.Request, client.Response) error - // ServeRequest honours the server.Router interface + // ProcessMessage handles inbound messages + ProcessMessage(context.Context, server.Message) error + // ServeRequest handles inbound requests ServeRequest(context.Context, server.Request, server.Response) error } diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index a09dd594..942d1a8f 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -89,6 +89,11 @@ func newGRPCServer(opts ...server.Option) server.Server { type grpcRouter struct { h func(context.Context, server.Request, interface{}) error + m func(context.Context, server.Message) error +} + +func (r grpcRouter) ProcessMessage(ctx context.Context, msg server.Message) error { + return r.m(ctx, msg) } func (r grpcRouter) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error { @@ -258,7 +263,7 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) error { handler = g.opts.HdlrWrappers[i-1](handler) } - r := grpcRouter{handler} + r := grpcRouter{h: handler} // serve the actual request using the request router if err := r.ServeRequest(ctx, request, response); err != nil { @@ -564,7 +569,7 @@ func (g *grpcServer) Register() error { node.Metadata["registry"] = config.Registry.String() node.Metadata["server"] = g.String() node.Metadata["transport"] = g.String() - // node.Metadata["transport"] = config.Transport.String() + node.Metadata["protocol"] = "grpc" g.RLock() // Maps are ordered randomly, sort the keys for consistency diff --git a/server/grpc/request.go b/server/grpc/request.go index 617b9a7d..adfed48e 100644 --- a/server/grpc/request.go +++ b/server/grpc/request.go @@ -20,6 +20,9 @@ type rpcMessage struct { topic string contentType string payload interface{} + header map[string]string + body []byte + codec codec.Codec } func (r *rpcRequest) ContentType() string { @@ -73,3 +76,15 @@ func (r *rpcMessage) Topic() string { func (r *rpcMessage) Payload() interface{} { return r.payload } + +func (r *rpcMessage) Header() map[string]string { + return r.header +} + +func (r *rpcMessage) Body() []byte { + return r.body +} + +func (r *rpcMessage) Codec() codec.Reader { + return r.codec +} diff --git a/server/grpc/subscriber.go b/server/grpc/subscriber.go index 1f885cab..0e4f4f4f 100644 --- a/server/grpc/subscriber.go +++ b/server/grpc/subscriber.go @@ -33,7 +33,6 @@ type subscriber struct { } func newSubscriber(topic string, sub interface{}, opts ...server.SubscriberOption) server.Subscriber { - options := server.SubscriberOptions{ AutoAck: true, } @@ -239,6 +238,8 @@ func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broke topic: sb.topic, contentType: ct, payload: req.Interface(), + header: msg.Header, + body: msg.Body, }) }() } diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 2fbddc0e..342110aa 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -135,12 +135,18 @@ func setupProtocol(msg *transport.Message) codec.NewCodec { endpoint := getHeader("Micro-Endpoint", msg.Header) protocol := getHeader("Micro-Protocol", msg.Header) target := getHeader("Micro-Target", msg.Header) + topic := getHeader("Micro-Topic", msg.Header) // if the protocol exists (mucp) do nothing if len(protocol) > 0 { return nil } + // newer method of processing messages over transport + if len(topic) > 0 { + 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"]] diff --git a/server/rpc_event.go b/server/rpc_event.go new file mode 100644 index 00000000..4bd39d4d --- /dev/null +++ b/server/rpc_event.go @@ -0,0 +1,33 @@ +package server + +import ( + "github.com/micro/go-micro/broker" + "github.com/micro/go-micro/transport" +) + +// event is a broker event we handle on the server transport +type event struct { + message *broker.Message +} + +func (e *event) Ack() error { + // there is no ack support + return nil +} + +func (e *event) Message() *broker.Message { + return e.message +} + +func (e *event) Topic() string { + return e.message.Header["Micro-Topic"] +} + +func newEvent(msg transport.Message) *event { + return &event{ + message: &broker.Message{ + Header: msg.Header, + Body: msg.Body, + }, + } +} diff --git a/server/rpc_request.go b/server/rpc_request.go index 532cf4b1..065d57e4 100644 --- a/server/rpc_request.go +++ b/server/rpc_request.go @@ -1,8 +1,11 @@ package server import ( + "bytes" + "github.com/micro/go-micro/codec" "github.com/micro/go-micro/transport" + "github.com/micro/go-micro/util/buf" ) type rpcRequest struct { @@ -23,6 +26,9 @@ type rpcMessage struct { topic string contentType string payload interface{} + header map[string]string + body []byte + codec codec.NewCodec } func (r *rpcRequest) Codec() codec.Reader { @@ -86,3 +92,16 @@ func (r *rpcMessage) Topic() string { func (r *rpcMessage) Payload() interface{} { return r.payload } + +func (r *rpcMessage) Header() map[string]string { + return r.header +} + +func (r *rpcMessage) Body() []byte { + return r.body +} + +func (r *rpcMessage) Codec() codec.Reader { + b := buf.New(bytes.NewBuffer(r.body)) + return r.codec(b) +} diff --git a/server/rpc_router.go b/server/rpc_router.go index b1eb66ff..493f2af7 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -9,6 +9,7 @@ package server import ( "context" "errors" + "fmt" "io" "reflect" "strings" @@ -60,19 +61,30 @@ type response struct { // router represents an RPC router. type router struct { - name string - mu sync.Mutex // protects the serviceMap - serviceMap map[string]*service - reqLock sync.Mutex // protects freeReq - freeReq *request - respLock sync.Mutex // protects freeResp - freeResp *response + name string + + mu sync.Mutex // protects the serviceMap + serviceMap map[string]*service + + reqLock sync.Mutex // protects freeReq + freeReq *request + + respLock sync.Mutex // protects freeResp + freeResp *response + + // handler wrappers hdlrWrappers []HandlerWrapper + // subscriber wrappers + subWrappers []SubscriberWrapper + + su sync.RWMutex + subscribers map[string][]*subscriber } func newRpcRouter() *router { return &router{ - serviceMap: make(map[string]*service), + serviceMap: make(map[string]*service), + subscribers: make(map[string][]*subscriber), } } @@ -449,3 +461,144 @@ func (router *router) ServeRequest(ctx context.Context, r Request, rsp Response) } return service.call(ctx, router, sending, mtype, req, argv, replyv, rsp.Codec()) } + +func (router *router) NewSubscriber(topic string, handler interface{}, opts ...SubscriberOption) Subscriber { + return newSubscriber(topic, handler, opts...) +} + +func (router *router) Subscribe(s Subscriber) error { + sub, ok := s.(*subscriber) + if !ok { + return fmt.Errorf("invalid subscriber: expected *subscriber") + } + if len(sub.handlers) == 0 { + return fmt.Errorf("invalid subscriber: no handler functions") + } + + if err := validateSubscriber(sub); err != nil { + return err + } + + router.su.Lock() + defer router.su.Unlock() + + // append to subscribers + subs := router.subscribers[sub.Topic()] + subs = append(subs, sub) + router.subscribers[sub.Topic()] = subs + + return nil +} + +func (router *router) ProcessMessage(ctx context.Context, msg Message) error { + router.su.RLock() + + // get the subscribers by topic + subs, ok := router.subscribers[msg.Topic()] + if !ok { + router.su.RUnlock() + return nil + } + + // unlock since we only need to get the subs + router.su.RUnlock() + + var results []string + + // we may have multiple subscribers for the topic + for _, sub := range subs { + // we may have multiple handlers per subscriber + for i := 0; i < len(sub.handlers); i++ { + // get the handler + handler := sub.handlers[i] + + var isVal bool + var req reflect.Value + + // check whether the handler is a pointer + if handler.reqType.Kind() == reflect.Ptr { + req = reflect.New(handler.reqType.Elem()) + } else { + req = reflect.New(handler.reqType) + isVal = true + } + + // if its a value get the element + if isVal { + req = req.Elem() + } + + if handler.reqType.Kind() == reflect.Ptr { + req = reflect.New(handler.reqType.Elem()) + } else { + req = reflect.New(handler.reqType) + isVal = true + } + + // if its a value get the element + if isVal { + req = req.Elem() + } + + cc := msg.Codec() + + // read the header. mostly a noop + if err := cc.ReadHeader(&codec.Message{}, codec.Event); err != nil { + return err + } + + // read the body into the handler request value + if err := cc.ReadBody(req.Interface()); err != nil { + return err + } + + // create the handler which will honour the SubscriberFunc type + fn := func(ctx context.Context, msg Message) error { + var vals []reflect.Value + if sub.typ.Kind() != reflect.Func { + vals = append(vals, sub.rcvr) + } + if handler.ctxType != nil { + vals = append(vals, reflect.ValueOf(ctx)) + } + + // values to pass the handler + vals = append(vals, reflect.ValueOf(msg.Payload())) + + // execute the actuall call of the handler + returnValues := handler.method.Call(vals) + if err := returnValues[0].Interface(); err != nil { + return err.(error) + } + return nil + } + + // wrap with subscriber wrappers + for i := len(router.subWrappers); i > 0; i-- { + fn = router.subWrappers[i-1](fn) + } + + // create new rpc message + rpcMsg := &rpcMessage{ + topic: msg.Topic(), + contentType: msg.ContentType(), + payload: req.Interface(), + codec: msg.(*rpcMessage).codec, + header: msg.Header(), + body: msg.Body(), + } + + // execute the message handler + if err := fn(ctx, rpcMsg); err != nil { + results = append(results, err.Error()) + } + } + } + + // if no errors just return + if len(results) == 0 { + return nil + } + + return errors.New("subscriber error: " + strings.Join(results, "\n")) +} diff --git a/server/rpc_server.go b/server/rpc_server.go index 850fd97b..607ead53 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -14,6 +14,7 @@ import ( "github.com/micro/go-micro/broker" "github.com/micro/go-micro/codec" + raw "github.com/micro/go-micro/codec/bytes" "github.com/micro/go-micro/metadata" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/transport" @@ -30,11 +31,13 @@ type rpcServer struct { sync.RWMutex opts Options handlers map[string]Handler - subscribers map[*subscriber][]broker.Subscriber + subscribers map[Subscriber][]broker.Subscriber // marks the serve as started started bool // used for first registration registered bool + // subscribe to service name + subscriber broker.Subscriber // graceful exit wg *sync.WaitGroup } @@ -43,12 +46,13 @@ func newRpcServer(opts ...Option) Server { options := newOptions(opts...) router := newRpcRouter() router.hdlrWrappers = options.HdlrWrappers + router.subWrappers = options.SubWrappers return &rpcServer{ opts: options, router: router, handlers: make(map[string]Handler), - subscribers: make(map[*subscriber][]broker.Subscriber), + subscribers: make(map[Subscriber][]broker.Subscriber), exit: make(chan chan error), wg: wait(options.Context), } @@ -56,12 +60,85 @@ func newRpcServer(opts ...Option) Server { type rpcRouter struct { h func(context.Context, Request, interface{}) error + m func(context.Context, Message) error +} + +func (r rpcRouter) ProcessMessage(ctx context.Context, msg Message) error { + return r.m(ctx, msg) } func (r rpcRouter) ServeRequest(ctx context.Context, req Request, rsp Response) error { return r.h(ctx, req, rsp) } +// HandleEvent handles inbound messages to the service directly +// TODO: handle requests from an event. We won't send a response. +func (s *rpcServer) HandleEvent(e broker.Event) error { + // formatting horrible cruft + msg := e.Message() + + if msg.Header == nil { + // create empty map in case of headers empty to avoid panic later + msg.Header = make(map[string]string) + } + + // 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 + } + + // create context + ctx := metadata.NewContext(context.Background(), hdr) + + // TODO: inspect message header + // Micro-Service means a request + // Micro-Topic means a message + + rpcMsg := &rpcMessage{ + topic: msg.Header["Micro-Topic"], + contentType: ct, + payload: &raw.Frame{msg.Body}, + codec: cf, + header: msg.Header, + body: msg.Body, + } + + // existing router + r := Router(s.router) + + // if the router is present then execute it + if s.opts.Router != nil { + // create a wrapped function + handler := s.opts.Router.ProcessMessage + + // execute the wrapper for it + for i := len(s.opts.SubWrappers); i > 0; i-- { + handler = s.opts.SubWrappers[i-1](handler) + } + + // set the router + r = rpcRouter{m: handler} + } + + return r.ProcessMessage(ctx, rpcMsg) +} + // ServeConn serves a single connection func (s *rpcServer) ServeConn(sock transport.Socket) { var wg sync.WaitGroup @@ -97,6 +174,26 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { return } + // check the message header for + // Micro-Service is a request + // Micro-Topic is a message + if t := msg.Header["Micro-Topic"]; len(t) > 0 { + // process the event + ev := newEvent(msg) + // TODO: handle the error event + if err := s.HandleEvent(ev); err != nil { + msg.Header["Micro-Error"] = err.Error() + } + // write back some 200 + sock.Send(&transport.Message{ + Header: msg.Header, + }) + // we're done + continue + } + + // business as usual + // use Micro-Stream as the stream identifier // in the event its blank we'll always process // on the same socket @@ -263,7 +360,7 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { } // set the router - r = rpcRouter{handler} + r = rpcRouter{h: handler} } // wait for processing to exit @@ -366,6 +463,7 @@ func (s *rpcServer) Init(opts ...Option) error { r := newRpcRouter() r.hdlrWrappers = s.opts.HdlrWrappers r.serviceMap = s.router.serviceMap + r.subWrappers = s.opts.SubWrappers s.router = r } @@ -391,29 +489,18 @@ func (s *rpcServer) Handle(h Handler) error { } func (s *rpcServer) NewSubscriber(topic string, sb interface{}, opts ...SubscriberOption) Subscriber { - return newSubscriber(topic, sb, opts...) + return s.router.NewSubscriber(topic, sb, opts...) } func (s *rpcServer) Subscribe(sb Subscriber) error { - sub, ok := sb.(*subscriber) - if !ok { - return fmt.Errorf("invalid subscriber: expected *subscriber") - } - if len(sub.handlers) == 0 { - return fmt.Errorf("invalid subscriber: no handler functions") - } + s.Lock() + defer s.Unlock() - if err := validateSubscriber(sb); err != nil { + if err := s.router.Subscribe(sb); err != nil { return err } - s.Lock() - defer s.Unlock() - _, ok = s.subscribers[sub] - if ok { - return fmt.Errorf("subscriber %v already exists", s) - } - s.subscribers[sub] = nil + s.subscribers[sb] = nil return nil } @@ -483,7 +570,7 @@ func (s *rpcServer) Register() error { } sort.Strings(handlerList) - var subscriberList []*subscriber + var subscriberList []Subscriber for e := range s.subscribers { // Only advertise non internal subscribers if !e.Options().Internal { @@ -491,7 +578,7 @@ func (s *rpcServer) Register() error { } } sort.Slice(subscriberList, func(i, j int) bool { - return subscriberList[i].topic > subscriberList[j].topic + return subscriberList[i].Topic() > subscriberList[j].Topic() }) endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList)) @@ -535,8 +622,17 @@ func (s *rpcServer) Register() error { s.registered = true + // subscribe to the topic with own name + sub, err := s.opts.Broker.Subscribe(config.Name, s.HandleEvent) + if err != nil { + return err + } + + // save the subscriber + s.subscriber = sub + + // subscribe for all of the subscribers for sb := range s.subscribers { - handler := s.createSubHandler(sb, s.opts) var opts []broker.SubscribeOption if queue := sb.Options().Queue; len(queue) > 0 { opts = append(opts, broker.Queue(queue)) @@ -550,10 +646,11 @@ func (s *rpcServer) Register() error { opts = append(opts, broker.DisableAutoAck()) } - sub, err := config.Broker.Subscribe(sb.Topic(), handler, opts...) + sub, err := config.Broker.Subscribe(sb.Topic(), s.HandleEvent, opts...) if err != nil { return err } + log.Logf("Subscribing %s to topic: %s", node.Id, sub.Topic()) s.subscribers[sb] = []broker.Subscriber{sub} } @@ -621,6 +718,12 @@ func (s *rpcServer) Deregister() error { s.registered = false + // close the subscriber + if s.subscriber != nil { + s.subscriber.Unsubscribe() + s.subscriber = nil + } + for sb, subs := range s.subscribers { for _, sub := range subs { log.Logf("Unsubscribing %s from topic: %s", node.Id, sub.Topic()) diff --git a/server/server.go b/server/server.go index 98f2cddb..34c38258 100644 --- a/server/server.go +++ b/server/server.go @@ -29,15 +29,26 @@ type Server interface { // Router handle serving messages type Router interface { + // ProcessMessage processes a message + ProcessMessage(context.Context, Message) error // ServeRequest processes a request to completion ServeRequest(context.Context, Request, Response) error } // Message is an async message interface type Message interface { + // Topic of the message Topic() string + // The decoded payload value Payload() interface{} + // The content type of the payload ContentType() string + // The raw headers of the message + Header() map[string]string + // The raw body of the message + Body() []byte + // Codec used to decode the message + Codec() codec.Reader } // Request is a synchronous request interface diff --git a/server/subscriber.go b/server/subscriber.go index f0f85cf8..62de0ed8 100644 --- a/server/subscriber.go +++ b/server/subscriber.go @@ -1,17 +1,10 @@ package server import ( - "bytes" - "context" "fmt" "reflect" - "strings" - "github.com/micro/go-micro/broker" - "github.com/micro/go-micro/codec" - "github.com/micro/go-micro/metadata" "github.com/micro/go-micro/registry" - "github.com/micro/go-micro/util/buf" ) const ( @@ -165,124 +158,6 @@ func validateSubscriber(sub Subscriber) error { return nil } -func (s *rpcServer) createSubHandler(sb *subscriber, opts Options) broker.Handler { - return func(p broker.Event) error { - msg := p.Message() - - if msg.Header == nil { - // create empty map in case of headers empty to avoid panic later - msg.Header = make(map[string]string) - } - - // 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 - } - - // create context - ctx := metadata.NewContext(context.Background(), hdr) - - results := make(chan error, len(sb.handlers)) - - for i := 0; i < len(sb.handlers); i++ { - handler := sb.handlers[i] - - var isVal bool - var req reflect.Value - - if handler.reqType.Kind() == reflect.Ptr { - req = reflect.New(handler.reqType.Elem()) - } else { - req = reflect.New(handler.reqType) - isVal = true - } - if isVal { - req = req.Elem() - } - - b := buf.New(bytes.NewBuffer(msg.Body)) - co := cf(b) - defer co.Close() - - if err := co.ReadHeader(&codec.Message{}, codec.Event); err != nil { - return err - } - - if err := co.ReadBody(req.Interface()); err != nil { - return err - } - - fn := func(ctx context.Context, msg Message) error { - var vals []reflect.Value - if sb.typ.Kind() != reflect.Func { - vals = append(vals, sb.rcvr) - } - if handler.ctxType != nil { - vals = append(vals, reflect.ValueOf(ctx)) - } - - vals = append(vals, reflect.ValueOf(msg.Payload())) - - returnValues := handler.method.Call(vals) - if err := returnValues[0].Interface(); err != nil { - return err.(error) - } - return nil - } - - for i := len(opts.SubWrappers); i > 0; i-- { - fn = opts.SubWrappers[i-1](fn) - } - - if s.wg != nil { - s.wg.Add(1) - } - - go func() { - if s.wg != nil { - defer s.wg.Done() - } - - results <- fn(ctx, &rpcMessage{ - topic: sb.topic, - contentType: ct, - payload: req.Interface(), - }) - }() - } - - var errors []string - - for i := 0; i < len(sb.handlers); i++ { - if err := <-results; err != nil { - errors = append(errors, err.Error()) - } - } - - if len(errors) > 0 { - return fmt.Errorf("subscriber error: %s", strings.Join(errors, "\n")) - } - - return nil - } -} - func (s *subscriber) Topic() string { return s.topic } diff --git a/util/mux/mux.go b/util/mux/mux.go index 4741bd18..741dafcd 100644 --- a/util/mux/mux.go +++ b/util/mux/mux.go @@ -22,6 +22,13 @@ var ( once sync.Once ) +func (s *Server) ProcessMessage(ctx context.Context, msg server.Message) error { + if msg.Topic() == s.Name { + return server.DefaultRouter.ProcessMessage(ctx, msg) + } + return s.Proxy.ProcessMessage(ctx, msg) +} + func (s *Server) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error { if req.Service() == s.Name { return server.DefaultRouter.ServeRequest(ctx, req, rsp) From 9095b99f6bc8dcbff48a02002812a1f3961bfe26 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Mon, 25 Nov 2019 18:56:00 +0000 Subject: [PATCH 246/344] Token has been stripped; Headers are encrypted --- tunnel/crypto.go | 16 +++++++------- tunnel/default.go | 42 ++++++++++++++--------------------- tunnel/listener.go | 4 ++++ tunnel/session.go | 55 ++++++++++++++++++++++++++++++---------------- 4 files changed, 65 insertions(+), 52 deletions(-) diff --git a/tunnel/crypto.go b/tunnel/crypto.go index f34f9c15..ba0d5057 100644 --- a/tunnel/crypto.go +++ b/tunnel/crypto.go @@ -8,6 +8,14 @@ import ( "io" ) +// hash hahes the data into 32 bytes key and returns it +// hash uses sha256 underneath to hash the supplied key +func hash(key string) []byte { + hasher := sha256.New() + hasher.Write([]byte(key)) + return hasher.Sum(nil) +} + // Encrypt encrypts data and returns the encrypted data func Encrypt(data []byte, key string) ([]byte, error) { // generate a new AES cipher using our 32 byte key @@ -62,11 +70,3 @@ func Decrypt(data []byte, key string) ([]byte, error) { return plaintext, nil } - -// hash hahes the data into 32 bytes key and returns it -// hash uses sha256 underneath to hash the supplied key -func hash(key string) []byte { - hasher := sha256.New() - hasher.Write([]byte(key)) - return hasher.Sum(nil) -} diff --git a/tunnel/default.go b/tunnel/default.go index adf4bb6d..72963f0c 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -30,7 +30,7 @@ type tun struct { // the unique id for this tunnel id string - // tunnel token for authentication + // tunnel token for session encryption token string // to indicate if we're connected or not @@ -119,6 +119,7 @@ func (t *tun) newSession(channel, sessionId string) (*session, bool) { tunnel: t.id, channel: channel, session: sessionId, + token: t.token, closed: make(chan bool), recv: make(chan *message, 128), send: t.send, @@ -159,7 +160,6 @@ func (t *tun) announce(channel, session string, link *link) { "Micro-Tunnel-Channel": channel, "Micro-Tunnel-Session": session, "Micro-Tunnel-Link": link.id, - "Micro-Tunnel-Token": t.token, }, } @@ -292,9 +292,6 @@ func (t *tun) process() { // set the session id newMsg.Header["Micro-Tunnel-Session"] = msg.session - // set the tunnel token - newMsg.Header["Micro-Tunnel-Token"] = t.token - // send the message via the interface t.RLock() @@ -447,14 +444,11 @@ func (t *tun) listen(link *link) { return } - // always ensure we have the correct auth token - // TODO: segment the tunnel based on token - // e.g use it as the basis - token := msg.Header["Micro-Tunnel-Token"] - if token != t.token { - log.Debugf("Tunnel link %s received invalid token %s", token) - return - } + // TODO: figure out network authentication + // for now we use tunnel token to encrypt/decrypt + // session communication, but we will probably need + // some sort of network authentication (token) to avoid + // having rogue actors spamming the network // message type mtype := msg.Header["Micro-Tunnel"] @@ -702,9 +696,8 @@ func (t *tun) discover(link *link) { // send a discovery message to all links if err := link.Send(&transport.Message{ Header: map[string]string{ - "Micro-Tunnel": "discover", - "Micro-Tunnel-Id": t.id, - "Micro-Tunnel-Token": t.token, + "Micro-Tunnel": "discover", + "Micro-Tunnel-Id": t.id, }, }); err != nil { log.Debugf("Tunnel failed to send discover to link %s: %v", link.id, err) @@ -733,9 +726,8 @@ func (t *tun) keepalive(link *link) { log.Debugf("Tunnel sending keepalive to link: %v", link.Remote()) if err := link.Send(&transport.Message{ Header: map[string]string{ - "Micro-Tunnel": "keepalive", - "Micro-Tunnel-Id": t.id, - "Micro-Tunnel-Token": t.token, + "Micro-Tunnel": "keepalive", + "Micro-Tunnel-Id": t.id, }, }); err != nil { log.Debugf("Error sending keepalive to link %v: %v", link.Remote(), err) @@ -765,9 +757,8 @@ func (t *tun) setupLink(node string) (*link, error) { // send the first connect message if err := link.Send(&transport.Message{ Header: map[string]string{ - "Micro-Tunnel": "connect", - "Micro-Tunnel-Id": t.id, - "Micro-Tunnel-Token": t.token, + "Micro-Tunnel": "connect", + "Micro-Tunnel-Id": t.id, }, }); err != nil { return nil, err @@ -901,9 +892,8 @@ func (t *tun) close() error { for node, link := range t.links { link.Send(&transport.Message{ Header: map[string]string{ - "Micro-Tunnel": "close", - "Micro-Tunnel-Id": t.id, - "Micro-Tunnel-Token": t.token, + "Micro-Tunnel": "close", + "Micro-Tunnel-Id": t.id, }, }) link.Close() @@ -1157,6 +1147,8 @@ func (t *tun) Listen(channel string, opts ...ListenOption) (Listener, error) { tl := &tunListener{ channel: channel, + // tunnel token + token: t.token, // the accept channel accept: make(chan *session, 128), // the channel to close diff --git a/tunnel/listener.go b/tunnel/listener.go index c893297d..cc207d70 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -10,6 +10,8 @@ import ( type tunListener struct { // address of the listener channel string + // token is the tunnel token + token string // the accept channel accept chan *session // the channel to close @@ -78,6 +80,8 @@ func (t *tunListener) process() { channel: m.channel, // the session id session: m.session, + // tunnel token + token: t.token, // is loopback conn loopback: m.loopback, // the link the message was received on diff --git a/tunnel/session.go b/tunnel/session.go index 09042fd1..4b8721aa 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -1,6 +1,7 @@ package tunnel import ( + "encoding/hex" "errors" "io" "time" @@ -17,6 +18,8 @@ type session struct { channel string // the session id based on Micro.Tunnel-Session session string + // token is the session token + token string // closed closed chan bool // remote addr @@ -301,16 +304,10 @@ func (s *session) Send(m *transport.Message) error { // no op } - // get the token - token, ok := m.Header["Micro-Tunnel-Token"] - if !ok { - // TODO: should we continue or return error - log.Debugf("no token found, insecure channel") - } - // encrypt the transport message payload - body, err := Encrypt(m.Body, token+s.channel+s.session) + body, err := Encrypt(m.Body, s.token+s.channel+s.session) if err != nil { + log.Debugf("failed to encrypt message body: %v", err) return err } @@ -320,9 +317,16 @@ func (s *session) Send(m *transport.Message) error { Body: body, } + // encrypt all the headers for k, v := range m.Header { - // TODO: should we also encrypt headers? - data.Header[k] = v + // encrypt the transport message payload + val, err := Encrypt([]byte(v), s.token+s.channel+s.session) + if err != nil { + log.Debugf("failed to encrypt message header %s: %v", k, err) + return err + } + // hex encode the encrypted header value + data.Header[k] = hex.EncodeToString(val) } // create a new message @@ -366,22 +370,35 @@ func (s *session) Recv(m *transport.Message) error { default: } - // TODO: if we encrypt headers we will have to decrypt them here - token, ok := msg.data.Header["Micro-Tunnel-Token"] - if !ok { - // TODO: should we continue or return error - log.Debugf("no token found, insecure channel") - } - - log.Tracef("Received %+v from recv backlog", msg) + //log.Tracef("Received %+v from recv backlog", msg) + log.Debugf("Received %+v from recv backlog", msg) // decrypt the received payload using the token - body, err := Decrypt(msg.data.Body, token+s.channel+s.session) + body, err := Decrypt(msg.data.Body, s.token+s.channel+s.session) if err != nil { + log.Debugf("failed to decrypt message body: %v", err) return err } msg.data.Body = body + // encrypt all the headers + for k, v := range msg.data.Header { + // hex decode the header values + h, err := hex.DecodeString(v) + if err != nil { + log.Debugf("failed to decode message header %s: %v", k, err) + return err + } + // encrypt the transport message payload + val, err := Decrypt([]byte(h), s.token+s.channel+s.session) + if err != nil { + log.Debugf("failed to decrypt message header %s: %v", k, err) + return err + } + // hex encode the encrypted header value + msg.data.Header[k] = string(val) + } + // set message *m = *msg.data // return nil From 9763820c75c17df2578bed1458852cbdc69209bc Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Mon, 25 Nov 2019 22:02:24 +0300 Subject: [PATCH 247/344] grpc client goroutine leak fix Signed-off-by: Vasiliy Tolstov --- client/grpc/stream.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/client/grpc/stream.go b/client/grpc/stream.go index af919e46..c6b38c15 100644 --- a/client/grpc/stream.go +++ b/client/grpc/stream.go @@ -43,14 +43,12 @@ func (g *grpcStream) Send(msg interface{}) error { func (g *grpcStream) Recv(msg interface{}) (err error) { defer g.setError(err) if err = g.stream.RecvMsg(msg); err != nil { - if err == io.EOF { - // #202 - inconsistent gRPC stream behavior - // the only way to tell if the stream is done is when we get a EOF on the Recv - // here we should close the underlying gRPC ClientConn - closeErr := g.conn.Close() - if closeErr != nil { - err = closeErr - } + // #202 - inconsistent gRPC stream behavior + // the only way to tell if the stream is done is when we get a EOF on the Recv + // here we should close the underlying gRPC ClientConn + closeErr := g.conn.Close() + if err == io.EOF && closeErr != nil { + err = closeErr } } return From d41185eb84bd6573981e777c840faa389cba3501 Mon Sep 17 00:00:00 2001 From: Sumanth Chinthagunta Date: Mon, 25 Nov 2019 18:42:24 -0800 Subject: [PATCH 248/344] go-micro docker now includes unprivileged user --- Dockerfile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 975cca65..4d993447 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,13 @@ FROM golang:1.13-alpine + +RUN mkdir /user && \ + echo 'nobody:x:65534:65534:nobody:/:' > /user/passwd && \ + echo 'nobody:x:65534:' > /user/group + ENV GO111MODULE=on -RUN apk --no-cache add make git gcc libtool musl-dev +RUN apk --no-cache add make git gcc libtool musl-dev ca-certificates && \ + rm -rf /var/cache/apk/* /tmp/* + WORKDIR / -COPY go.mod . -COPY go.sum . +COPY ./go.mod ./go.sum ./ RUN go mod download && rm go.mod go.sum From d2eba3f8f9fb6a0f96c57d0841a814ee45a169fc Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Tue, 26 Nov 2019 11:17:32 +0000 Subject: [PATCH 249/344] Create Bug Report Issue Template To encourage users to provide context with bug reports --- .github/ISSUE_TEMPLATE/bug_report.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..40026657 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug report +about: For reporting bugs in go-micro +title: "[BUG]" +labels: '' +assignees: '' + +--- + +**Describe the bug** + +1. What are you trying to do? +2. What did you expect to happen? +3. What happens instead? + + +**How to reproduce the bug:** + +If possible, please include a minimal code snippet here. + +**Environment:** +``` +please paste `go env` output here +``` From 39bf71376a338681d6ebabe30a1bd3898a219d2e Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Tue, 26 Nov 2019 11:48:14 +0000 Subject: [PATCH 250/344] Add some more issue templates (#987) * Add some more issue templates * Update bug_report.md * Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .../feature-request---enhancement.md | 17 +++++++++++++++++ .github/ISSUE_TEMPLATE/question.md | 14 ++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/feature-request---enhancement.md create mode 100644 .github/ISSUE_TEMPLATE/question.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 40026657..1899438a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -13,12 +13,12 @@ assignees: '' 2. What did you expect to happen? 3. What happens instead? - **How to reproduce the bug:** If possible, please include a minimal code snippet here. **Environment:** +Go Version: please paste `go version` output here ``` please paste `go env` output here ``` diff --git a/.github/ISSUE_TEMPLATE/feature-request---enhancement.md b/.github/ISSUE_TEMPLATE/feature-request---enhancement.md new file mode 100644 index 00000000..459817f4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request---enhancement.md @@ -0,0 +1,17 @@ +--- +name: Feature request / Enhancement +about: If you have a need not served by go-micro +title: "[FEATURE]" +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 00000000..1daf48b6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,14 @@ +--- +name: Question +about: Ask a question about go-micro +title: '' +labels: '' +assignees: '' + +--- + +Before asking, please check if your question has already been answered: + +1. Check the documentation - https://micro.mu/docs/ +2. Check the examples and plugins - https://github.com/micro/examples & https://github.com/micro/go-plugins +3. Search existing issues From b06854b0d586a74d5b0f1aa45f19403613418ffc Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 26 Nov 2019 13:49:52 +0000 Subject: [PATCH 251/344] Change the k8s runtime notifier update to get the deployment and update build --- runtime/kubernetes/client/kubernetes.go | 12 - runtime/kubernetes/kubernetes.go | 309 +++++++++++++----------- runtime/kubernetes/service.go | 4 + 3 files changed, 166 insertions(+), 159 deletions(-) diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index e75862f8..677a2214 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -2,9 +2,7 @@ package client import ( - "strconv" "strings" - "time" "github.com/micro/go-micro/util/log" ) @@ -94,16 +92,6 @@ func NewDeployment(name, version string) *Deployment { Annotations: map[string]string{}, } - // TODO: we need to figure out this version stuff - // might have to add Build to runtime.Service - buildTime, err := strconv.ParseInt(version, 10, 64) - if err == nil { - buildUnixTimeUTC := time.Unix(buildTime, 0) - Metadata.Annotations["build"] = buildUnixTimeUTC.Format(time.RFC3339) - } else { - log.Tracef("could not parse build: %v", err) - } - // enable go modules by default env := EnvVar{ Name: "GO111MODULE", diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 91b224bc..ccac8ed4 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -4,7 +4,6 @@ package kubernetes import ( "errors" "fmt" - "strconv" "sync" "time" @@ -42,72 +41,6 @@ type kubernetes struct { client client.Kubernetes } -// NewRuntime creates new kubernetes runtime -func NewRuntime(opts ...runtime.Option) runtime.Runtime { - // get default options - options := runtime.Options{} - - // apply requested options - for _, o := range opts { - o(&options) - } - - // kubernetes client - client := client.NewClientInCluster() - - return &kubernetes{ - options: options, - closed: make(chan bool), - queue: make(chan *task, 128), - client: client, - } -} - -// Init initializes runtime options -func (k *kubernetes) Init(opts ...runtime.Option) error { - k.Lock() - defer k.Unlock() - - for _, o := range opts { - o(&k.options) - } - - return nil -} - -// Creates a service -func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) error { - k.Lock() - defer k.Unlock() - - var options runtime.CreateOptions - for _, o := range opts { - o(&options) - } - - // quickly prevalidate the name and version - name := s.Name - if len(s.Version) > 0 { - name = name + "-" + s.Version - } - - // format as we'll format in the deployment - name = client.Format(name) - - // create new kubernetes micro service - service := newService(s, options) - - log.Debugf("Runtime queueing service %s version %s for start action", service.Name, service.Version) - - // push into start queue - k.queue <- &task{ - action: start, - service: service, - } - - return nil -} - // getService queries kubernetes for micro service // NOTE: this function is not thread-safe func (k *kubernetes) getService(labels map[string]string) ([]*runtime.Service, error) { @@ -117,6 +50,8 @@ func (k *kubernetes) getService(labels map[string]string) ([]*runtime.Service, e Kind: "service", Value: serviceList, } + + // get the service from k8s if err := k.client.Get(r, labels); err != nil { return nil, err } @@ -127,6 +62,8 @@ func (k *kubernetes) getService(labels map[string]string) ([]*runtime.Service, e Kind: "deployment", Value: depList, } + + // get the deployment from k8s if err := k.client.Get(d, labels); err != nil { return nil, err } @@ -217,6 +154,139 @@ func (k *kubernetes) getService(labels map[string]string) ([]*runtime.Service, e return services, nil } +// run runs the runtime management loop +func (k *kubernetes) run(events <-chan runtime.Event) { + t := time.NewTicker(time.Second * 10) + defer t.Stop() + + for { + select { + case <-t.C: + // TODO: figure out what to do here + // - do we even need the ticker for k8s services? + case task := <-k.queue: + // The task queue is used to take actions e.g (CRUD - R) + switch task.action { + case start: + log.Debugf("Runtime starting new service: %s", task.service.Name) + if err := task.service.Start(k.client); err != nil { + log.Debugf("Runtime failed to start service %s: %v", task.service.Name, err) + continue + } + case stop: + log.Debugf("Runtime stopping service: %s", task.service.Name) + if err := task.service.Stop(k.client); err != nil { + log.Debugf("Runtime failed to stop service %s: %v", task.service.Name, err) + continue + } + case update: + log.Debugf("Runtime updating service: %s", task.service.Name) + if err := task.service.Update(k.client); err != nil { + log.Debugf("Runtime failed to update service %s: %v", task.service.Name, err) + continue + } + default: + log.Debugf("Runtime received unknown action for service: %s", task.service.Name) + } + case event := <-events: + // NOTE: we only handle Update events for now + log.Debugf("Runtime received notification event: %v", event) + switch event.Type { + case runtime.Update: + // only process if there's an actual service + // we do not update all the things individually + if len(event.Service) == 0 { + continue + } + + // set the default labels + labels := map[string]string{ + "micro": "service", + "name": event.Service, + } + + if len(event.Version) > 0 { + labels["version"] = event.Version + } + + // get the deployment status + deployed := new(client.DeploymentList) + + // get the existing service rather than creating a new one + err := k.client.Get(&client.Resource{ + Kind: "deployment", + Value: deployed, + }, labels) + + if err != nil { + log.Debugf("Runtime update failed to get service %s: %v", event.Service, err) + continue + } + + // technically we should not receive multiple versions but hey ho + for _, service := range deployed.Items { + // update build time annotation + service.Spec.Template.Metadata.Annotations["build"] = event.Timestamp.Format(time.RFC3339) + + log.Debugf("Runtime updating service: %s", event.Service) + if err := k.client.Update(deploymentResource(&service)); err != nil { + log.Debugf("Runtime failed to update service %s: %v", event.Service, err) + continue + } + } + } + case <-k.closed: + log.Debugf("Runtime stopped") + return + } + } +} + +// Init initializes runtime options +func (k *kubernetes) Init(opts ...runtime.Option) error { + k.Lock() + defer k.Unlock() + + for _, o := range opts { + o(&k.options) + } + + return nil +} + +// Creates a service +func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) error { + k.Lock() + defer k.Unlock() + + var options runtime.CreateOptions + for _, o := range opts { + o(&options) + } + + // quickly prevalidate the name and version + name := s.Name + if len(s.Version) > 0 { + name = name + "-" + s.Version + } + + // format as we'll format in the deployment + name = client.Format(name) + + // create new kubernetes micro service + service := newService(s, options) + + log.Debugf("Runtime queueing service %s version %s for start action", service.Name, service.Version) + + // push into start queue + k.queue <- &task{ + action: start, + service: service, + } + + return nil +} + // Read returns all instances of given service func (k *kubernetes) Read(name string, opts ...runtime.ReadOption) ([]*runtime.Service, error) { k.Lock() @@ -267,18 +337,11 @@ func (k *kubernetes) List() ([]*runtime.Service, error) { // Update the service in place func (k *kubernetes) Update(s *runtime.Service) error { - // parse version into human readable timestamp - updateTimeStamp, err := strconv.ParseInt(s.Version, 10, 64) - if err != nil { - return err - } - unixTimeUTC := time.Unix(updateTimeStamp, 0) - // create new kubernetes micro service service := newService(s, runtime.CreateOptions{}) // update build time annotation - service.kdeploy.Spec.Template.Metadata.Annotations["build"] = unixTimeUTC.Format(time.RFC3339) + service.kdeploy.Spec.Template.Metadata.Annotations["build"] = time.Now().Format(time.RFC3339) log.Debugf("Runtime queueing service %s for update action", service.Name) @@ -291,7 +354,7 @@ func (k *kubernetes) Update(s *runtime.Service) error { return nil } -// Remove a service +// Delete removes a service func (k *kubernetes) Delete(s *runtime.Service) error { k.Lock() defer k.Unlock() @@ -310,76 +373,7 @@ func (k *kubernetes) Delete(s *runtime.Service) error { return nil } -// run runs the runtime management loop -func (k *kubernetes) run(events <-chan runtime.Event) { - t := time.NewTicker(time.Second * 10) - defer t.Stop() - - for { - select { - case <-t.C: - // TODO: figure out what to do here - // - do we even need the ticker for k8s services? - case task := <-k.queue: - switch task.action { - case start: - log.Debugf("Runtime starting new service: %s", task.service.Name) - if err := task.service.Start(k.client); err != nil { - log.Debugf("Runtime failed to start service %s: %v", task.service.Name, err) - continue - } - case stop: - log.Debugf("Runtime stopping service: %s", task.service.Name) - if err := task.service.Stop(k.client); err != nil { - log.Debugf("Runtime failed to stop service %s: %v", task.service.Name, err) - continue - } - case update: - log.Debugf("Runtime updating service: %s", task.service.Name) - if err := task.service.Update(k.client); err != nil { - log.Debugf("Runtime failed to update service %s: %v", task.service.Name, err) - continue - } - default: - log.Debugf("Runtime received unknown action for service: %s", task.service.Name) - } - case event := <-events: - // NOTE: we only handle Update events for now - log.Debugf("Runtime received notification event: %v", event) - switch event.Type { - case runtime.Update: - // parse returned response to timestamp - updateTimeStamp, err := strconv.ParseInt(event.Version, 10, 64) - if err != nil { - log.Debugf("Runtime error parsing update build time: %v", err) - continue - } - unixTimeUTC := time.Unix(updateTimeStamp, 0) - if len(event.Service) > 0 { - s := &runtime.Service{ - Name: event.Service, - Version: event.Version, - } - // create new kubernetes micro service - service := newService(s, runtime.CreateOptions{}) - // update build time annotation - service.kdeploy.Spec.Template.Metadata.Annotations["build"] = unixTimeUTC.Format(time.RFC3339) - - log.Debugf("Runtime updating service: %s", service.Name) - if err := service.Update(k.client); err != nil { - log.Debugf("Runtime failed to update service %s: %v", service.Name, err) - continue - } - } - } - case <-k.closed: - log.Debugf("Runtime stopped") - return - } - } -} - -// starts the runtime +// Start starts the runtime func (k *kubernetes) Start() error { k.Lock() defer k.Unlock() @@ -408,7 +402,7 @@ func (k *kubernetes) Start() error { return nil } -// Shutdown the runtime +// Stop shuts down the runtime func (k *kubernetes) Stop() error { k.Lock() defer k.Unlock() @@ -437,3 +431,24 @@ func (k *kubernetes) Stop() error { func (k *kubernetes) String() string { return "kubernetes" } + +// NewRuntime creates new kubernetes runtime +func NewRuntime(opts ...runtime.Option) runtime.Runtime { + // get default options + options := runtime.Options{} + + // apply requested options + for _, o := range opts { + o(&options) + } + + // kubernetes client + client := client.NewClientInCluster() + + return &kubernetes{ + options: options, + closed: make(chan bool), + queue: make(chan *task, 128), + client: client, + } +} diff --git a/runtime/kubernetes/service.go b/runtime/kubernetes/service.go index 2a73071c..1fcb4029 100644 --- a/runtime/kubernetes/service.go +++ b/runtime/kubernetes/service.go @@ -2,6 +2,7 @@ package kubernetes import ( "strings" + "time" "github.com/micro/go-micro/runtime" "github.com/micro/go-micro/runtime/kubernetes/client" @@ -34,6 +35,9 @@ func newService(s *runtime.Service, c runtime.CreateOptions) *service { kdeploy.Metadata.Annotations["owner"] = "micro" kdeploy.Metadata.Annotations["group"] = "micro" + // set a build timestamp to the current time + kdeploy.Metadata.Annotations["build"] = time.Now().Format(time.RFC3339) + // define the environment values used by the container env := make([]client.EnvVar, 0, len(c.Env)) for _, evar := range c.Env { From 8b63df7a983e7d6ac3b3fc40068f5885f4e610de Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 26 Nov 2019 13:53:33 +0000 Subject: [PATCH 252/344] regenerate the protos --- agent/proto/bot.pb.go | 76 +++--- agent/proto/{bot.micro.go => bot.pb.micro.go} | 28 +-- api/proto/api.pb.go | 96 ++++---- api/proto/{api.micro.go => api.pb.micro.go} | 22 +- broker/service/proto/broker.pb.go | 191 +++------------ .../{broker.micro.go => broker.pb.micro.go} | 2 +- client/proto/client.pb.go | 228 ++---------------- .../{client.micro.go => client.pb.micro.go} | 2 +- debug/proto/debug.pb.go | 151 ++---------- .../{debug.micro.go => debug.pb.micro.go} | 2 +- network/proto/network.pb.go | 216 ----------------- .../{network.micro.go => network.pb.micro.go} | 0 registry/service/proto/registry.pb.go | 116 ++++----- ...registry.micro.go => registry.pb.micro.go} | 0 router/proto/router.pb.go | 145 +++++------ .../{router.micro.go => router.pb.micro.go} | 2 +- server/proto/server.pb.go | 153 ++---------- .../{server.micro.go => server.pb.micro.go} | 2 +- store/service/proto/store.pb.go | 201 --------------- .../{store.micro.go => store.pb.micro.go} | 0 20 files changed, 342 insertions(+), 1291 deletions(-) rename agent/proto/{bot.micro.go => bot.pb.micro.go} (85%) rename api/proto/{api.micro.go => api.pb.micro.go} (59%) rename broker/service/proto/{broker.micro.go => broker.pb.micro.go} (98%) rename client/proto/{client.micro.go => client.pb.micro.go} (98%) rename debug/proto/{debug.micro.go => debug.pb.micro.go} (97%) rename network/proto/{network.micro.go => network.pb.micro.go} (100%) rename registry/service/proto/{registry.micro.go => registry.pb.micro.go} (100%) rename router/proto/{router.micro.go => router.pb.micro.go} (99%) rename server/proto/{server.micro.go => server.pb.micro.go} (97%) rename store/service/proto/{store.micro.go => store.pb.micro.go} (100%) diff --git a/agent/proto/bot.pb.go b/agent/proto/bot.pb.go index f36d9f4a..b51da305 100644 --- a/agent/proto/bot.pb.go +++ b/agent/proto/bot.pb.go @@ -1,11 +1,13 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/micro/go-bot/proto/bot.proto +// source: github.com/micro/go-micro/agent/proto/bot.proto package go_micro_bot -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 @@ -16,7 +18,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.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type HelpRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -28,16 +30,17 @@ func (m *HelpRequest) Reset() { *m = HelpRequest{} } func (m *HelpRequest) String() string { return proto.CompactTextString(m) } func (*HelpRequest) ProtoMessage() {} func (*HelpRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_bot_654832eab83ed4b5, []int{0} + return fileDescriptor_018e8d5b14a89d12, []int{0} } + func (m *HelpRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HelpRequest.Unmarshal(m, b) } func (m *HelpRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_HelpRequest.Marshal(b, m, deterministic) } -func (dst *HelpRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_HelpRequest.Merge(dst, src) +func (m *HelpRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_HelpRequest.Merge(m, src) } func (m *HelpRequest) XXX_Size() int { return xxx_messageInfo_HelpRequest.Size(m) @@ -60,16 +63,17 @@ func (m *HelpResponse) Reset() { *m = HelpResponse{} } func (m *HelpResponse) String() string { return proto.CompactTextString(m) } func (*HelpResponse) ProtoMessage() {} func (*HelpResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bot_654832eab83ed4b5, []int{1} + return fileDescriptor_018e8d5b14a89d12, []int{1} } + func (m *HelpResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HelpResponse.Unmarshal(m, b) } func (m *HelpResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_HelpResponse.Marshal(b, m, deterministic) } -func (dst *HelpResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_HelpResponse.Merge(dst, src) +func (m *HelpResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_HelpResponse.Merge(m, src) } func (m *HelpResponse) XXX_Size() int { return xxx_messageInfo_HelpResponse.Size(m) @@ -105,16 +109,17 @@ func (m *ExecRequest) Reset() { *m = ExecRequest{} } func (m *ExecRequest) String() string { return proto.CompactTextString(m) } func (*ExecRequest) ProtoMessage() {} func (*ExecRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_bot_654832eab83ed4b5, []int{2} + return fileDescriptor_018e8d5b14a89d12, []int{2} } + func (m *ExecRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecRequest.Unmarshal(m, b) } func (m *ExecRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_ExecRequest.Marshal(b, m, deterministic) } -func (dst *ExecRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_ExecRequest.Merge(dst, src) +func (m *ExecRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExecRequest.Merge(m, src) } func (m *ExecRequest) XXX_Size() int { return xxx_messageInfo_ExecRequest.Size(m) @@ -144,16 +149,17 @@ func (m *ExecResponse) Reset() { *m = ExecResponse{} } func (m *ExecResponse) String() string { return proto.CompactTextString(m) } func (*ExecResponse) ProtoMessage() {} func (*ExecResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bot_654832eab83ed4b5, []int{3} + return fileDescriptor_018e8d5b14a89d12, []int{3} } + func (m *ExecResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExecResponse.Unmarshal(m, b) } func (m *ExecResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_ExecResponse.Marshal(b, m, deterministic) } -func (dst *ExecResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_ExecResponse.Merge(dst, src) +func (m *ExecResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExecResponse.Merge(m, src) } func (m *ExecResponse) XXX_Size() int { return xxx_messageInfo_ExecResponse.Size(m) @@ -186,25 +192,25 @@ func init() { } func init() { - proto.RegisterFile("github.com/micro/go-bot/proto/bot.proto", fileDescriptor_bot_654832eab83ed4b5) + proto.RegisterFile("github.com/micro/go-micro/agent/proto/bot.proto", fileDescriptor_018e8d5b14a89d12) } -var fileDescriptor_bot_654832eab83ed4b5 = []byte{ +var fileDescriptor_018e8d5b14a89d12 = []byte{ // 246 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x41, 0x4b, 0xc4, 0x30, - 0x10, 0x85, 0xb7, 0xba, 0xae, 0xec, 0xb4, 0x5e, 0x82, 0x48, 0xdd, 0x53, 0xcd, 0xc5, 0xbd, 0x98, - 0x82, 0x5e, 0x05, 0x0f, 0xa2, 0x78, 0xee, 0x3f, 0x68, 0xba, 0x43, 0x2c, 0x6c, 0x3b, 0x35, 0x99, - 0x82, 0xff, 0xc1, 0x3f, 0x2d, 0x4d, 0x72, 0x08, 0xcb, 0xde, 0xe6, 0x65, 0x86, 0xf7, 0xbe, 0x17, - 0x78, 0x34, 0x3d, 0x7f, 0xcf, 0x5a, 0x75, 0x34, 0xd4, 0x43, 0xdf, 0x59, 0xaa, 0x0d, 0x3d, 0x69, - 0xe2, 0x7a, 0xb2, 0xc4, 0x54, 0x6b, 0x62, 0xe5, 0x27, 0x51, 0x18, 0x52, 0xfe, 0x40, 0x69, 0x62, - 0x79, 0x03, 0xf9, 0x17, 0x1e, 0xa7, 0x06, 0x7f, 0x66, 0x74, 0x2c, 0x3f, 0xa1, 0x08, 0xd2, 0x4d, - 0x34, 0x3a, 0x14, 0xb7, 0x70, 0x35, 0xbb, 0xd6, 0x60, 0x99, 0x55, 0xd9, 0x7e, 0xdb, 0x04, 0x21, - 0x2a, 0xc8, 0x0f, 0xe8, 0x3a, 0xdb, 0x4f, 0xdc, 0xd3, 0x58, 0x5e, 0xf8, 0x5d, 0xfa, 0x24, 0x1f, - 0x20, 0xff, 0xf8, 0xc5, 0x2e, 0xda, 0x0a, 0x01, 0xeb, 0xd6, 0x1a, 0x57, 0x66, 0xd5, 0xe5, 0x7e, - 0xdb, 0xf8, 0x59, 0xbe, 0x42, 0x11, 0x4e, 0x62, 0xd4, 0x1d, 0x6c, 0x2c, 0xba, 0xf9, 0xc8, 0x3e, - 0xab, 0x68, 0xa2, 0x5a, 0x10, 0xd0, 0x5a, 0xb2, 0x31, 0x26, 0x88, 0xe7, 0xbf, 0x0c, 0xae, 0xdf, - 0x69, 0x18, 0xda, 0xf1, 0x20, 0xde, 0x60, 0xbd, 0x40, 0x8b, 0x7b, 0x95, 0x56, 0x53, 0x49, 0xaf, - 0xdd, 0xee, 0xdc, 0x2a, 0x04, 0xcb, 0xd5, 0x62, 0xb0, 0xa0, 0x9c, 0x1a, 0x24, 0x0d, 0x4e, 0x0d, - 0x52, 0x72, 0xb9, 0xd2, 0x1b, 0xff, 0xb5, 0x2f, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x77, - 0xdf, 0x28, 0x85, 0x01, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x50, 0x4d, 0x4b, 0xc4, 0x30, + 0x10, 0xdd, 0xea, 0xba, 0xb2, 0xd3, 0x7a, 0x09, 0x22, 0x75, 0x4f, 0x35, 0xa7, 0xbd, 0x98, 0x80, + 0x5e, 0x05, 0x0f, 0xa2, 0x78, 0xee, 0x3f, 0x68, 0xbb, 0x43, 0x2c, 0x6c, 0x3b, 0x35, 0x99, 0x82, + 0xff, 0xc1, 0x3f, 0x2d, 0x4d, 0x72, 0x08, 0xc5, 0xdb, 0x7b, 0x79, 0xe1, 0x7d, 0x0c, 0x68, 0xd3, + 0xf3, 0xd7, 0xdc, 0xaa, 0x8e, 0x06, 0x3d, 0xf4, 0x9d, 0x25, 0x6d, 0xe8, 0x31, 0x80, 0xc6, 0xe0, + 0xc8, 0x7a, 0xb2, 0xc4, 0xa4, 0x5b, 0x62, 0xe5, 0x91, 0x28, 0x0c, 0x29, 0xaf, 0xab, 0x96, 0x58, + 0xde, 0x40, 0xfe, 0x89, 0xe7, 0xa9, 0xc6, 0xef, 0x19, 0x1d, 0xcb, 0x0f, 0x28, 0x02, 0x75, 0x13, + 0x8d, 0x0e, 0xc5, 0x2d, 0x5c, 0xcd, 0xae, 0x31, 0x58, 0x66, 0x55, 0x76, 0xdc, 0xd7, 0x81, 0x88, + 0x0a, 0xf2, 0x13, 0xba, 0xce, 0xf6, 0x13, 0xf7, 0x34, 0x96, 0x17, 0x5e, 0x4b, 0x9f, 0xe4, 0x03, + 0xe4, 0xef, 0x3f, 0xd8, 0x45, 0x5b, 0x21, 0x60, 0xdb, 0x58, 0xe3, 0xca, 0xac, 0xba, 0x3c, 0xee, + 0x6b, 0x8f, 0xe5, 0x0b, 0x14, 0xe1, 0x4b, 0x8c, 0xba, 0x83, 0x9d, 0x45, 0x37, 0x9f, 0xd9, 0x67, + 0x15, 0x75, 0x64, 0x4b, 0x05, 0xb4, 0x96, 0x6c, 0x8c, 0x09, 0xe4, 0xe9, 0x37, 0x83, 0xeb, 0x37, + 0x1a, 0x86, 0x66, 0x3c, 0x89, 0x57, 0xd8, 0x2e, 0xa5, 0xc5, 0xbd, 0x4a, 0xa7, 0xa9, 0x64, 0xd7, + 0xe1, 0xf0, 0x9f, 0x14, 0x82, 0xe5, 0x66, 0x31, 0x58, 0xaa, 0xac, 0x0d, 0x92, 0x05, 0x6b, 0x83, + 0xb4, 0xb9, 0xdc, 0xb4, 0x3b, 0x7f, 0xda, 0xe7, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0xbd, + 0x39, 0x29, 0x8d, 0x01, 0x00, 0x00, } diff --git a/agent/proto/bot.micro.go b/agent/proto/bot.pb.micro.go similarity index 85% rename from agent/proto/bot.micro.go rename to agent/proto/bot.pb.micro.go index 0a027a82..1c04fe59 100644 --- a/agent/proto/bot.micro.go +++ b/agent/proto/bot.pb.micro.go @@ -1,23 +1,13 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: github.com/micro/go-bot/proto/bot.proto +// source: github.com/micro/go-micro/agent/proto/bot.proto -/* -Package go_micro_bot is a generated protocol buffer package. - -It is generated from these files: - github.com/micro/go-bot/proto/bot.proto - -It has these top-level messages: - HelpRequest - HelpResponse - ExecRequest - ExecResponse -*/ package go_micro_bot -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) import ( context "context" @@ -34,7 +24,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.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package // Reference imports to suppress errors if they are not otherwise used. var _ context.Context @@ -94,12 +84,12 @@ type CommandHandler interface { } func RegisterCommandHandler(s server.Server, hdlr CommandHandler, opts ...server.HandlerOption) error { - type _command interface { + type command interface { Help(ctx context.Context, in *HelpRequest, out *HelpResponse) error Exec(ctx context.Context, in *ExecRequest, out *ExecResponse) error } type Command struct { - _command + command } h := &commandHandler{hdlr} return s.Handle(s.NewHandler(&Command{h}, opts...)) diff --git a/api/proto/api.pb.go b/api/proto/api.pb.go index 3304d4e1..9e912f49 100644 --- a/api/proto/api.pb.go +++ b/api/proto/api.pb.go @@ -3,9 +3,11 @@ package go_api -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 @@ -16,7 +18,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.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type Pair struct { Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` @@ -30,16 +32,17 @@ func (m *Pair) Reset() { *m = Pair{} } func (m *Pair) String() string { return proto.CompactTextString(m) } func (*Pair) ProtoMessage() {} func (*Pair) Descriptor() ([]byte, []int) { - return fileDescriptor_api_17a7876430d97ebd, []int{0} + return fileDescriptor_7b6696ef87ec1943, []int{0} } + func (m *Pair) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Pair.Unmarshal(m, b) } func (m *Pair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Pair.Marshal(b, m, deterministic) } -func (dst *Pair) XXX_Merge(src proto.Message) { - xxx_messageInfo_Pair.Merge(dst, src) +func (m *Pair) XXX_Merge(src proto.Message) { + xxx_messageInfo_Pair.Merge(m, src) } func (m *Pair) XXX_Size() int { return xxx_messageInfo_Pair.Size(m) @@ -83,16 +86,17 @@ func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { - return fileDescriptor_api_17a7876430d97ebd, []int{1} + return fileDescriptor_7b6696ef87ec1943, []int{1} } + func (m *Request) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Request.Unmarshal(m, b) } func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Request.Marshal(b, m, deterministic) } -func (dst *Request) XXX_Merge(src proto.Message) { - xxx_messageInfo_Request.Merge(dst, src) +func (m *Request) XXX_Merge(src proto.Message) { + xxx_messageInfo_Request.Merge(m, src) } func (m *Request) XXX_Size() int { return xxx_messageInfo_Request.Size(m) @@ -167,16 +171,17 @@ func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { - return fileDescriptor_api_17a7876430d97ebd, []int{2} + return fileDescriptor_7b6696ef87ec1943, []int{2} } + func (m *Response) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Response.Unmarshal(m, b) } func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Response.Marshal(b, m, deterministic) } -func (dst *Response) XXX_Merge(src proto.Message) { - xxx_messageInfo_Response.Merge(dst, src) +func (m *Response) XXX_Merge(src proto.Message) { + xxx_messageInfo_Response.Merge(m, src) } func (m *Response) XXX_Size() int { return xxx_messageInfo_Response.Size(m) @@ -230,16 +235,17 @@ func (m *Event) Reset() { *m = Event{} } func (m *Event) String() string { return proto.CompactTextString(m) } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { - return fileDescriptor_api_17a7876430d97ebd, []int{3} + return fileDescriptor_7b6696ef87ec1943, []int{3} } + func (m *Event) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Event.Unmarshal(m, b) } func (m *Event) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Event.Marshal(b, m, deterministic) } -func (dst *Event) XXX_Merge(src proto.Message) { - xxx_messageInfo_Event.Merge(dst, src) +func (m *Event) XXX_Merge(src proto.Message) { + xxx_messageInfo_Event.Merge(m, src) } func (m *Event) XXX_Size() int { return xxx_messageInfo_Event.Size(m) @@ -298,35 +304,35 @@ func init() { } func init() { - proto.RegisterFile("github.com/micro/go-micro/api/proto/api.proto", fileDescriptor_api_17a7876430d97ebd) + proto.RegisterFile("github.com/micro/go-micro/api/proto/api.proto", fileDescriptor_7b6696ef87ec1943) } -var fileDescriptor_api_17a7876430d97ebd = []byte{ - // 410 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0xc1, 0x6e, 0xd4, 0x30, - 0x10, 0x55, 0xe2, 0x24, 0x6d, 0x66, 0x11, 0x42, 0x3e, 0x20, 0x53, 0x2a, 0xb4, 0xca, 0x85, 0x15, - 0x52, 0x13, 0x68, 0x39, 0x20, 0xae, 0xb0, 0x2a, 0xc7, 0xca, 0x7f, 0xe0, 0x6d, 0xac, 0xc4, 0x62, - 0x13, 0x9b, 0xd8, 0xa9, 0xb4, 0x1f, 0xc7, 0x81, 0xcf, 0xe0, 0x6f, 0x90, 0x27, 0xde, 0xdd, 0xb2, - 0x5a, 0x2e, 0x74, 0x6f, 0x2f, 0xf6, 0x9b, 0x37, 0x6f, 0xde, 0x38, 0xf0, 0xb6, 0x51, 0xae, 0x1d, - 0x57, 0xe5, 0xbd, 0xee, 0xaa, 0x4e, 0xdd, 0x0f, 0xba, 0x6a, 0xf4, 0x95, 0x30, 0xaa, 0x32, 0x83, - 0x76, 0xba, 0x12, 0x46, 0x95, 0x88, 0x68, 0xd6, 0xe8, 0x52, 0x18, 0x55, 0xbc, 0x87, 0xe4, 0x4e, - 0xa8, 0x81, 0xbe, 0x00, 0xf2, 0x5d, 0x6e, 0x58, 0x34, 0x8f, 0x16, 0x39, 0xf7, 0x90, 0xbe, 0x84, - 0xec, 0x41, 0xac, 0x47, 0x69, 0x59, 0x3c, 0x27, 0x8b, 0x9c, 0x87, 0xaf, 0xe2, 0x17, 0x81, 0x33, - 0x2e, 0x7f, 0x8c, 0xd2, 0x3a, 0xcf, 0xe9, 0xa4, 0x6b, 0x75, 0x1d, 0x0a, 0xc3, 0x17, 0xa5, 0x90, - 0x18, 0xe1, 0x5a, 0x16, 0xe3, 0x29, 0x62, 0x7a, 0x03, 0x59, 0x2b, 0x45, 0x2d, 0x07, 0x46, 0xe6, - 0x64, 0x31, 0xbb, 0x7e, 0x5d, 0x4e, 0x16, 0xca, 0x20, 0x56, 0x7e, 0xc3, 0xdb, 0x65, 0xef, 0x86, - 0x0d, 0x0f, 0x54, 0xfa, 0x0e, 0x48, 0x23, 0x1d, 0x4b, 0xb0, 0x82, 0x1d, 0x56, 0xdc, 0x4a, 0x37, - 0xd1, 0x3d, 0x89, 0x5e, 0x41, 0x62, 0xb4, 0x75, 0x2c, 0x45, 0xf2, 0xab, 0x43, 0xf2, 0x9d, 0xb6, - 0x81, 0x8d, 0x34, 0xef, 0x71, 0xa5, 0xeb, 0x0d, 0xcb, 0x26, 0x8f, 0x1e, 0xfb, 0x14, 0xc6, 0x61, - 0xcd, 0xce, 0xa6, 0x14, 0xc6, 0x61, 0x7d, 0x71, 0x0b, 0xb3, 0x47, 0xbe, 0x8e, 0xc4, 0x54, 0x40, - 0x8a, 0xc1, 0xe0, 0xac, 0xb3, 0xeb, 0x67, 0xdb, 0xb6, 0x3e, 0x55, 0x3e, 0x5d, 0x7d, 0x8e, 0x3f, - 0x45, 0x17, 0x5f, 0xe1, 0x7c, 0x6b, 0xf7, 0x09, 0x2a, 0x4b, 0xc8, 0x77, 0x73, 0xfc, 0xbf, 0x4c, - 0xf1, 0x33, 0x82, 0x73, 0x2e, 0xad, 0xd1, 0xbd, 0x95, 0xf4, 0x0d, 0x80, 0x75, 0xc2, 0x8d, 0xf6, - 0x8b, 0xae, 0x25, 0xaa, 0xa5, 0xfc, 0xd1, 0x09, 0xfd, 0xb8, 0x5b, 0x5c, 0x8c, 0xc9, 0x5e, 0xee, - 0x93, 0x9d, 0x14, 0x8e, 0x6e, 0x6e, 0x1b, 0x2f, 0xd9, 0xc7, 0x7b, 0xb2, 0x30, 0x8b, 0xdf, 0x11, - 0xa4, 0xcb, 0x07, 0xd9, 0xe3, 0x16, 0x7b, 0xd1, 0xc9, 0x20, 0x82, 0x98, 0x3e, 0x87, 0x58, 0xd5, - 0xe1, 0xed, 0xc5, 0xaa, 0xa6, 0x97, 0x90, 0x3b, 0xd5, 0x49, 0xeb, 0x44, 0x67, 0xd0, 0x0f, 0xe1, - 0xfb, 0x03, 0xfa, 0x61, 0x37, 0x5e, 0xf2, 0xf7, 0xc3, 0xc1, 0x06, 0xff, 0x9a, 0xad, 0x16, 0x4e, - 0xb0, 0x74, 0x6a, 0xea, 0xf1, 0xc9, 0x66, 0x5b, 0x65, 0xf8, 0x83, 0xde, 0xfc, 0x09, 0x00, 0x00, - 0xff, 0xff, 0x7a, 0xb4, 0xd4, 0x8f, 0xcb, 0x03, 0x00, 0x00, +var fileDescriptor_7b6696ef87ec1943 = []byte{ + // 408 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0x4d, 0x8f, 0xd3, 0x30, + 0x10, 0x55, 0xe2, 0x24, 0xbb, 0x99, 0x22, 0x84, 0x7c, 0x40, 0x66, 0x59, 0xa1, 0x2a, 0xa7, 0x0a, + 0xa9, 0x29, 0xec, 0x72, 0x40, 0x5c, 0xa1, 0x5a, 0x8e, 0x2b, 0xff, 0x03, 0x77, 0x63, 0x25, 0x16, + 0x4d, 0x1c, 0x62, 0xa7, 0x52, 0x7f, 0x1c, 0x07, 0x7e, 0x06, 0xff, 0x06, 0x79, 0xec, 0x7e, 0x50, + 0x95, 0x0b, 0xf4, 0xf6, 0x62, 0xbf, 0x79, 0xf3, 0xe6, 0x8d, 0x03, 0xf3, 0x5a, 0xd9, 0x66, 0x5c, + 0x95, 0x4f, 0xba, 0x5d, 0xb4, 0xea, 0x69, 0xd0, 0x8b, 0x5a, 0xcf, 0x3d, 0x10, 0xbd, 0x5a, 0xf4, + 0x83, 0xb6, 0x88, 0x4a, 0x44, 0x34, 0xab, 0x75, 0x29, 0x7a, 0x55, 0xbc, 0x83, 0xe4, 0x51, 0xa8, + 0x81, 0xbe, 0x00, 0xf2, 0x4d, 0x6e, 0x59, 0x34, 0x8d, 0x66, 0x39, 0x77, 0x90, 0xbe, 0x84, 0x6c, + 0x23, 0xd6, 0xa3, 0x34, 0x2c, 0x9e, 0x92, 0x59, 0xce, 0xc3, 0x57, 0xf1, 0x93, 0xc0, 0x15, 0x97, + 0xdf, 0x47, 0x69, 0xac, 0xe3, 0xb4, 0xd2, 0x36, 0xba, 0x0a, 0x85, 0xe1, 0x8b, 0x52, 0x48, 0x7a, + 0x61, 0x1b, 0x16, 0xe3, 0x29, 0x62, 0x7a, 0x0f, 0x59, 0x23, 0x45, 0x25, 0x07, 0x46, 0xa6, 0x64, + 0x36, 0xb9, 0x7b, 0x5d, 0x7a, 0x0b, 0x65, 0x10, 0x2b, 0xbf, 0xe2, 0xed, 0xb2, 0xb3, 0xc3, 0x96, + 0x07, 0x2a, 0x7d, 0x0b, 0xa4, 0x96, 0x96, 0x25, 0x58, 0xc1, 0x4e, 0x2b, 0x1e, 0xa4, 0xf5, 0x74, + 0x47, 0xa2, 0x73, 0x48, 0x7a, 0x6d, 0x2c, 0x4b, 0x91, 0xfc, 0xea, 0x94, 0xfc, 0xa8, 0x4d, 0x60, + 0x23, 0xcd, 0x79, 0x5c, 0xe9, 0x6a, 0xcb, 0x32, 0xef, 0xd1, 0x61, 0x97, 0xc2, 0x38, 0xac, 0xd9, + 0x95, 0x4f, 0x61, 0x1c, 0xd6, 0x37, 0x0f, 0x30, 0x39, 0xf2, 0x75, 0x26, 0xa6, 0x02, 0x52, 0x0c, + 0x06, 0x67, 0x9d, 0xdc, 0x3d, 0xdb, 0xb5, 0x75, 0xa9, 0x72, 0x7f, 0xf5, 0x29, 0xfe, 0x18, 0xdd, + 0x7c, 0x81, 0xeb, 0x9d, 0xdd, 0xff, 0x50, 0x59, 0x42, 0xbe, 0x9f, 0xe3, 0xdf, 0x65, 0x8a, 0x1f, + 0x11, 0x5c, 0x73, 0x69, 0x7a, 0xdd, 0x19, 0x49, 0xdf, 0x00, 0x18, 0x2b, 0xec, 0x68, 0x3e, 0xeb, + 0x4a, 0xa2, 0x5a, 0xca, 0x8f, 0x4e, 0xe8, 0x87, 0xfd, 0xe2, 0x62, 0x4c, 0xf6, 0xf6, 0x90, 0xac, + 0x57, 0x38, 0xbb, 0xb9, 0x5d, 0xbc, 0xe4, 0x10, 0xef, 0xc5, 0xc2, 0x2c, 0x7e, 0x45, 0x90, 0x2e, + 0x37, 0xb2, 0xc3, 0x2d, 0x76, 0xa2, 0x95, 0x41, 0x04, 0x31, 0x7d, 0x0e, 0xb1, 0xaa, 0xc2, 0xdb, + 0x8b, 0x55, 0x45, 0x6f, 0x21, 0xb7, 0xaa, 0x95, 0xc6, 0x8a, 0xb6, 0x47, 0x3f, 0x84, 0x1f, 0x0e, + 0xe8, 0xfb, 0xfd, 0x78, 0xc9, 0x9f, 0x0f, 0x07, 0x1b, 0xfc, 0x6d, 0xb6, 0x4a, 0x58, 0xc1, 0x52, + 0xdf, 0xd4, 0xe1, 0x8b, 0xcd, 0xb6, 0xca, 0xf0, 0x07, 0xbd, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff, + 0x97, 0xf3, 0x59, 0x6e, 0xd1, 0x03, 0x00, 0x00, } diff --git a/api/proto/api.micro.go b/api/proto/api.pb.micro.go similarity index 59% rename from api/proto/api.micro.go rename to api/proto/api.pb.micro.go index b7b01f8b..a05f98b1 100644 --- a/api/proto/api.micro.go +++ b/api/proto/api.pb.micro.go @@ -1,23 +1,13 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. // source: github.com/micro/go-micro/api/proto/api.proto -/* -Package go_api is a generated protocol buffer package. - -It is generated from these files: - github.com/micro/go-micro/api/proto/api.proto - -It has these top-level messages: - Pair - Request - Response - Event -*/ package go_api -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 @@ -28,4 +18,4 @@ 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 diff --git a/broker/service/proto/broker.pb.go b/broker/service/proto/broker.pb.go index b54a5480..e602e4b1 100644 --- a/broker/service/proto/broker.pb.go +++ b/broker/service/proto/broker.pb.go @@ -1,13 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/micro/go-micro/broker/proto/broker.proto +// source: micro/go-micro/broker/service/proto/broker.proto package go_micro_broker import ( - context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" math "math" ) @@ -32,7 +30,7 @@ func (m *Empty) Reset() { *m = Empty{} } func (m *Empty) String() string { return proto.CompactTextString(m) } func (*Empty) ProtoMessage() {} func (*Empty) Descriptor() ([]byte, []int) { - return fileDescriptor_5edf81766900dd99, []int{0} + return fileDescriptor_178fdc60944ff5e5, []int{0} } func (m *Empty) XXX_Unmarshal(b []byte) error { @@ -65,7 +63,7 @@ func (m *PublishRequest) Reset() { *m = PublishRequest{} } func (m *PublishRequest) String() string { return proto.CompactTextString(m) } func (*PublishRequest) ProtoMessage() {} func (*PublishRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5edf81766900dd99, []int{1} + return fileDescriptor_178fdc60944ff5e5, []int{1} } func (m *PublishRequest) XXX_Unmarshal(b []byte) error { @@ -112,7 +110,7 @@ func (m *SubscribeRequest) Reset() { *m = SubscribeRequest{} } func (m *SubscribeRequest) String() string { return proto.CompactTextString(m) } func (*SubscribeRequest) ProtoMessage() {} func (*SubscribeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5edf81766900dd99, []int{2} + return fileDescriptor_178fdc60944ff5e5, []int{2} } func (m *SubscribeRequest) XXX_Unmarshal(b []byte) error { @@ -159,7 +157,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_5edf81766900dd99, []int{3} + return fileDescriptor_178fdc60944ff5e5, []int{3} } func (m *Message) XXX_Unmarshal(b []byte) error { @@ -203,162 +201,29 @@ func init() { } func init() { - proto.RegisterFile("github.com/micro/go-micro/broker/proto/broker.proto", fileDescriptor_5edf81766900dd99) + proto.RegisterFile("micro/go-micro/broker/service/proto/broker.proto", fileDescriptor_178fdc60944ff5e5) } -var fileDescriptor_5edf81766900dd99 = []byte{ - // 309 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xcf, 0x4a, 0xf3, 0x40, - 0x14, 0xc5, 0x3b, 0xed, 0xd7, 0x86, 0xde, 0x7e, 0x68, 0x19, 0x8a, 0x84, 0x6e, 0x8c, 0xc1, 0x45, - 0x36, 0x4e, 0x24, 0xdd, 0xa8, 0x88, 0x0b, 0xb1, 0xe0, 0x42, 0x41, 0xc6, 0x9d, 0xbb, 0x4c, 0x3a, - 0x24, 0xa1, 0x8d, 0x93, 0x4e, 0x66, 0x84, 0xbc, 0x88, 0x2b, 0x1f, 0x56, 0x3a, 0x93, 0xfa, 0xa7, - 0xa1, 0xee, 0xee, 0x49, 0x7e, 0x73, 0xee, 0xe1, 0x5c, 0x98, 0xa5, 0xb9, 0xca, 0x34, 0x23, 0x89, - 0x28, 0xc2, 0x22, 0x4f, 0xa4, 0x08, 0x53, 0x71, 0x66, 0x07, 0x26, 0xc5, 0x92, 0xcb, 0xb0, 0x94, - 0x42, 0x6d, 0x05, 0x31, 0x02, 0x1f, 0xa6, 0x82, 0x18, 0x86, 0xd8, 0xcf, 0xbe, 0x03, 0xfd, 0x79, - 0x51, 0xaa, 0xda, 0x7f, 0x81, 0x83, 0x27, 0xcd, 0x56, 0x79, 0x95, 0x51, 0xbe, 0xd6, 0xbc, 0x52, - 0x78, 0x02, 0x7d, 0x25, 0xca, 0x3c, 0x71, 0x91, 0x87, 0x82, 0x21, 0xb5, 0x02, 0x47, 0xe0, 0x14, - 0xbc, 0xaa, 0xe2, 0x94, 0xbb, 0x5d, 0x0f, 0x05, 0xa3, 0xc8, 0x25, 0x3b, 0x9e, 0xe4, 0xd1, 0xfe, - 0xa7, 0x5b, 0xd0, 0xbf, 0x81, 0xf1, 0xb3, 0x66, 0x55, 0x22, 0x73, 0xc6, 0xff, 0x76, 0x9f, 0x40, - 0x7f, 0xad, 0xb9, 0xb6, 0xde, 0x43, 0x6a, 0x85, 0xff, 0x8e, 0xc0, 0x69, 0x4c, 0xf1, 0x35, 0x0c, - 0x32, 0x1e, 0x2f, 0xb8, 0x74, 0x91, 0xd7, 0x0b, 0x46, 0xd1, 0xe9, 0xbe, 0xf5, 0xe4, 0xde, 0x60, - 0xf3, 0x57, 0x25, 0x6b, 0xda, 0xbc, 0xc1, 0x18, 0xfe, 0x31, 0xb1, 0xa8, 0x8d, 0xfd, 0x7f, 0x6a, - 0xe6, 0xe9, 0x25, 0x8c, 0x7e, 0xa0, 0x78, 0x0c, 0xbd, 0x25, 0xaf, 0x9b, 0x58, 0x9b, 0x71, 0x13, - 0xea, 0x2d, 0x5e, 0x7d, 0x87, 0x32, 0xe2, 0xaa, 0x7b, 0x81, 0xa2, 0x0f, 0x04, 0x83, 0x5b, 0xb3, - 0x15, 0xdf, 0x81, 0xd3, 0xf4, 0x87, 0x8f, 0x5b, 0x91, 0x7e, 0x37, 0x3b, 0x3d, 0x6a, 0x01, 0xf6, - 0x06, 0x1d, 0xfc, 0x00, 0xc3, 0xaf, 0xa6, 0xf0, 0x49, 0x0b, 0xdb, 0x6d, 0x71, 0xba, 0xb7, 0x7c, - 0xbf, 0x73, 0x8e, 0xd8, 0xc0, 0x1c, 0x7d, 0xf6, 0x19, 0x00, 0x00, 0xff, 0xff, 0x25, 0x38, 0xfa, - 0x02, 0x2b, 0x02, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// BrokerClient is the client API for Broker service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type BrokerClient interface { - Publish(ctx context.Context, in *PublishRequest, opts ...grpc.CallOption) (*Empty, error) - Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (Broker_SubscribeClient, error) -} - -type brokerClient struct { - cc *grpc.ClientConn -} - -func NewBrokerClient(cc *grpc.ClientConn) BrokerClient { - return &brokerClient{cc} -} - -func (c *brokerClient) Publish(ctx context.Context, in *PublishRequest, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) - err := c.cc.Invoke(ctx, "/go.micro.broker.Broker/Publish", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *brokerClient) Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (Broker_SubscribeClient, error) { - stream, err := c.cc.NewStream(ctx, &_Broker_serviceDesc.Streams[0], "/go.micro.broker.Broker/Subscribe", opts...) - if err != nil { - return nil, err - } - x := &brokerSubscribeClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Broker_SubscribeClient interface { - Recv() (*Message, error) - grpc.ClientStream -} - -type brokerSubscribeClient struct { - grpc.ClientStream -} - -func (x *brokerSubscribeClient) Recv() (*Message, error) { - m := new(Message) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// BrokerServer is the server API for Broker service. -type BrokerServer interface { - Publish(context.Context, *PublishRequest) (*Empty, error) - Subscribe(*SubscribeRequest, Broker_SubscribeServer) error -} - -func RegisterBrokerServer(s *grpc.Server, srv BrokerServer) { - s.RegisterService(&_Broker_serviceDesc, srv) -} - -func _Broker_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PublishRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BrokerServer).Publish(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.broker.Broker/Publish", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BrokerServer).Publish(ctx, req.(*PublishRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Broker_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SubscribeRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BrokerServer).Subscribe(m, &brokerSubscribeServer{stream}) -} - -type Broker_SubscribeServer interface { - Send(*Message) error - grpc.ServerStream -} - -type brokerSubscribeServer struct { - grpc.ServerStream -} - -func (x *brokerSubscribeServer) Send(m *Message) error { - return x.ServerStream.SendMsg(m) -} - -var _Broker_serviceDesc = grpc.ServiceDesc{ - ServiceName: "go.micro.broker.Broker", - HandlerType: (*BrokerServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Publish", - Handler: _Broker_Publish_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "Subscribe", - Handler: _Broker_Subscribe_Handler, - ServerStreams: true, - }, - }, - Metadata: "github.com/micro/go-micro/broker/proto/broker.proto", +var fileDescriptor_178fdc60944ff5e5 = []byte{ + // 305 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x51, 0x4d, 0x4f, 0xc2, 0x40, + 0x14, 0x64, 0x41, 0x68, 0x78, 0x18, 0x25, 0x1b, 0x62, 0x1a, 0x2e, 0x62, 0xe3, 0x81, 0x8b, 0x5b, + 0x52, 0x2f, 0x6a, 0x8c, 0x07, 0x23, 0x89, 0x07, 0x4d, 0xcc, 0x7a, 0xf3, 0xd6, 0x2d, 0x2f, 0xa5, + 0x81, 0xba, 0x65, 0xb7, 0x25, 0xe9, 0x1f, 0xf1, 0xe4, 0x8f, 0x35, 0xec, 0x16, 0x3f, 0x68, 0xf0, + 0x36, 0xf3, 0x76, 0x76, 0xde, 0x64, 0x1e, 0x4c, 0xd2, 0x24, 0x52, 0xd2, 0x8f, 0xe5, 0x85, 0x05, + 0x42, 0xc9, 0x05, 0x2a, 0x5f, 0xa3, 0x5a, 0x27, 0x11, 0xfa, 0x99, 0x92, 0xf9, 0x76, 0xc8, 0x0c, + 0xa1, 0xc7, 0xb1, 0x64, 0x46, 0xcb, 0xec, 0xd8, 0x73, 0xa0, 0x3d, 0x4d, 0xb3, 0xbc, 0xf4, 0xde, + 0xe0, 0xe8, 0xa5, 0x10, 0xcb, 0x44, 0xcf, 0x39, 0xae, 0x0a, 0xd4, 0x39, 0x1d, 0x40, 0x3b, 0x97, + 0x59, 0x12, 0xb9, 0x64, 0x44, 0xc6, 0x5d, 0x6e, 0x09, 0x0d, 0xc0, 0x49, 0x51, 0xeb, 0x30, 0x46, + 0xb7, 0x39, 0x22, 0xe3, 0x5e, 0xe0, 0xb2, 0x1d, 0x4f, 0xf6, 0x6c, 0xdf, 0xf9, 0x56, 0xe8, 0xdd, + 0x41, 0xff, 0xb5, 0x10, 0x3a, 0x52, 0x89, 0xc0, 0xff, 0xdd, 0x07, 0xd0, 0x5e, 0x15, 0x58, 0x58, + 0xef, 0x2e, 0xb7, 0xc4, 0xfb, 0x20, 0xe0, 0x54, 0xa6, 0xf4, 0x16, 0x3a, 0x73, 0x0c, 0x67, 0xa8, + 0x5c, 0x32, 0x6a, 0x8d, 0x7b, 0xc1, 0xf9, 0xbe, 0xf5, 0xec, 0xd1, 0xc8, 0xa6, 0xef, 0xb9, 0x2a, + 0x79, 0xf5, 0x87, 0x52, 0x38, 0x10, 0x72, 0x56, 0x1a, 0xfb, 0x43, 0x6e, 0xf0, 0xf0, 0x1a, 0x7a, + 0xbf, 0xa4, 0xb4, 0x0f, 0xad, 0x05, 0x96, 0x55, 0xac, 0x0d, 0xdc, 0x84, 0x5a, 0x87, 0xcb, 0x9f, + 0x50, 0x86, 0xdc, 0x34, 0xaf, 0x48, 0xf0, 0x49, 0xa0, 0x73, 0x6f, 0xb6, 0xd2, 0x07, 0x70, 0xaa, + 0xfe, 0xe8, 0x69, 0x2d, 0xd2, 0xdf, 0x66, 0x87, 0x27, 0x35, 0x81, 0xbd, 0x41, 0x83, 0x3e, 0x41, + 0xf7, 0xbb, 0x29, 0x7a, 0x56, 0x93, 0xed, 0xb6, 0x38, 0xdc, 0x5b, 0xbe, 0xd7, 0x98, 0x10, 0xd1, + 0x31, 0x47, 0xbf, 0xfc, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x60, 0x8c, 0x40, 0xd5, 0x28, 0x02, 0x00, + 0x00, } diff --git a/broker/service/proto/broker.micro.go b/broker/service/proto/broker.pb.micro.go similarity index 98% rename from broker/service/proto/broker.micro.go rename to broker/service/proto/broker.pb.micro.go index 577132c5..c0229fb6 100644 --- a/broker/service/proto/broker.micro.go +++ b/broker/service/proto/broker.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: github.com/micro/go-micro/broker/proto/broker.proto +// source: micro/go-micro/broker/service/proto/broker.proto package go_micro_broker diff --git a/client/proto/client.pb.go b/client/proto/client.pb.go index c923e337..bd5b3702 100644 --- a/client/proto/client.pb.go +++ b/client/proto/client.pb.go @@ -1,13 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: micro/go-micro/client/proto/client.proto +// source: github.com/micro/go-micro/client/proto/client.proto package go_micro_client import ( - context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" math "math" ) @@ -36,7 +34,7 @@ func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { - return fileDescriptor_7d733ae29171347b, []int{0} + return fileDescriptor_d418333f021a3308, []int{0} } func (m *Request) XXX_Unmarshal(b []byte) error { @@ -96,7 +94,7 @@ func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { - return fileDescriptor_7d733ae29171347b, []int{1} + return fileDescriptor_d418333f021a3308, []int{1} } func (m *Response) XXX_Unmarshal(b []byte) error { @@ -137,7 +135,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_7d733ae29171347b, []int{2} + return fileDescriptor_d418333f021a3308, []int{2} } func (m *Message) XXX_Unmarshal(b []byte) error { @@ -186,203 +184,27 @@ func init() { } func init() { - proto.RegisterFile("micro/go-micro/client/proto/client.proto", fileDescriptor_7d733ae29171347b) + proto.RegisterFile("github.com/micro/go-micro/client/proto/client.proto", fileDescriptor_d418333f021a3308) } -var fileDescriptor_7d733ae29171347b = []byte{ - // 270 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0x41, 0x4b, 0xc3, 0x40, - 0x10, 0x85, 0xbb, 0x6d, 0x4c, 0xea, 0x58, 0x10, 0x06, 0x0f, 0x6b, 0x0e, 0x52, 0x73, 0xca, 0xc5, - 0x54, 0xf4, 0x2c, 0x1e, 0x72, 0x16, 0x24, 0x8a, 0x57, 0x49, 0xb6, 0x43, 0x5c, 0x48, 0x77, 0xd7, - 0xec, 0xb6, 0x90, 0x1f, 0xe9, 0x7f, 0x12, 0x36, 0xa9, 0x15, 0x6d, 0x2f, 0xbd, 0xcd, 0x9b, 0x6f, - 0x79, 0x33, 0xfb, 0x06, 0xd2, 0x95, 0x14, 0xad, 0x5e, 0xd4, 0xfa, 0xa6, 0x2f, 0x44, 0x23, 0x49, - 0xb9, 0x85, 0x69, 0xb5, 0xdb, 0x8a, 0xcc, 0x0b, 0x3c, 0xaf, 0x75, 0xe6, 0xdf, 0x64, 0x7d, 0x3b, - 0xd9, 0x40, 0x54, 0xd0, 0xe7, 0x9a, 0xac, 0x43, 0x0e, 0x91, 0xa5, 0x76, 0x23, 0x05, 0x71, 0x36, - 0x67, 0xe9, 0x69, 0xb1, 0x95, 0x18, 0xc3, 0x94, 0xd4, 0xd2, 0x68, 0xa9, 0x1c, 0x1f, 0x7b, 0xf4, - 0xa3, 0xf1, 0x1a, 0x66, 0x42, 0x2b, 0x47, 0xca, 0xbd, 0xbb, 0xce, 0x10, 0x9f, 0x78, 0x7e, 0x36, - 0xf4, 0x5e, 0x3b, 0x43, 0x88, 0x10, 0x54, 0x7a, 0xd9, 0xf1, 0x60, 0xce, 0xd2, 0x59, 0xe1, 0xeb, - 0xe4, 0x0a, 0xa6, 0x05, 0x59, 0xa3, 0x95, 0xdd, 0x71, 0xf6, 0x8b, 0xbf, 0x41, 0xf4, 0x44, 0xd6, - 0x96, 0x35, 0xe1, 0x05, 0x9c, 0x38, 0x6d, 0xa4, 0x18, 0xb6, 0xea, 0xc5, 0xbf, 0xb9, 0xe3, 0xc3, - 0x73, 0x27, 0x3b, 0xdf, 0xbb, 0x2f, 0x06, 0x61, 0xee, 0xbf, 0x8e, 0x0f, 0x10, 0xe4, 0x65, 0xd3, - 0x20, 0xcf, 0xfe, 0x84, 0x92, 0x0d, 0x89, 0xc4, 0x97, 0x7b, 0x48, 0xbf, 0x73, 0x32, 0xc2, 0x1c, - 0xc2, 0x17, 0xd7, 0x52, 0xb9, 0x3a, 0xd2, 0x20, 0x65, 0xb7, 0x0c, 0x1f, 0x21, 0x7a, 0x5e, 0x57, - 0x8d, 0xb4, 0x1f, 0x7b, 0x5c, 0x86, 0x00, 0xe2, 0x83, 0x24, 0x19, 0x55, 0xa1, 0xbf, 0xeb, 0xfd, - 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x76, 0x1f, 0x51, 0x03, 0x02, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// ClientClient is the client API for Client service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type ClientClient interface { - // Call allows a single request to be made - Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) - // Stream is a bidirectional stream - Stream(ctx context.Context, opts ...grpc.CallOption) (Client_StreamClient, error) - // Publish publishes a message and returns an empty Message - Publish(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) -} - -type clientClient struct { - cc *grpc.ClientConn -} - -func NewClientClient(cc *grpc.ClientConn) ClientClient { - return &clientClient{cc} -} - -func (c *clientClient) Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { - out := new(Response) - err := c.cc.Invoke(ctx, "/go.micro.client.Client/Call", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *clientClient) Stream(ctx context.Context, opts ...grpc.CallOption) (Client_StreamClient, error) { - stream, err := c.cc.NewStream(ctx, &_Client_serviceDesc.Streams[0], "/go.micro.client.Client/Stream", opts...) - if err != nil { - return nil, err - } - x := &clientStreamClient{stream} - return x, nil -} - -type Client_StreamClient interface { - Send(*Request) error - Recv() (*Response, error) - grpc.ClientStream -} - -type clientStreamClient struct { - grpc.ClientStream -} - -func (x *clientStreamClient) Send(m *Request) error { - return x.ClientStream.SendMsg(m) -} - -func (x *clientStreamClient) Recv() (*Response, error) { - m := new(Response) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *clientClient) Publish(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) { - out := new(Message) - err := c.cc.Invoke(ctx, "/go.micro.client.Client/Publish", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// ClientServer is the server API for Client service. -type ClientServer interface { - // Call allows a single request to be made - Call(context.Context, *Request) (*Response, error) - // Stream is a bidirectional stream - Stream(Client_StreamServer) error - // Publish publishes a message and returns an empty Message - Publish(context.Context, *Message) (*Message, error) -} - -func RegisterClientServer(s *grpc.Server, srv ClientServer) { - s.RegisterService(&_Client_serviceDesc, srv) -} - -func _Client_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Request) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ClientServer).Call(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.client.Client/Call", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientServer).Call(ctx, req.(*Request)) - } - return interceptor(ctx, in, info, handler) -} - -func _Client_Stream_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(ClientServer).Stream(&clientStreamServer{stream}) -} - -type Client_StreamServer interface { - Send(*Response) error - Recv() (*Request, error) - grpc.ServerStream -} - -type clientStreamServer struct { - grpc.ServerStream -} - -func (x *clientStreamServer) Send(m *Response) error { - return x.ServerStream.SendMsg(m) -} - -func (x *clientStreamServer) Recv() (*Request, error) { - m := new(Request) - if err := x.ServerStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func _Client_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Message) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ClientServer).Publish(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.client.Client/Publish", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientServer).Publish(ctx, req.(*Message)) - } - return interceptor(ctx, in, info, handler) -} - -var _Client_serviceDesc = grpc.ServiceDesc{ - ServiceName: "go.micro.client.Client", - HandlerType: (*ClientServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Call", - Handler: _Client_Call_Handler, - }, - { - MethodName: "Publish", - Handler: _Client_Publish_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "Stream", - Handler: _Client_Stream_Handler, - ServerStreams: true, - ClientStreams: true, - }, - }, - Metadata: "micro/go-micro/client/proto/client.proto", +var fileDescriptor_d418333f021a3308 = []byte{ + // 279 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0x31, 0x4f, 0xfb, 0x30, + 0x10, 0xc5, 0xeb, 0xb6, 0xff, 0xa4, 0xff, 0xa3, 0x12, 0x92, 0xc5, 0x60, 0x32, 0xa0, 0x92, 0x29, + 0x0b, 0x0e, 0xa2, 0x33, 0x62, 0xc8, 0x8c, 0x84, 0x02, 0x62, 0x45, 0x89, 0x7b, 0x4a, 0x2d, 0x25, + 0xb6, 0x89, 0x9d, 0x4a, 0xf9, 0x90, 0x7c, 0x27, 0x24, 0x27, 0xa5, 0x08, 0xda, 0x85, 0xed, 0xde, + 0xfd, 0xac, 0x77, 0xe7, 0x77, 0xb0, 0xae, 0xa4, 0xdb, 0x76, 0x25, 0x17, 0xba, 0x49, 0x1b, 0x29, + 0x5a, 0x9d, 0x56, 0xfa, 0x66, 0x28, 0x44, 0x2d, 0x51, 0xb9, 0xd4, 0xb4, 0xda, 0xed, 0x05, 0xf7, + 0x82, 0x9e, 0x57, 0x9a, 0xfb, 0x37, 0x7c, 0x68, 0xc7, 0x3b, 0x08, 0x73, 0x7c, 0xef, 0xd0, 0x3a, + 0xca, 0x20, 0xb4, 0xd8, 0xee, 0xa4, 0x40, 0x46, 0x56, 0x24, 0xf9, 0x9f, 0xef, 0x25, 0x8d, 0x60, + 0x81, 0x6a, 0x63, 0xb4, 0x54, 0x8e, 0x4d, 0x3d, 0xfa, 0xd2, 0xf4, 0x1a, 0x96, 0x42, 0x2b, 0x87, + 0xca, 0xbd, 0xb9, 0xde, 0x20, 0x9b, 0x79, 0x7e, 0x36, 0xf6, 0x5e, 0x7a, 0x83, 0x94, 0xc2, 0xbc, + 0xd4, 0x9b, 0x9e, 0xcd, 0x57, 0x24, 0x59, 0xe6, 0xbe, 0x8e, 0xaf, 0x60, 0x91, 0xa3, 0x35, 0x5a, + 0xd9, 0x03, 0x27, 0xdf, 0xf8, 0x2b, 0x84, 0x8f, 0x68, 0x6d, 0x51, 0x21, 0xbd, 0x80, 0x7f, 0x4e, + 0x1b, 0x29, 0xc6, 0xad, 0x06, 0xf1, 0x6b, 0xee, 0xf4, 0xf4, 0xdc, 0xd9, 0xc1, 0xf7, 0xee, 0x83, + 0x40, 0x90, 0xf9, 0xaf, 0xd3, 0x7b, 0x98, 0x67, 0x45, 0x5d, 0x53, 0xc6, 0x7f, 0x84, 0xc2, 0xc7, + 0x44, 0xa2, 0xcb, 0x23, 0x64, 0xd8, 0x39, 0x9e, 0xd0, 0x0c, 0x82, 0x67, 0xd7, 0x62, 0xd1, 0xfc, + 0xd1, 0x20, 0x21, 0xb7, 0x84, 0x3e, 0x40, 0xf8, 0xd4, 0x95, 0xb5, 0xb4, 0xdb, 0x23, 0x2e, 0x63, + 0x00, 0xd1, 0x49, 0x12, 0x4f, 0xca, 0xc0, 0xdf, 0x75, 0xfd, 0x19, 0x00, 0x00, 0xff, 0xff, 0xb6, + 0x4d, 0x6e, 0xd5, 0x0e, 0x02, 0x00, 0x00, } diff --git a/client/proto/client.micro.go b/client/proto/client.pb.micro.go similarity index 98% rename from client/proto/client.micro.go rename to client/proto/client.pb.micro.go index 6fc4886e..140d9b45 100644 --- a/client/proto/client.micro.go +++ b/client/proto/client.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: micro/go-micro/client/proto/client.proto +// source: github.com/micro/go-micro/client/proto/client.proto package go_micro_client diff --git a/debug/proto/debug.pb.go b/debug/proto/debug.pb.go index 5ba4f8c9..316df6a8 100644 --- a/debug/proto/debug.pb.go +++ b/debug/proto/debug.pb.go @@ -1,13 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: micro/go-micro/debug/proto/debug.proto +// source: github.com/micro/go-micro/debug/proto/debug.proto package debug import ( - context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" math "math" ) @@ -32,7 +30,7 @@ func (m *HealthRequest) Reset() { *m = HealthRequest{} } func (m *HealthRequest) String() string { return proto.CompactTextString(m) } func (*HealthRequest) ProtoMessage() {} func (*HealthRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f25415e61bccfa1f, []int{0} + return fileDescriptor_7cb19b1a05a6e0a9, []int{0} } func (m *HealthRequest) XXX_Unmarshal(b []byte) error { @@ -65,7 +63,7 @@ func (m *HealthResponse) Reset() { *m = HealthResponse{} } func (m *HealthResponse) String() string { return proto.CompactTextString(m) } func (*HealthResponse) ProtoMessage() {} func (*HealthResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f25415e61bccfa1f, []int{1} + return fileDescriptor_7cb19b1a05a6e0a9, []int{1} } func (m *HealthResponse) XXX_Unmarshal(b []byte) error { @@ -103,7 +101,7 @@ func (m *StatsRequest) Reset() { *m = StatsRequest{} } func (m *StatsRequest) String() string { return proto.CompactTextString(m) } func (*StatsRequest) ProtoMessage() {} func (*StatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f25415e61bccfa1f, []int{2} + return fileDescriptor_7cb19b1a05a6e0a9, []int{2} } func (m *StatsRequest) XXX_Unmarshal(b []byte) error { @@ -144,7 +142,7 @@ func (m *StatsResponse) Reset() { *m = StatsResponse{} } func (m *StatsResponse) String() string { return proto.CompactTextString(m) } func (*StatsResponse) ProtoMessage() {} func (*StatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f25415e61bccfa1f, []int{3} + return fileDescriptor_7cb19b1a05a6e0a9, []int{3} } func (m *StatsResponse) XXX_Unmarshal(b []byte) error { @@ -208,129 +206,24 @@ func init() { } func init() { - proto.RegisterFile("micro/go-micro/debug/proto/debug.proto", fileDescriptor_f25415e61bccfa1f) + proto.RegisterFile("github.com/micro/go-micro/debug/proto/debug.proto", fileDescriptor_7cb19b1a05a6e0a9) } -var fileDescriptor_f25415e61bccfa1f = []byte{ - // 230 bytes of a gzipped FileDescriptorProto +var fileDescriptor_7cb19b1a05a6e0a9 = []byte{ + // 237 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0x41, 0x4b, 0xc4, 0x30, - 0x10, 0x85, 0xb7, 0x75, 0x5b, 0x71, 0xb0, 0x59, 0xc8, 0x41, 0xc2, 0x9e, 0x24, 0x07, 0x29, 0x88, - 0x59, 0xd0, 0xbf, 0xe0, 0xc1, 0x73, 0xbd, 0x0b, 0xd9, 0x76, 0xe8, 0x16, 0xac, 0xa9, 0x99, 0xe9, - 0xc1, 0xb3, 0x7f, 0x5c, 0x9a, 0xa4, 0x60, 0x6f, 0xef, 0xbd, 0xf0, 0x1e, 0xf9, 0x06, 0x1e, 0xc6, - 0xa1, 0xf5, 0xee, 0xd4, 0xbb, 0xa7, 0x28, 0x3a, 0x3c, 0xcf, 0xfd, 0x69, 0xf2, 0x8e, 0x93, 0x36, - 0x41, 0xeb, 0x03, 0x54, 0x6f, 0x68, 0x3f, 0xf9, 0xd2, 0xe0, 0xf7, 0x8c, 0xc4, 0xba, 0x06, 0xb1, - 0x06, 0x34, 0xb9, 0x2f, 0x42, 0x79, 0x07, 0x25, 0xb1, 0xe5, 0x99, 0x54, 0x76, 0x9f, 0xd5, 0x37, - 0x4d, 0x72, 0x5a, 0xc0, 0xed, 0x3b, 0x5b, 0xa6, 0xb5, 0xf9, 0x9b, 0x41, 0x95, 0x82, 0xd4, 0x54, - 0x70, 0x4d, 0x6c, 0x3d, 0x63, 0x17, 0xaa, 0xfb, 0x66, 0xb5, 0xcb, 0xe6, 0x3c, 0xf1, 0x30, 0xa2, - 0xca, 0xc3, 0x43, 0x72, 0x4b, 0x3e, 0xe2, 0xe8, 0xfc, 0x8f, 0xba, 0x8a, 0x79, 0x74, 0xcb, 0x12, - 0x5f, 0x3c, 0xda, 0x8e, 0xd4, 0x3e, 0x2e, 0x25, 0x2b, 0x05, 0xe4, 0x7d, 0xab, 0x8a, 0x10, 0xe6, - 0x7d, 0xfb, 0xfc, 0x01, 0xc5, 0xeb, 0xc2, 0x27, 0x1f, 0xa1, 0x8c, 0x20, 0x52, 0x98, 0x0d, 0xe2, - 0xf1, 0x60, 0xb6, 0x84, 0x7a, 0x27, 0x6b, 0x28, 0xc2, 0xd7, 0x65, 0x65, 0xfe, 0x33, 0x1d, 0x85, - 0xd9, 0x10, 0xe9, 0xdd, 0xb9, 0x0c, 0x77, 0x7b, 0xf9, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xb9, - 0x5f, 0xf7, 0x61, 0x01, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// DebugClient is the client API for Debug service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type DebugClient interface { - Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) - Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error) -} - -type debugClient struct { - cc *grpc.ClientConn -} - -func NewDebugClient(cc *grpc.ClientConn) DebugClient { - return &debugClient{cc} -} - -func (c *debugClient) Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) { - out := new(HealthResponse) - err := c.cc.Invoke(ctx, "/Debug/Health", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *debugClient) Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error) { - out := new(StatsResponse) - err := c.cc.Invoke(ctx, "/Debug/Stats", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// DebugServer is the server API for Debug service. -type DebugServer interface { - Health(context.Context, *HealthRequest) (*HealthResponse, error) - Stats(context.Context, *StatsRequest) (*StatsResponse, error) -} - -func RegisterDebugServer(s *grpc.Server, srv DebugServer) { - s.RegisterService(&_Debug_serviceDesc, srv) -} - -func _Debug_Health_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(HealthRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DebugServer).Health(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/Debug/Health", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DebugServer).Health(ctx, req.(*HealthRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Debug_Stats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(StatsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DebugServer).Stats(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/Debug/Stats", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DebugServer).Stats(ctx, req.(*StatsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Debug_serviceDesc = grpc.ServiceDesc{ - ServiceName: "Debug", - HandlerType: (*DebugServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Health", - Handler: _Debug_Health_Handler, - }, - { - MethodName: "Stats", - Handler: _Debug_Stats_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "micro/go-micro/debug/proto/debug.proto", + 0x14, 0x84, 0x77, 0xeb, 0xb6, 0xe2, 0xc3, 0x66, 0x21, 0x07, 0x09, 0x7b, 0x92, 0x9c, 0x0a, 0x62, + 0x8a, 0xfa, 0x17, 0x3c, 0x78, 0xae, 0x77, 0x21, 0x6d, 0x43, 0x5a, 0x30, 0xa6, 0x26, 0x2f, 0x07, + 0xcf, 0xfe, 0x71, 0x69, 0x92, 0x82, 0xbd, 0xcd, 0x4c, 0x98, 0x21, 0xdf, 0x83, 0x27, 0x3d, 0xe3, + 0x14, 0x7a, 0x31, 0x58, 0xd3, 0x9a, 0x79, 0x70, 0xb6, 0xd5, 0xf6, 0x31, 0x89, 0x51, 0xf5, 0x41, + 0xb7, 0x8b, 0xb3, 0x98, 0xb5, 0x88, 0x9a, 0x9f, 0xa1, 0x7e, 0x53, 0xf2, 0x13, 0xa7, 0x4e, 0x7d, + 0x07, 0xe5, 0x91, 0x37, 0x40, 0xb6, 0xc0, 0x2f, 0xf6, 0xcb, 0x2b, 0x7a, 0x07, 0x95, 0x47, 0x89, + 0xc1, 0xb3, 0xe3, 0xfd, 0xb1, 0xb9, 0xe9, 0xb2, 0xe3, 0x04, 0x6e, 0xdf, 0x51, 0xa2, 0xdf, 0x9a, + 0xbf, 0x47, 0xa8, 0x73, 0x90, 0x9b, 0x0c, 0xae, 0x3d, 0x4a, 0x87, 0x6a, 0x8c, 0xd5, 0x53, 0xb7, + 0xd9, 0x75, 0x33, 0x2c, 0x38, 0x1b, 0xc5, 0x8a, 0xf8, 0x90, 0xdd, 0x9a, 0x1b, 0x65, 0xac, 0xfb, + 0x61, 0x57, 0x29, 0x4f, 0x6e, 0x5d, 0xc2, 0xc9, 0x29, 0x39, 0x7a, 0x76, 0x4a, 0x4b, 0xd9, 0x52, + 0x02, 0x85, 0x1e, 0x58, 0x19, 0xc3, 0x42, 0x0f, 0xcf, 0x1f, 0x50, 0xbe, 0xae, 0x7c, 0xf4, 0x01, + 0xaa, 0x04, 0x42, 0x89, 0xd8, 0x21, 0x5e, 0xce, 0x62, 0x4f, 0xc8, 0x0f, 0xb4, 0x81, 0x32, 0x7e, + 0x9d, 0xd6, 0xe2, 0x3f, 0xd3, 0x85, 0x88, 0x1d, 0x11, 0x3f, 0xf4, 0x55, 0xbc, 0xdb, 0xcb, 0x5f, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x20, 0xb8, 0xfe, 0x98, 0x6c, 0x01, 0x00, 0x00, } diff --git a/debug/proto/debug.micro.go b/debug/proto/debug.pb.micro.go similarity index 97% rename from debug/proto/debug.micro.go rename to debug/proto/debug.pb.micro.go index baa06cee..3dcc256f 100644 --- a/debug/proto/debug.micro.go +++ b/debug/proto/debug.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: micro/go-micro/debug/proto/debug.proto +// source: github.com/micro/go-micro/debug/proto/debug.proto package debug diff --git a/network/proto/network.pb.go b/network/proto/network.pb.go index 4e81fa65..97b38402 100644 --- a/network/proto/network.pb.go +++ b/network/proto/network.pb.go @@ -4,11 +4,9 @@ package go_micro_network import ( - context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" proto1 "github.com/micro/go-micro/router/proto" - grpc "google.golang.org/grpc" math "math" ) @@ -737,217 +735,3 @@ var fileDescriptor_0b7953b26a7c4730 = []byte{ 0xc9, 0x5c, 0x9e, 0x5d, 0x4f, 0xc0, 0xab, 0x20, 0xb9, 0xe8, 0x4d, 0xc3, 0xfc, 0x49, 0x0f, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x79, 0x8a, 0x5f, 0xf0, 0x24, 0x06, 0x00, 0x00, } - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// NetworkClient is the client API for Network service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type NetworkClient interface { - // Connect to the network - Connect(ctx context.Context, in *ConnectRequest, opts ...grpc.CallOption) (*ConnectResponse, error) - // Returns the entire network graph - Graph(ctx context.Context, in *GraphRequest, opts ...grpc.CallOption) (*GraphResponse, error) - // Returns a list of known nodes in the network - Nodes(ctx context.Context, in *NodesRequest, opts ...grpc.CallOption) (*NodesResponse, error) - // Returns a list of known routes in the network - Routes(ctx context.Context, in *RoutesRequest, opts ...grpc.CallOption) (*RoutesResponse, error) - // Returns a list of known services based on routes - Services(ctx context.Context, in *ServicesRequest, opts ...grpc.CallOption) (*ServicesResponse, error) -} - -type networkClient struct { - cc *grpc.ClientConn -} - -func NewNetworkClient(cc *grpc.ClientConn) NetworkClient { - return &networkClient{cc} -} - -func (c *networkClient) Connect(ctx context.Context, in *ConnectRequest, opts ...grpc.CallOption) (*ConnectResponse, error) { - out := new(ConnectResponse) - err := c.cc.Invoke(ctx, "/go.micro.network.Network/Connect", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *networkClient) Graph(ctx context.Context, in *GraphRequest, opts ...grpc.CallOption) (*GraphResponse, error) { - out := new(GraphResponse) - err := c.cc.Invoke(ctx, "/go.micro.network.Network/Graph", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *networkClient) Nodes(ctx context.Context, in *NodesRequest, opts ...grpc.CallOption) (*NodesResponse, error) { - out := new(NodesResponse) - err := c.cc.Invoke(ctx, "/go.micro.network.Network/Nodes", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *networkClient) Routes(ctx context.Context, in *RoutesRequest, opts ...grpc.CallOption) (*RoutesResponse, error) { - out := new(RoutesResponse) - err := c.cc.Invoke(ctx, "/go.micro.network.Network/Routes", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *networkClient) Services(ctx context.Context, in *ServicesRequest, opts ...grpc.CallOption) (*ServicesResponse, error) { - out := new(ServicesResponse) - err := c.cc.Invoke(ctx, "/go.micro.network.Network/Services", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// NetworkServer is the server API for Network service. -type NetworkServer interface { - // Connect to the network - Connect(context.Context, *ConnectRequest) (*ConnectResponse, error) - // Returns the entire network graph - Graph(context.Context, *GraphRequest) (*GraphResponse, error) - // Returns a list of known nodes in the network - Nodes(context.Context, *NodesRequest) (*NodesResponse, error) - // Returns a list of known routes in the network - Routes(context.Context, *RoutesRequest) (*RoutesResponse, error) - // Returns a list of known services based on routes - Services(context.Context, *ServicesRequest) (*ServicesResponse, error) -} - -func RegisterNetworkServer(s *grpc.Server, srv NetworkServer) { - s.RegisterService(&_Network_serviceDesc, srv) -} - -func _Network_Connect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ConnectRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NetworkServer).Connect(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.network.Network/Connect", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NetworkServer).Connect(ctx, req.(*ConnectRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Network_Graph_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GraphRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NetworkServer).Graph(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.network.Network/Graph", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NetworkServer).Graph(ctx, req.(*GraphRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Network_Nodes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(NodesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NetworkServer).Nodes(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.network.Network/Nodes", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NetworkServer).Nodes(ctx, req.(*NodesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Network_Routes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RoutesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NetworkServer).Routes(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.network.Network/Routes", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NetworkServer).Routes(ctx, req.(*RoutesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Network_Services_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ServicesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NetworkServer).Services(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.network.Network/Services", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NetworkServer).Services(ctx, req.(*ServicesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Network_serviceDesc = grpc.ServiceDesc{ - ServiceName: "go.micro.network.Network", - HandlerType: (*NetworkServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Connect", - Handler: _Network_Connect_Handler, - }, - { - MethodName: "Graph", - Handler: _Network_Graph_Handler, - }, - { - MethodName: "Nodes", - Handler: _Network_Nodes_Handler, - }, - { - MethodName: "Routes", - Handler: _Network_Routes_Handler, - }, - { - MethodName: "Services", - Handler: _Network_Services_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "github.com/micro/go-micro/network/proto/network.proto", -} diff --git a/network/proto/network.micro.go b/network/proto/network.pb.micro.go similarity index 100% rename from network/proto/network.micro.go rename to network/proto/network.pb.micro.go diff --git a/registry/service/proto/registry.pb.go b/registry/service/proto/registry.pb.go index 99d20bdb..9383e99a 100644 --- a/registry/service/proto/registry.pb.go +++ b/registry/service/proto/registry.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: go-micro/registry/service/proto/registry.proto +// source: micro/go-micro/registry/service/proto/registry.proto package go_micro_registry @@ -46,7 +46,7 @@ func (x EventType) String() string { } func (EventType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{0} + return fileDescriptor_2f73432195c6499a, []int{0} } // Service represents a go-micro service @@ -66,7 +66,7 @@ func (m *Service) Reset() { *m = Service{} } func (m *Service) String() string { return proto.CompactTextString(m) } func (*Service) ProtoMessage() {} func (*Service) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{0} + return fileDescriptor_2f73432195c6499a, []int{0} } func (m *Service) XXX_Unmarshal(b []byte) error { @@ -144,7 +144,7 @@ func (m *Node) Reset() { *m = Node{} } func (m *Node) String() string { return proto.CompactTextString(m) } func (*Node) ProtoMessage() {} func (*Node) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{1} + return fileDescriptor_2f73432195c6499a, []int{1} } func (m *Node) XXX_Unmarshal(b []byte) error { @@ -208,7 +208,7 @@ func (m *Endpoint) Reset() { *m = Endpoint{} } func (m *Endpoint) String() string { return proto.CompactTextString(m) } func (*Endpoint) ProtoMessage() {} func (*Endpoint) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{2} + return fileDescriptor_2f73432195c6499a, []int{2} } func (m *Endpoint) XXX_Unmarshal(b []byte) error { @@ -271,7 +271,7 @@ func (m *Value) Reset() { *m = Value{} } func (m *Value) String() string { return proto.CompactTextString(m) } func (*Value) ProtoMessage() {} func (*Value) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{3} + return fileDescriptor_2f73432195c6499a, []int{3} } func (m *Value) XXX_Unmarshal(b []byte) error { @@ -325,7 +325,7 @@ func (m *Options) Reset() { *m = Options{} } func (m *Options) String() string { return proto.CompactTextString(m) } func (*Options) ProtoMessage() {} func (*Options) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{4} + return fileDescriptor_2f73432195c6499a, []int{4} } func (m *Options) XXX_Unmarshal(b []byte) error { @@ -367,7 +367,7 @@ func (m *Result) Reset() { *m = Result{} } func (m *Result) String() string { return proto.CompactTextString(m) } func (*Result) ProtoMessage() {} func (*Result) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{5} + return fileDescriptor_2f73432195c6499a, []int{5} } func (m *Result) XXX_Unmarshal(b []byte) error { @@ -419,7 +419,7 @@ func (m *EmptyResponse) Reset() { *m = EmptyResponse{} } func (m *EmptyResponse) String() string { return proto.CompactTextString(m) } func (*EmptyResponse) ProtoMessage() {} func (*EmptyResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{6} + return fileDescriptor_2f73432195c6499a, []int{6} } func (m *EmptyResponse) XXX_Unmarshal(b []byte) error { @@ -451,7 +451,7 @@ func (m *GetRequest) Reset() { *m = GetRequest{} } func (m *GetRequest) String() string { return proto.CompactTextString(m) } func (*GetRequest) ProtoMessage() {} func (*GetRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{7} + return fileDescriptor_2f73432195c6499a, []int{7} } func (m *GetRequest) XXX_Unmarshal(b []byte) error { @@ -490,7 +490,7 @@ func (m *GetResponse) Reset() { *m = GetResponse{} } func (m *GetResponse) String() string { return proto.CompactTextString(m) } func (*GetResponse) ProtoMessage() {} func (*GetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{8} + return fileDescriptor_2f73432195c6499a, []int{8} } func (m *GetResponse) XXX_Unmarshal(b []byte) error { @@ -528,7 +528,7 @@ func (m *ListRequest) Reset() { *m = ListRequest{} } func (m *ListRequest) String() string { return proto.CompactTextString(m) } func (*ListRequest) ProtoMessage() {} func (*ListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{9} + return fileDescriptor_2f73432195c6499a, []int{9} } func (m *ListRequest) XXX_Unmarshal(b []byte) error { @@ -560,7 +560,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} } func (m *ListResponse) String() string { return proto.CompactTextString(m) } func (*ListResponse) ProtoMessage() {} func (*ListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{10} + return fileDescriptor_2f73432195c6499a, []int{10} } func (m *ListResponse) XXX_Unmarshal(b []byte) error { @@ -600,7 +600,7 @@ func (m *WatchRequest) Reset() { *m = WatchRequest{} } func (m *WatchRequest) String() string { return proto.CompactTextString(m) } func (*WatchRequest) ProtoMessage() {} func (*WatchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{11} + return fileDescriptor_2f73432195c6499a, []int{11} } func (m *WatchRequest) XXX_Unmarshal(b []byte) error { @@ -647,7 +647,7 @@ func (m *Event) Reset() { *m = Event{} } func (m *Event) String() string { return proto.CompactTextString(m) } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { - return fileDescriptor_0e39fd3e4b9b6e63, []int{12} + return fileDescriptor_2f73432195c6499a, []int{12} } func (m *Event) XXX_Unmarshal(b []byte) error { @@ -717,52 +717,52 @@ func init() { } func init() { - proto.RegisterFile("go-micro/registry/service/proto/registry.proto", fileDescriptor_0e39fd3e4b9b6e63) + proto.RegisterFile("micro/go-micro/registry/service/proto/registry.proto", fileDescriptor_2f73432195c6499a) } -var fileDescriptor_0e39fd3e4b9b6e63 = []byte{ - // 679 bytes of a gzipped FileDescriptorProto +var fileDescriptor_2f73432195c6499a = []byte{ + // 681 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xdd, 0x6e, 0xd3, 0x4c, 0x10, 0x8d, 0xed, 0xfc, 0x4e, 0xda, 0x7e, 0xfd, 0x46, 0x08, 0x8c, 0x5b, 0x20, 0xb2, 0x04, 0x0a, - 0x48, 0x75, 0xaa, 0x50, 0x21, 0x7e, 0xae, 0x10, 0x0d, 0x95, 0x50, 0x0b, 0x62, 0xf9, 0xbb, 0x36, + 0x48, 0x4d, 0xaa, 0x50, 0x21, 0x7e, 0xae, 0x10, 0x0d, 0x95, 0x50, 0x0b, 0x62, 0xf9, 0xbb, 0x36, 0xf1, 0xa8, 0x58, 0x24, 0xb6, 0xd9, 0xdd, 0x46, 0xca, 0x3b, 0x20, 0xf1, 0x04, 0xbc, 0x0d, 0x4f, - 0xc1, 0xd3, 0xa0, 0x5d, 0xaf, 0x93, 0x54, 0xb5, 0x03, 0x52, 0xe1, 0x6e, 0x66, 0xf7, 0x9c, 0xd9, - 0xd9, 0x33, 0x67, 0x6d, 0x08, 0x4e, 0xd3, 0xbd, 0x69, 0x3c, 0xe6, 0xe9, 0x80, 0xd3, 0x69, 0x2c, - 0x24, 0x9f, 0x0f, 0x04, 0xf1, 0x59, 0x3c, 0xa6, 0x41, 0xc6, 0x53, 0xb9, 0x5c, 0x0e, 0x74, 0x8a, - 0xff, 0x9f, 0xa6, 0x81, 0xc6, 0x07, 0xc5, 0x86, 0xff, 0xd3, 0x86, 0xd6, 0x9b, 0x9c, 0x83, 0x08, - 0xf5, 0x24, 0x9c, 0x92, 0x6b, 0xf5, 0xac, 0x7e, 0x87, 0xe9, 0x18, 0x5d, 0x68, 0xcd, 0x88, 0x8b, - 0x38, 0x4d, 0x5c, 0x5b, 0x2f, 0x17, 0x29, 0x1e, 0x42, 0x7b, 0x4a, 0x32, 0x8c, 0x42, 0x19, 0xba, - 0x4e, 0xcf, 0xe9, 0x77, 0x87, 0xfd, 0xe0, 0x42, 0xfd, 0xc0, 0xd4, 0x0e, 0x4e, 0x0c, 0x74, 0x94, - 0x48, 0x3e, 0x67, 0x0b, 0x26, 0x3e, 0x82, 0x0e, 0x25, 0x51, 0x96, 0xc6, 0x89, 0x14, 0x6e, 0x5d, - 0x97, 0xd9, 0x29, 0x29, 0x33, 0x32, 0x18, 0xb6, 0x44, 0xe3, 0x1e, 0x34, 0x92, 0x34, 0x22, 0xe1, - 0x36, 0x34, 0xed, 0x5a, 0x09, 0xed, 0x65, 0x1a, 0x11, 0xcb, 0x51, 0x78, 0x00, 0xad, 0x34, 0x93, - 0x71, 0x9a, 0x08, 0xb7, 0xd9, 0xb3, 0xfa, 0xdd, 0xa1, 0x57, 0x42, 0x78, 0x95, 0x23, 0x58, 0x01, - 0xf5, 0x9e, 0xc0, 0xe6, 0xb9, 0xd6, 0x71, 0x1b, 0x9c, 0xcf, 0x34, 0x37, 0x1a, 0xa9, 0x10, 0xaf, - 0x40, 0x63, 0x16, 0x4e, 0xce, 0xc8, 0x08, 0x94, 0x27, 0x8f, 0xed, 0x87, 0x96, 0xff, 0xc3, 0x82, - 0xba, 0x6a, 0x01, 0xb7, 0xc0, 0x8e, 0x23, 0xc3, 0xb1, 0xe3, 0x48, 0xa9, 0x1a, 0x46, 0x11, 0x27, - 0x21, 0x0a, 0x55, 0x4d, 0xaa, 0x66, 0x90, 0xa5, 0x5c, 0xba, 0x4e, 0xcf, 0xea, 0x3b, 0x4c, 0xc7, - 0xf8, 0x74, 0x45, 0xe9, 0x5c, 0xa2, 0xdb, 0x15, 0x77, 0xad, 0x92, 0xf9, 0x72, 0xd7, 0xf8, 0x6a, - 0x43, 0xbb, 0x18, 0x40, 0xa9, 0x49, 0x86, 0xd0, 0xe2, 0xf4, 0xe5, 0x8c, 0x84, 0xd4, 0xe4, 0xee, - 0xd0, 0x2d, 0xe9, 0xef, 0xbd, 0xaa, 0xc7, 0x0a, 0x20, 0x1e, 0x40, 0x9b, 0x93, 0xc8, 0xd2, 0x44, - 0x90, 0xbe, 0xec, 0x3a, 0xd2, 0x02, 0x89, 0xa3, 0x0b, 0x52, 0xdc, 0x5d, 0xe3, 0x96, 0x7f, 0x23, - 0x47, 0x08, 0x0d, 0xdd, 0x56, 0xa9, 0x14, 0x08, 0x75, 0x39, 0xcf, 0x0a, 0x96, 0x8e, 0x71, 0x1f, - 0x9a, 0x9a, 0x2d, 0xcc, 0x3b, 0xa9, 0xbe, 0xa8, 0xc1, 0xf9, 0x3b, 0xd0, 0x32, 0x4e, 0x54, 0x9d, - 0x49, 0x39, 0xd1, 0x67, 0x38, 0x4c, 0x85, 0xbe, 0x84, 0x26, 0x23, 0x71, 0x36, 0x91, 0x78, 0x15, - 0x9a, 0xe1, 0x58, 0xc1, 0x4c, 0x0b, 0x26, 0x53, 0x56, 0x37, 0xdf, 0x01, 0x33, 0x0f, 0xaf, 0xfa, - 0x65, 0xb2, 0x02, 0x8a, 0xbb, 0xd0, 0x91, 0xf1, 0x94, 0x84, 0x0c, 0xa7, 0x99, 0xf1, 0xdf, 0x72, - 0xc1, 0xff, 0x0f, 0x36, 0x47, 0xd3, 0x4c, 0xce, 0x99, 0x19, 0x85, 0x7f, 0x07, 0xe0, 0x88, 0x24, - 0x33, 0xe3, 0x74, 0x97, 0x47, 0xe6, 0xbd, 0x14, 0xa9, 0x3f, 0x82, 0xae, 0xc6, 0x99, 0x09, 0x3e, - 0x80, 0xb6, 0xd9, 0x11, 0xae, 0xa5, 0xe5, 0x58, 0xd7, 0xdc, 0x02, 0xeb, 0x6f, 0x42, 0xf7, 0x38, - 0x16, 0xc5, 0x79, 0xfe, 0x73, 0xd8, 0xc8, 0xd3, 0x4b, 0x96, 0xed, 0xc3, 0xc6, 0x87, 0x50, 0x8e, - 0x3f, 0xfd, 0xfe, 0x1e, 0xdf, 0x2d, 0x68, 0x8c, 0x66, 0x94, 0xc8, 0x0b, 0xaf, 0x79, 0x7f, 0x65, - 0xe6, 0x5b, 0xc3, 0xdd, 0x32, 0x43, 0x2a, 0xde, 0xdb, 0x79, 0x46, 0xc6, 0x11, 0x6b, 0xa5, 0x5e, - 0x1d, 0x5f, 0xfd, 0x8f, 0xc7, 0x77, 0x6f, 0x00, 0x9d, 0xc5, 0x31, 0x08, 0xd0, 0x7c, 0xc6, 0x29, - 0x94, 0xb4, 0x5d, 0x53, 0xf1, 0x21, 0x4d, 0x48, 0xd2, 0xb6, 0xa5, 0xe2, 0x77, 0x59, 0xa4, 0xd6, - 0xed, 0xe1, 0x37, 0x07, 0xda, 0xcc, 0x94, 0xc3, 0x13, 0x3d, 0xcd, 0xe2, 0x4f, 0x70, 0xa3, 0xe4, - 0xc0, 0xe5, 0xb0, 0xbd, 0x9b, 0x55, 0xdb, 0xc6, 0x1a, 0x35, 0x7c, 0x51, 0x94, 0x26, 0x8e, 0x6b, - 0xba, 0xf7, 0x7a, 0x65, 0x62, 0x9d, 0xb3, 0x59, 0x0d, 0x8f, 0x01, 0x0e, 0x89, 0xff, 0xad, 0x6a, - 0xaf, 0x73, 0xe3, 0x18, 0x8a, 0xc0, 0xb2, 0xbb, 0xac, 0x18, 0xcd, 0xbb, 0x55, 0xb9, 0xbf, 0x28, - 0x79, 0x04, 0x0d, 0xed, 0x21, 0x2c, 0xc3, 0xae, 0xba, 0xcb, 0xbb, 0x5e, 0x02, 0xc8, 0xdf, 0xb2, - 0x5f, 0xdb, 0xb7, 0x3e, 0x36, 0xf5, 0x6f, 0xfa, 0xfe, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4c, - 0x3e, 0x92, 0x97, 0xd8, 0x07, 0x00, 0x00, + 0xc1, 0xd3, 0xa0, 0x5d, 0xaf, 0x93, 0x54, 0xdd, 0x04, 0xa4, 0xc2, 0xdd, 0xcc, 0xee, 0x39, 0xb3, + 0xb3, 0x67, 0xce, 0xda, 0x70, 0x30, 0x49, 0x46, 0x3c, 0xeb, 0x9f, 0x66, 0x7b, 0x45, 0xc0, 0xe9, + 0x34, 0x11, 0x92, 0xcf, 0xfa, 0x82, 0xf8, 0x34, 0x19, 0x51, 0x3f, 0xe7, 0x99, 0x5c, 0x2c, 0xf7, + 0x74, 0x8a, 0xff, 0x9f, 0x66, 0x3d, 0x8d, 0xef, 0x95, 0x1b, 0xe1, 0x4f, 0x17, 0x1a, 0x6f, 0x0a, + 0x0e, 0x22, 0x54, 0xd3, 0x68, 0x42, 0xbe, 0xd3, 0x71, 0xba, 0x2d, 0xa6, 0x63, 0xf4, 0xa1, 0x31, + 0x25, 0x2e, 0x92, 0x2c, 0xf5, 0x5d, 0xbd, 0x5c, 0xa6, 0x78, 0x08, 0xcd, 0x09, 0xc9, 0x28, 0x8e, + 0x64, 0xe4, 0x7b, 0x1d, 0xaf, 0xdb, 0x1e, 0x74, 0x7b, 0x17, 0xea, 0xf7, 0x4c, 0xed, 0xde, 0x89, + 0x81, 0x0e, 0x53, 0xc9, 0x67, 0x6c, 0xce, 0xc4, 0x47, 0xd0, 0xa2, 0x34, 0xce, 0xb3, 0x24, 0x95, + 0xc2, 0xaf, 0xea, 0x32, 0x3b, 0x96, 0x32, 0x43, 0x83, 0x61, 0x0b, 0x34, 0xee, 0x41, 0x2d, 0xcd, + 0x62, 0x12, 0x7e, 0x4d, 0xd3, 0xae, 0x59, 0x68, 0x2f, 0xb3, 0x98, 0x58, 0x81, 0xc2, 0x03, 0x68, + 0x64, 0xb9, 0x4c, 0xb2, 0x54, 0xf8, 0xf5, 0x8e, 0xd3, 0x6d, 0x0f, 0x02, 0x0b, 0xe1, 0x55, 0x81, + 0x60, 0x25, 0x34, 0x78, 0x02, 0x9b, 0xe7, 0x5a, 0xc7, 0x6d, 0xf0, 0x3e, 0xd3, 0xcc, 0x68, 0xa4, + 0x42, 0xbc, 0x02, 0xb5, 0x69, 0x34, 0x3e, 0x23, 0x23, 0x50, 0x91, 0x3c, 0x76, 0x1f, 0x3a, 0xe1, + 0x0f, 0x07, 0xaa, 0xaa, 0x05, 0xdc, 0x02, 0x37, 0x89, 0x0d, 0xc7, 0x4d, 0x62, 0xa5, 0x6a, 0x14, + 0xc7, 0x9c, 0x84, 0x28, 0x55, 0x35, 0xa9, 0x9a, 0x41, 0x9e, 0x71, 0xe9, 0x7b, 0x1d, 0xa7, 0xeb, + 0x31, 0x1d, 0xe3, 0xd3, 0x25, 0xa5, 0x0b, 0x89, 0x6e, 0xaf, 0xb8, 0xeb, 0x2a, 0x99, 0x2f, 0x77, + 0x8d, 0xaf, 0x2e, 0x34, 0xcb, 0x01, 0x58, 0x4d, 0x32, 0x80, 0x06, 0xa7, 0x2f, 0x67, 0x24, 0xa4, + 0x26, 0xb7, 0x07, 0xbe, 0xa5, 0xbf, 0xf7, 0xaa, 0x1e, 0x2b, 0x81, 0x78, 0x00, 0x4d, 0x4e, 0x22, + 0xcf, 0x52, 0x41, 0xfa, 0xb2, 0xeb, 0x48, 0x73, 0x24, 0x0e, 0x2f, 0x48, 0x71, 0x77, 0x8d, 0x5b, + 0xfe, 0x8d, 0x1c, 0x11, 0xd4, 0x74, 0x5b, 0x56, 0x29, 0x10, 0xaa, 0x72, 0x96, 0x97, 0x2c, 0x1d, + 0xe3, 0x3e, 0xd4, 0x35, 0x5b, 0x98, 0x77, 0xb2, 0xfa, 0xa2, 0x06, 0x17, 0xee, 0x40, 0xc3, 0x38, + 0x51, 0x75, 0x26, 0xe5, 0x58, 0x9f, 0xe1, 0x31, 0x15, 0x86, 0x12, 0xea, 0x8c, 0xc4, 0xd9, 0x58, + 0xe2, 0x55, 0xa8, 0x47, 0x23, 0x05, 0x33, 0x2d, 0x98, 0x4c, 0x59, 0xdd, 0x7c, 0x07, 0xcc, 0x3c, + 0x82, 0xd5, 0x2f, 0x93, 0x95, 0x50, 0xdc, 0x85, 0x96, 0x4c, 0x26, 0x24, 0x64, 0x34, 0xc9, 0x8d, + 0xff, 0x16, 0x0b, 0xe1, 0x7f, 0xb0, 0x39, 0x9c, 0xe4, 0x72, 0xc6, 0xcc, 0x28, 0xc2, 0x3b, 0x00, + 0x47, 0x24, 0x99, 0x19, 0xa7, 0xbf, 0x38, 0xb2, 0xe8, 0xa5, 0x4c, 0xc3, 0x21, 0xb4, 0x35, 0xce, + 0x4c, 0xf0, 0x01, 0x34, 0xcd, 0x8e, 0xf0, 0x1d, 0x2d, 0xc7, 0xba, 0xe6, 0xe6, 0xd8, 0x70, 0x13, + 0xda, 0xc7, 0x89, 0x28, 0xcf, 0x0b, 0x9f, 0xc3, 0x46, 0x91, 0x5e, 0xb2, 0x6c, 0x17, 0x36, 0x3e, + 0x44, 0x72, 0xf4, 0xe9, 0xf7, 0xf7, 0xf8, 0xee, 0x40, 0x6d, 0x38, 0xa5, 0x54, 0x5e, 0x78, 0xcd, + 0xfb, 0x4b, 0x33, 0xdf, 0x1a, 0xec, 0xda, 0x0c, 0xa9, 0x78, 0x6f, 0x67, 0x39, 0x19, 0x47, 0xac, + 0x95, 0x7a, 0x79, 0x7c, 0xd5, 0x3f, 0x1e, 0xdf, 0xbd, 0x3e, 0xb4, 0xe6, 0xc7, 0x20, 0x40, 0xfd, + 0x19, 0xa7, 0x48, 0xd2, 0x76, 0x45, 0xc5, 0x87, 0x34, 0x26, 0x49, 0xdb, 0x8e, 0x8a, 0xdf, 0xe5, + 0xb1, 0x5a, 0x77, 0x07, 0xdf, 0x3c, 0x68, 0x32, 0x53, 0x0e, 0x4f, 0xf4, 0x34, 0xcb, 0x3f, 0xc1, + 0x0d, 0xcb, 0x81, 0x8b, 0x61, 0x07, 0x37, 0x57, 0x6d, 0x1b, 0x6b, 0x54, 0xf0, 0x45, 0x59, 0x9a, + 0x38, 0xae, 0xe9, 0x3e, 0xe8, 0xd8, 0xc4, 0x3a, 0x67, 0xb3, 0x0a, 0x1e, 0x03, 0x1c, 0x12, 0xff, + 0x5b, 0xd5, 0x5e, 0x17, 0xc6, 0x31, 0x14, 0x81, 0xb6, 0xbb, 0x2c, 0x19, 0x2d, 0xb8, 0xb5, 0x72, + 0x7f, 0x5e, 0xf2, 0x08, 0x6a, 0xda, 0x43, 0x68, 0xc3, 0x2e, 0xbb, 0x2b, 0xb8, 0x6e, 0x01, 0x14, + 0x6f, 0x39, 0xac, 0xec, 0x3b, 0x1f, 0xeb, 0xfa, 0x37, 0x7d, 0xff, 0x57, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x69, 0x33, 0x08, 0xdb, 0xde, 0x07, 0x00, 0x00, } diff --git a/registry/service/proto/registry.micro.go b/registry/service/proto/registry.pb.micro.go similarity index 100% rename from registry/service/proto/registry.micro.go rename to registry/service/proto/registry.pb.micro.go diff --git a/router/proto/router.pb.go b/router/proto/router.pb.go index 19813a34..4e2c4cc0 100644 --- a/router/proto/router.pb.go +++ b/router/proto/router.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: router.proto +// source: github.com/micro/go-micro/router/proto/router.proto package go_micro_router @@ -43,7 +43,7 @@ func (x AdvertType) String() string { } func (AdvertType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{0} + return fileDescriptor_2dd64c6ec344e37e, []int{0} } // EventType defines the type of event @@ -72,7 +72,7 @@ func (x EventType) String() string { } func (EventType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{1} + return fileDescriptor_2dd64c6ec344e37e, []int{1} } // Empty request @@ -86,7 +86,7 @@ func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{0} + return fileDescriptor_2dd64c6ec344e37e, []int{0} } func (m *Request) XXX_Unmarshal(b []byte) error { @@ -118,7 +118,7 @@ func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{1} + return fileDescriptor_2dd64c6ec344e37e, []int{1} } func (m *Response) XXX_Unmarshal(b []byte) error { @@ -151,7 +151,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} } func (m *ListResponse) String() string { return proto.CompactTextString(m) } func (*ListResponse) ProtoMessage() {} func (*ListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{2} + return fileDescriptor_2dd64c6ec344e37e, []int{2} } func (m *ListResponse) XXX_Unmarshal(b []byte) error { @@ -191,7 +191,7 @@ func (m *LookupRequest) Reset() { *m = LookupRequest{} } func (m *LookupRequest) String() string { return proto.CompactTextString(m) } func (*LookupRequest) ProtoMessage() {} func (*LookupRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{3} + return fileDescriptor_2dd64c6ec344e37e, []int{3} } func (m *LookupRequest) XXX_Unmarshal(b []byte) error { @@ -231,7 +231,7 @@ func (m *LookupResponse) Reset() { *m = LookupResponse{} } func (m *LookupResponse) String() string { return proto.CompactTextString(m) } func (*LookupResponse) ProtoMessage() {} func (*LookupResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{4} + return fileDescriptor_2dd64c6ec344e37e, []int{4} } func (m *LookupResponse) XXX_Unmarshal(b []byte) error { @@ -271,7 +271,7 @@ func (m *QueryRequest) Reset() { *m = QueryRequest{} } func (m *QueryRequest) String() string { return proto.CompactTextString(m) } func (*QueryRequest) ProtoMessage() {} func (*QueryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{5} + return fileDescriptor_2dd64c6ec344e37e, []int{5} } func (m *QueryRequest) XXX_Unmarshal(b []byte) error { @@ -311,7 +311,7 @@ func (m *QueryResponse) Reset() { *m = QueryResponse{} } func (m *QueryResponse) String() string { return proto.CompactTextString(m) } func (*QueryResponse) ProtoMessage() {} func (*QueryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{6} + return fileDescriptor_2dd64c6ec344e37e, []int{6} } func (m *QueryResponse) XXX_Unmarshal(b []byte) error { @@ -350,7 +350,7 @@ func (m *WatchRequest) Reset() { *m = WatchRequest{} } func (m *WatchRequest) String() string { return proto.CompactTextString(m) } func (*WatchRequest) ProtoMessage() {} func (*WatchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{7} + return fileDescriptor_2dd64c6ec344e37e, []int{7} } func (m *WatchRequest) XXX_Unmarshal(b []byte) error { @@ -392,7 +392,7 @@ func (m *Advert) Reset() { *m = Advert{} } func (m *Advert) String() string { return proto.CompactTextString(m) } func (*Advert) ProtoMessage() {} func (*Advert) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{8} + return fileDescriptor_2dd64c6ec344e37e, []int{8} } func (m *Advert) XXX_Unmarshal(b []byte) error { @@ -461,7 +461,7 @@ func (m *Solicit) Reset() { *m = Solicit{} } func (m *Solicit) String() string { return proto.CompactTextString(m) } func (*Solicit) ProtoMessage() {} func (*Solicit) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{9} + return fileDescriptor_2dd64c6ec344e37e, []int{9} } func (m *Solicit) XXX_Unmarshal(b []byte) error { @@ -500,7 +500,7 @@ func (m *ProcessResponse) Reset() { *m = ProcessResponse{} } func (m *ProcessResponse) String() string { return proto.CompactTextString(m) } func (*ProcessResponse) ProtoMessage() {} func (*ProcessResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{10} + return fileDescriptor_2dd64c6ec344e37e, []int{10} } func (m *ProcessResponse) XXX_Unmarshal(b []byte) error { @@ -532,7 +532,7 @@ func (m *CreateResponse) Reset() { *m = CreateResponse{} } func (m *CreateResponse) String() string { return proto.CompactTextString(m) } func (*CreateResponse) ProtoMessage() {} func (*CreateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{11} + return fileDescriptor_2dd64c6ec344e37e, []int{11} } func (m *CreateResponse) XXX_Unmarshal(b []byte) error { @@ -564,7 +564,7 @@ func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } func (*DeleteResponse) ProtoMessage() {} func (*DeleteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{12} + return fileDescriptor_2dd64c6ec344e37e, []int{12} } func (m *DeleteResponse) XXX_Unmarshal(b []byte) error { @@ -596,7 +596,7 @@ func (m *UpdateResponse) Reset() { *m = UpdateResponse{} } func (m *UpdateResponse) String() string { return proto.CompactTextString(m) } func (*UpdateResponse) ProtoMessage() {} func (*UpdateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{13} + return fileDescriptor_2dd64c6ec344e37e, []int{13} } func (m *UpdateResponse) XXX_Unmarshal(b []byte) error { @@ -634,7 +634,7 @@ func (m *Event) Reset() { *m = Event{} } func (m *Event) String() string { return proto.CompactTextString(m) } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{14} + return fileDescriptor_2dd64c6ec344e37e, []int{14} } func (m *Event) XXX_Unmarshal(b []byte) error { @@ -693,7 +693,7 @@ func (m *Query) Reset() { *m = Query{} } func (m *Query) String() string { return proto.CompactTextString(m) } func (*Query) ProtoMessage() {} func (*Query) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{15} + return fileDescriptor_2dd64c6ec344e37e, []int{15} } func (m *Query) XXX_Unmarshal(b []byte) error { @@ -760,7 +760,7 @@ func (m *Route) Reset() { *m = Route{} } func (m *Route) String() string { return proto.CompactTextString(m) } func (*Route) ProtoMessage() {} func (*Route) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{16} + return fileDescriptor_2dd64c6ec344e37e, []int{16} } func (m *Route) XXX_Unmarshal(b []byte) error { @@ -842,7 +842,7 @@ func (m *Status) Reset() { *m = Status{} } func (m *Status) String() string { return proto.CompactTextString(m) } func (*Status) ProtoMessage() {} func (*Status) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{17} + return fileDescriptor_2dd64c6ec344e37e, []int{17} } func (m *Status) XXX_Unmarshal(b []byte) error { @@ -888,7 +888,7 @@ func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (m *StatusResponse) String() string { return proto.CompactTextString(m) } func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_367072455c71aedc, []int{18} + return fileDescriptor_2dd64c6ec344e37e, []int{18} } func (m *StatusResponse) XXX_Unmarshal(b []byte) error { @@ -940,53 +940,56 @@ func init() { proto.RegisterType((*StatusResponse)(nil), "go.micro.router.StatusResponse") } -func init() { proto.RegisterFile("router.proto", fileDescriptor_367072455c71aedc) } - -var fileDescriptor_367072455c71aedc = []byte{ - // 714 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcd, 0x4e, 0xdb, 0x40, - 0x10, 0xb6, 0x93, 0xd8, 0x69, 0xa6, 0x21, 0xa4, 0xa3, 0x0a, 0x4c, 0x5a, 0x20, 0xf2, 0x09, 0x21, - 0x64, 0xaa, 0xf4, 0xda, 0x1f, 0x02, 0xa5, 0xaa, 0x54, 0x0e, 0xad, 0x01, 0xf5, 0x6c, 0xec, 0x15, - 0xb5, 0x48, 0xbc, 0x66, 0x77, 0x03, 0xca, 0xb9, 0x4f, 0xd3, 0x4b, 0x2f, 0x7d, 0xa4, 0xbe, 0x48, - 0xe5, 0xdd, 0x75, 0x08, 0x71, 0x16, 0x09, 0x4e, 0xd9, 0xf9, 0xfb, 0x66, 0x66, 0xf7, 0x9b, 0x71, - 0xa0, 0xcd, 0xe8, 0x44, 0x10, 0x16, 0xe4, 0x8c, 0x0a, 0x8a, 0xab, 0x97, 0x34, 0x18, 0xa7, 0x31, - 0xa3, 0x81, 0x52, 0xfb, 0x2d, 0x68, 0x86, 0xe4, 0x7a, 0x42, 0xb8, 0xf0, 0x01, 0x9e, 0x85, 0x84, - 0xe7, 0x34, 0xe3, 0xc4, 0xff, 0x00, 0xed, 0x93, 0x94, 0x8b, 0x52, 0xc6, 0x00, 0x5c, 0x19, 0xc0, - 0x3d, 0xbb, 0x5f, 0xdf, 0x79, 0x3e, 0x58, 0x0b, 0x16, 0x80, 0x82, 0xb0, 0xf8, 0x09, 0xb5, 0x97, - 0xff, 0x1e, 0x56, 0x4e, 0x28, 0xbd, 0x9a, 0xe4, 0x1a, 0x1c, 0xf7, 0xc0, 0xb9, 0x9e, 0x10, 0x36, - 0xf5, 0xec, 0xbe, 0xbd, 0x34, 0xfe, 0x7b, 0x61, 0x0d, 0x95, 0x93, 0x7f, 0x00, 0x9d, 0x32, 0xfc, - 0x89, 0x05, 0xbc, 0x83, 0xb6, 0x42, 0x7c, 0x52, 0xfe, 0x8f, 0xb0, 0xa2, 0xa3, 0x9f, 0x98, 0xbe, - 0x03, 0xed, 0x1f, 0x91, 0x88, 0x7f, 0x96, 0x77, 0xfb, 0xdb, 0x06, 0x77, 0x98, 0xdc, 0x10, 0x26, - 0xb0, 0x03, 0xb5, 0x34, 0x91, 0x65, 0xb4, 0xc2, 0x5a, 0x9a, 0xe0, 0x3e, 0x34, 0xc4, 0x34, 0x27, - 0x5e, 0xad, 0x6f, 0xef, 0x74, 0x06, 0xaf, 0x2a, 0xc0, 0x2a, 0xec, 0x6c, 0x9a, 0x93, 0x50, 0x3a, - 0xe2, 0x6b, 0x68, 0x89, 0x74, 0x4c, 0xb8, 0x88, 0xc6, 0xb9, 0x57, 0xef, 0xdb, 0x3b, 0xf5, 0xf0, - 0x4e, 0x81, 0x5d, 0xa8, 0x0b, 0x31, 0xf2, 0x1a, 0x52, 0x5f, 0x1c, 0x8b, 0xda, 0xc9, 0x0d, 0xc9, - 0x04, 0xf7, 0x1c, 0x43, 0xed, 0xc7, 0x85, 0x39, 0xd4, 0x5e, 0xfe, 0x06, 0x34, 0x4f, 0xe9, 0x28, - 0x8d, 0xd3, 0x4a, 0xad, 0xfe, 0x0b, 0x58, 0xfd, 0xc6, 0x68, 0x4c, 0x38, 0x9f, 0x31, 0xa5, 0x0b, - 0x9d, 0x23, 0x46, 0x22, 0x41, 0xe6, 0x35, 0x9f, 0xc8, 0x88, 0xdc, 0xd7, 0x9c, 0xe7, 0xc9, 0xbc, - 0xcf, 0x2f, 0x1b, 0x1c, 0x99, 0x15, 0x03, 0xdd, 0xbe, 0x2d, 0xdb, 0xef, 0x2d, 0xaf, 0xcd, 0xd4, - 0x7d, 0x6d, 0xb1, 0xfb, 0x3d, 0x70, 0x64, 0x9c, 0xbc, 0x17, 0xf3, 0x33, 0x29, 0x27, 0xff, 0x1c, - 0x1c, 0xf9, 0xcc, 0xe8, 0x41, 0x93, 0x13, 0x76, 0x93, 0xc6, 0x44, 0x37, 0x5b, 0x8a, 0x85, 0xe5, - 0x32, 0x12, 0xe4, 0x36, 0x9a, 0xca, 0x64, 0xad, 0xb0, 0x14, 0x0b, 0x4b, 0x46, 0xc4, 0x2d, 0x65, - 0x57, 0x32, 0x59, 0x2b, 0x2c, 0x45, 0xff, 0xaf, 0x0d, 0x8e, 0xcc, 0xf3, 0x30, 0x6e, 0x94, 0x24, - 0x8c, 0x70, 0x5e, 0xe2, 0x6a, 0x71, 0x3e, 0x63, 0xdd, 0x98, 0xb1, 0x71, 0x2f, 0x23, 0xae, 0x69, - 0x7a, 0x32, 0xcf, 0x91, 0x06, 0x2d, 0x21, 0x42, 0x63, 0x94, 0x66, 0x57, 0x9e, 0x2b, 0xb5, 0xf2, - 0x5c, 0xf8, 0x8e, 0x89, 0x60, 0x69, 0xec, 0x35, 0xe5, 0xed, 0x69, 0xc9, 0x1f, 0x80, 0x7b, 0x2a, - 0x22, 0x31, 0xe1, 0x45, 0x54, 0x4c, 0x93, 0xb2, 0x64, 0x79, 0xc6, 0x97, 0xe0, 0x10, 0xc6, 0x28, - 0xd3, 0xd5, 0x2a, 0xc1, 0x1f, 0x42, 0x47, 0xc5, 0xcc, 0x06, 0x65, 0x1f, 0x5c, 0x2e, 0x35, 0x7a, - 0xd0, 0xd6, 0x2b, 0x2f, 0xa0, 0x03, 0xb4, 0xdb, 0xee, 0x00, 0xe0, 0x8e, 0xe1, 0x88, 0xd0, 0x51, - 0xd2, 0x30, 0xcb, 0xe8, 0x24, 0x8b, 0x49, 0xd7, 0xc2, 0x2e, 0xb4, 0x95, 0x4e, 0x71, 0xa8, 0x6b, - 0xef, 0xee, 0x43, 0x6b, 0x46, 0x0b, 0x04, 0x70, 0x15, 0x01, 0xbb, 0x56, 0x71, 0x56, 0xd4, 0xeb, - 0xda, 0xc5, 0x59, 0x07, 0xd4, 0x06, 0x7f, 0xea, 0xe0, 0x86, 0xea, 0x4a, 0xbe, 0x82, 0xab, 0x56, - 0x0b, 0x6e, 0x55, 0x4a, 0xbb, 0xb7, 0xb2, 0x7a, 0xdb, 0x46, 0xbb, 0x26, 0xb1, 0x85, 0x87, 0xe0, - 0xc8, 0x31, 0xc7, 0xcd, 0x8a, 0xef, 0xfc, 0xf8, 0xf7, 0x0c, 0x23, 0xe7, 0x5b, 0x6f, 0x6c, 0x3c, - 0x84, 0x96, 0x6a, 0x2f, 0xe5, 0x04, 0xbd, 0x2a, 0x61, 0x35, 0xc4, 0xba, 0x61, 0x31, 0x48, 0x8c, - 0x83, 0xbb, 0x91, 0x35, 0x23, 0x6c, 0x2c, 0xb1, 0xcc, 0x3a, 0xf9, 0x0c, 0x4d, 0x3d, 0xd9, 0x68, - 0xca, 0xd4, 0xeb, 0x57, 0x0c, 0x8b, 0xcb, 0xc0, 0xc2, 0xe3, 0x19, 0x8b, 0xcc, 0x85, 0x6c, 0x9b, - 0x38, 0x31, 0x83, 0x19, 0xfc, 0xab, 0x81, 0x73, 0x16, 0x5d, 0x8c, 0x08, 0x1e, 0x95, 0xcf, 0x8b, - 0x86, 0x61, 0x5e, 0x02, 0xb7, 0xb0, 0x90, 0xac, 0x02, 0x44, 0xf1, 0xe2, 0x11, 0x20, 0x0b, 0x3b, - 0x4c, 0x82, 0x28, 0x42, 0x3d, 0x02, 0x64, 0x61, 0xed, 0x59, 0x38, 0x84, 0x46, 0xf1, 0x61, 0x7d, - 0xe0, 0x76, 0xaa, 0x54, 0x9a, 0xff, 0x12, 0xfb, 0x16, 0x7e, 0x29, 0xb7, 0xd6, 0xa6, 0xe1, 0x23, - 0xa6, 0x81, 0xb6, 0x4c, 0xe6, 0x12, 0xe9, 0xc2, 0x95, 0x7f, 0x0a, 0xde, 0xfe, 0x0f, 0x00, 0x00, - 0xff, 0xff, 0xb7, 0x25, 0xac, 0xac, 0x24, 0x08, 0x00, 0x00, +func init() { + proto.RegisterFile("github.com/micro/go-micro/router/proto/router.proto", fileDescriptor_2dd64c6ec344e37e) +} + +var fileDescriptor_2dd64c6ec344e37e = []byte{ + // 736 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x4f, 0x4f, 0xdb, 0x4a, + 0x10, 0xb7, 0x93, 0xd8, 0x79, 0x99, 0x17, 0x42, 0xde, 0xe8, 0x09, 0x4c, 0xde, 0x03, 0x22, 0x9f, + 0x10, 0xa2, 0x4e, 0x15, 0xae, 0xfd, 0x43, 0xa0, 0x54, 0x95, 0xca, 0xa1, 0x35, 0xa0, 0x9e, 0x8d, + 0xb3, 0x0a, 0x16, 0x49, 0xd6, 0xec, 0xae, 0x41, 0x39, 0xf7, 0xd3, 0xf4, 0xd2, 0x4b, 0x3f, 0x52, + 0xbf, 0x48, 0xe5, 0xdd, 0x75, 0x08, 0x71, 0x16, 0x09, 0x4e, 0xd9, 0xf9, 0xf7, 0x9b, 0x99, 0xdd, + 0xdf, 0x8c, 0x03, 0x87, 0xa3, 0x44, 0x5c, 0x67, 0x57, 0x41, 0x4c, 0x27, 0xbd, 0x49, 0x12, 0x33, + 0xda, 0x1b, 0xd1, 0x57, 0xea, 0xc0, 0x68, 0x26, 0x08, 0xeb, 0xa5, 0x8c, 0x8a, 0x42, 0x08, 0xa4, + 0x80, 0xeb, 0x23, 0x1a, 0x48, 0x9f, 0x40, 0xa9, 0xfd, 0x06, 0xd4, 0x43, 0x72, 0x9b, 0x11, 0x2e, + 0x7c, 0x80, 0xbf, 0x42, 0xc2, 0x53, 0x3a, 0xe5, 0xc4, 0x7f, 0x07, 0xcd, 0xb3, 0x84, 0x8b, 0x42, + 0xc6, 0x00, 0x5c, 0x19, 0xc0, 0x3d, 0xbb, 0x5b, 0xdd, 0xfb, 0xbb, 0xbf, 0x11, 0x2c, 0x01, 0x05, + 0x61, 0xfe, 0x13, 0x6a, 0x2f, 0xff, 0x2d, 0xac, 0x9d, 0x51, 0x7a, 0x93, 0xa5, 0x1a, 0x1c, 0x0f, + 0xc0, 0xb9, 0xcd, 0x08, 0x9b, 0x79, 0x76, 0xd7, 0x5e, 0x19, 0xff, 0x35, 0xb7, 0x86, 0xca, 0xc9, + 0x3f, 0x82, 0x56, 0x11, 0xfe, 0xc2, 0x02, 0xde, 0x40, 0x53, 0x21, 0xbe, 0x28, 0xff, 0x7b, 0x58, + 0xd3, 0xd1, 0x2f, 0x4c, 0xdf, 0x82, 0xe6, 0xb7, 0x48, 0xc4, 0xd7, 0xc5, 0xdd, 0xfe, 0xb0, 0xc1, + 0x1d, 0x0c, 0xef, 0x08, 0x13, 0xd8, 0x82, 0x4a, 0x32, 0x94, 0x65, 0x34, 0xc2, 0x4a, 0x32, 0xc4, + 0x1e, 0xd4, 0xc4, 0x2c, 0x25, 0x5e, 0xa5, 0x6b, 0xef, 0xb5, 0xfa, 0xff, 0x95, 0x80, 0x55, 0xd8, + 0xc5, 0x2c, 0x25, 0xa1, 0x74, 0xc4, 0xff, 0xa1, 0x21, 0x92, 0x09, 0xe1, 0x22, 0x9a, 0xa4, 0x5e, + 0xb5, 0x6b, 0xef, 0x55, 0xc3, 0x07, 0x05, 0xb6, 0xa1, 0x2a, 0xc4, 0xd8, 0xab, 0x49, 0x7d, 0x7e, + 0xcc, 0x6b, 0x27, 0x77, 0x64, 0x2a, 0xb8, 0xe7, 0x18, 0x6a, 0x3f, 0xcd, 0xcd, 0xa1, 0xf6, 0xf2, + 0xb7, 0xa0, 0x7e, 0x4e, 0xc7, 0x49, 0x9c, 0x94, 0x6a, 0xf5, 0xff, 0x81, 0xf5, 0x2f, 0x8c, 0xc6, + 0x84, 0xf3, 0x39, 0x53, 0xda, 0xd0, 0x3a, 0x61, 0x24, 0x12, 0x64, 0x51, 0xf3, 0x81, 0x8c, 0xc9, + 0x63, 0xcd, 0x65, 0x3a, 0x5c, 0xf4, 0xf9, 0x6e, 0x83, 0x23, 0xb3, 0x62, 0xa0, 0xdb, 0xb7, 0x65, + 0xfb, 0x9d, 0xd5, 0xb5, 0x99, 0xba, 0xaf, 0x2c, 0x77, 0x7f, 0x00, 0x8e, 0x8c, 0x93, 0xf7, 0x62, + 0x7e, 0x26, 0xe5, 0xe4, 0x5f, 0x82, 0x23, 0x9f, 0x19, 0x3d, 0xa8, 0x73, 0xc2, 0xee, 0x92, 0x98, + 0xe8, 0x66, 0x0b, 0x31, 0xb7, 0x8c, 0x22, 0x41, 0xee, 0xa3, 0x99, 0x4c, 0xd6, 0x08, 0x0b, 0x31, + 0xb7, 0x4c, 0x89, 0xb8, 0xa7, 0xec, 0x46, 0x26, 0x6b, 0x84, 0x85, 0xe8, 0xff, 0xb2, 0xc1, 0x91, + 0x79, 0x9e, 0xc6, 0x8d, 0x86, 0x43, 0x46, 0x38, 0x2f, 0x70, 0xb5, 0xb8, 0x98, 0xb1, 0x6a, 0xcc, + 0x58, 0x7b, 0x94, 0x11, 0x37, 0x34, 0x3d, 0x99, 0xe7, 0x48, 0x83, 0x96, 0x10, 0xa1, 0x36, 0x4e, + 0xa6, 0x37, 0x9e, 0x2b, 0xb5, 0xf2, 0x9c, 0xfb, 0x4e, 0x88, 0x60, 0x49, 0xec, 0xd5, 0xe5, 0xed, + 0x69, 0xc9, 0xef, 0x83, 0x7b, 0x2e, 0x22, 0x91, 0xf1, 0x3c, 0x2a, 0xa6, 0xc3, 0xa2, 0x64, 0x79, + 0xc6, 0x7f, 0xc1, 0x21, 0x8c, 0x51, 0xa6, 0xab, 0x55, 0x82, 0x3f, 0x80, 0x96, 0x8a, 0x99, 0x0f, + 0x4a, 0x0f, 0x5c, 0x2e, 0x35, 0x7a, 0xd0, 0x36, 0x4b, 0x2f, 0xa0, 0x03, 0xb4, 0xdb, 0x7e, 0x1f, + 0xe0, 0x81, 0xe1, 0x88, 0xd0, 0x52, 0xd2, 0x60, 0x3a, 0xa5, 0xd9, 0x34, 0x26, 0x6d, 0x0b, 0xdb, + 0xd0, 0x54, 0x3a, 0xc5, 0xa1, 0xb6, 0xbd, 0xdf, 0x83, 0xc6, 0x9c, 0x16, 0x08, 0xe0, 0x2a, 0x02, + 0xb6, 0xad, 0xfc, 0xac, 0xa8, 0xd7, 0xb6, 0xf3, 0xb3, 0x0e, 0xa8, 0xf4, 0x7f, 0x56, 0xc1, 0x0d, + 0xd5, 0x95, 0x7c, 0x06, 0x57, 0xad, 0x16, 0xdc, 0x29, 0x95, 0xf6, 0x68, 0x65, 0x75, 0x76, 0x8d, + 0x76, 0x4d, 0x62, 0x0b, 0x8f, 0xc1, 0x91, 0x63, 0x8e, 0xdb, 0x25, 0xdf, 0xc5, 0xf1, 0xef, 0x18, + 0x46, 0xce, 0xb7, 0x5e, 0xdb, 0x78, 0x0c, 0x0d, 0xd5, 0x5e, 0xc2, 0x09, 0x7a, 0x65, 0xc2, 0x6a, + 0x88, 0x4d, 0xc3, 0x62, 0x90, 0x18, 0x47, 0x0f, 0x23, 0x6b, 0x46, 0xd8, 0x5a, 0x61, 0x99, 0x77, + 0xf2, 0x11, 0xea, 0x7a, 0xb2, 0xd1, 0x94, 0xa9, 0xd3, 0x2d, 0x19, 0x96, 0x97, 0x81, 0x85, 0xa7, + 0x73, 0x16, 0x99, 0x0b, 0xd9, 0x35, 0x71, 0x62, 0x0e, 0xd3, 0xff, 0x5d, 0x01, 0xe7, 0x22, 0xba, + 0x1a, 0x13, 0x3c, 0x29, 0x9e, 0x17, 0x0d, 0xc3, 0xbc, 0x02, 0x6e, 0x69, 0x21, 0x59, 0x39, 0x88, + 0xe2, 0xc5, 0x33, 0x40, 0x96, 0x76, 0x98, 0x04, 0x51, 0x84, 0x7a, 0x06, 0xc8, 0xd2, 0xda, 0xb3, + 0x70, 0x00, 0xb5, 0xfc, 0xc3, 0xfa, 0xc4, 0xed, 0x94, 0xa9, 0xb4, 0xf8, 0x25, 0xf6, 0x2d, 0xfc, + 0x54, 0x6c, 0xad, 0x6d, 0xc3, 0x47, 0x4c, 0x03, 0xed, 0x98, 0xcc, 0x05, 0xd2, 0x95, 0x2b, 0xff, + 0x14, 0x1c, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0x47, 0x98, 0xd8, 0x20, 0x4b, 0x08, 0x00, 0x00, } diff --git a/router/proto/router.micro.go b/router/proto/router.pb.micro.go similarity index 99% rename from router/proto/router.micro.go rename to router/proto/router.pb.micro.go index a27af9e6..024989b9 100644 --- a/router/proto/router.micro.go +++ b/router/proto/router.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: router.proto +// source: github.com/micro/go-micro/router/proto/router.proto package go_micro_router diff --git a/server/proto/server.pb.go b/server/proto/server.pb.go index e3b8d327..bcd86b46 100644 --- a/server/proto/server.pb.go +++ b/server/proto/server.pb.go @@ -1,13 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: micro/go-micro/server/proto/server.proto +// source: github.com/micro/go-micro/server/proto/server.proto package go_micro_server import ( - context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" math "math" ) @@ -35,7 +33,7 @@ func (m *HandleRequest) Reset() { *m = HandleRequest{} } func (m *HandleRequest) String() string { return proto.CompactTextString(m) } func (*HandleRequest) ProtoMessage() {} func (*HandleRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_aabeb7f1c6b4fe84, []int{0} + return fileDescriptor_4cb0c66620400ff8, []int{0} } func (m *HandleRequest) XXX_Unmarshal(b []byte) error { @@ -87,7 +85,7 @@ func (m *HandleResponse) Reset() { *m = HandleResponse{} } func (m *HandleResponse) String() string { return proto.CompactTextString(m) } func (*HandleResponse) ProtoMessage() {} func (*HandleResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_aabeb7f1c6b4fe84, []int{1} + return fileDescriptor_4cb0c66620400ff8, []int{1} } func (m *HandleResponse) XXX_Unmarshal(b []byte) error { @@ -119,7 +117,7 @@ func (m *SubscribeRequest) Reset() { *m = SubscribeRequest{} } func (m *SubscribeRequest) String() string { return proto.CompactTextString(m) } func (*SubscribeRequest) ProtoMessage() {} func (*SubscribeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_aabeb7f1c6b4fe84, []int{2} + return fileDescriptor_4cb0c66620400ff8, []int{2} } func (m *SubscribeRequest) XXX_Unmarshal(b []byte) error { @@ -157,7 +155,7 @@ func (m *SubscribeResponse) Reset() { *m = SubscribeResponse{} } func (m *SubscribeResponse) String() string { return proto.CompactTextString(m) } func (*SubscribeResponse) ProtoMessage() {} func (*SubscribeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_aabeb7f1c6b4fe84, []int{3} + return fileDescriptor_4cb0c66620400ff8, []int{3} } func (m *SubscribeResponse) XXX_Unmarshal(b []byte) error { @@ -186,129 +184,24 @@ func init() { } func init() { - proto.RegisterFile("micro/go-micro/server/proto/server.proto", fileDescriptor_aabeb7f1c6b4fe84) + proto.RegisterFile("github.com/micro/go-micro/server/proto/server.proto", fileDescriptor_4cb0c66620400ff8) } -var fileDescriptor_aabeb7f1c6b4fe84 = []byte{ - // 228 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xcd, 0x4e, 0xc4, 0x20, - 0x14, 0x85, 0xad, 0xc6, 0xea, 0xdc, 0x44, 0x1d, 0xd1, 0x05, 0xe9, 0xc2, 0x1f, 0x56, 0xdd, 0xc8, - 0x24, 0xfa, 0x12, 0x26, 0xee, 0x66, 0x7c, 0x81, 0x29, 0xbd, 0x69, 0x48, 0x2a, 0x17, 0x81, 0xfa, - 0x52, 0xbe, 0xa4, 0x29, 0x94, 0x46, 0x6b, 0x74, 0xc7, 0xc7, 0x39, 0xdc, 0x73, 0x2e, 0x50, 0xbf, - 0x69, 0xe5, 0x68, 0xd3, 0xd1, 0x43, 0x3a, 0x78, 0x74, 0x1f, 0xe8, 0x36, 0xd6, 0x51, 0xc8, 0x20, - 0x23, 0xb0, 0x8b, 0x8e, 0x64, 0xf4, 0xc8, 0x74, 0x2d, 0xf6, 0x70, 0xf6, 0xbc, 0x37, 0x6d, 0x8f, - 0x5b, 0x7c, 0x1f, 0xd0, 0x07, 0xc6, 0xe1, 0x64, 0x94, 0xb4, 0x42, 0x5e, 0xdc, 0x15, 0xf5, 0x6a, - 0x9b, 0x91, 0x55, 0x70, 0x8a, 0xa6, 0xb5, 0xa4, 0x4d, 0xe0, 0x87, 0x51, 0x9a, 0x79, 0xd4, 0x62, - 0x80, 0xa2, 0x9e, 0x1f, 0x25, 0x2d, 0xb3, 0x58, 0xc3, 0x79, 0x8e, 0xf0, 0x96, 0x8c, 0x47, 0x51, - 0xc3, 0x7a, 0x37, 0x34, 0x5e, 0x39, 0xdd, 0xcc, 0xb9, 0xd7, 0x70, 0x1c, 0xc8, 0x6a, 0x35, 0xa5, - 0x26, 0x10, 0x57, 0x70, 0xf9, 0xcd, 0x99, 0x9e, 0x3f, 0x7e, 0x16, 0x50, 0xee, 0x62, 0x7d, 0xf6, - 0x02, 0x65, 0x9a, 0xcd, 0x6e, 0xe4, 0x62, 0x35, 0xf9, 0x63, 0xaf, 0xea, 0xf6, 0x4f, 0x7d, 0x2a, - 0x75, 0xc0, 0x5e, 0x61, 0x35, 0x87, 0xb1, 0xfb, 0x5f, 0xfe, 0x65, 0xe5, 0x4a, 0xfc, 0x67, 0xc9, - 0x53, 0x9b, 0x32, 0x7e, 0xc4, 0xd3, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xb8, 0x5c, 0x69, - 0xa5, 0x01, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// ServerClient is the client API for Server service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type ServerClient interface { - Handle(ctx context.Context, in *HandleRequest, opts ...grpc.CallOption) (*HandleResponse, error) - Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (*SubscribeResponse, error) -} - -type serverClient struct { - cc *grpc.ClientConn -} - -func NewServerClient(cc *grpc.ClientConn) ServerClient { - return &serverClient{cc} -} - -func (c *serverClient) Handle(ctx context.Context, in *HandleRequest, opts ...grpc.CallOption) (*HandleResponse, error) { - out := new(HandleResponse) - err := c.cc.Invoke(ctx, "/go.micro.server.Server/Handle", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *serverClient) Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (*SubscribeResponse, error) { - out := new(SubscribeResponse) - err := c.cc.Invoke(ctx, "/go.micro.server.Server/Subscribe", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// ServerServer is the server API for Server service. -type ServerServer interface { - Handle(context.Context, *HandleRequest) (*HandleResponse, error) - Subscribe(context.Context, *SubscribeRequest) (*SubscribeResponse, error) -} - -func RegisterServerServer(s *grpc.Server, srv ServerServer) { - s.RegisterService(&_Server_serviceDesc, srv) -} - -func _Server_Handle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(HandleRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ServerServer).Handle(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.server.Server/Handle", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerServer).Handle(ctx, req.(*HandleRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Server_Subscribe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SubscribeRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ServerServer).Subscribe(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.server.Server/Subscribe", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerServer).Subscribe(ctx, req.(*SubscribeRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Server_serviceDesc = grpc.ServiceDesc{ - ServiceName: "go.micro.server.Server", - HandlerType: (*ServerServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Handle", - Handler: _Server_Handle_Handler, - }, - { - MethodName: "Subscribe", - Handler: _Server_Subscribe_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "micro/go-micro/server/proto/server.proto", +var fileDescriptor_4cb0c66620400ff8 = []byte{ + // 236 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xcd, 0x4e, 0x03, 0x21, + 0x14, 0x85, 0x1d, 0x8d, 0xa3, 0xbd, 0x89, 0x5a, 0xd1, 0x05, 0x99, 0x85, 0x3f, 0xac, 0xba, 0x91, + 0x49, 0xec, 0x4b, 0x98, 0xb8, 0x6b, 0x7d, 0x81, 0x42, 0x6f, 0x46, 0x92, 0x96, 0x8b, 0xc0, 0xf8, + 0x52, 0xbe, 0xa4, 0x29, 0x94, 0x89, 0x8e, 0xb1, 0x3b, 0x3e, 0xce, 0xe1, 0x9e, 0x73, 0x81, 0x79, + 0x67, 0xe2, 0x7b, 0xaf, 0xa4, 0xa6, 0x6d, 0xbb, 0x35, 0xda, 0x53, 0xdb, 0xd1, 0x53, 0x3e, 0x04, + 0xf4, 0x9f, 0xe8, 0x5b, 0xe7, 0x29, 0x16, 0x90, 0x09, 0xd8, 0x55, 0x47, 0x32, 0x79, 0x64, 0xbe, + 0x16, 0x2b, 0xb8, 0x78, 0x59, 0xd9, 0xf5, 0x06, 0x17, 0xf8, 0xd1, 0x63, 0x88, 0x8c, 0xc3, 0xd9, + 0x4e, 0x32, 0x1a, 0x79, 0xf5, 0x50, 0xcd, 0x26, 0x8b, 0x82, 0xac, 0x81, 0x73, 0xb4, 0x6b, 0x47, + 0xc6, 0x46, 0x7e, 0x9c, 0xa4, 0x81, 0x77, 0x5a, 0x0a, 0xd0, 0xb4, 0xe1, 0x27, 0x59, 0x2b, 0x2c, + 0xa6, 0x70, 0x59, 0x22, 0x82, 0x23, 0x1b, 0x50, 0xcc, 0x60, 0xba, 0xec, 0x55, 0xd0, 0xde, 0xa8, + 0x21, 0xf7, 0x16, 0x4e, 0x23, 0x39, 0xa3, 0xf7, 0xa9, 0x19, 0xc4, 0x0d, 0x5c, 0xff, 0x70, 0xe6, + 0xe7, 0xcf, 0x5f, 0x15, 0xd4, 0xcb, 0x54, 0x9f, 0xbd, 0x42, 0x9d, 0x67, 0xb3, 0x3b, 0x39, 0x5a, + 0x4d, 0xfe, 0xda, 0xab, 0xb9, 0xff, 0x57, 0xdf, 0x97, 0x3a, 0x62, 0x6f, 0x30, 0x19, 0xc2, 0xd8, + 0xe3, 0x1f, 0xff, 0xb8, 0x72, 0x23, 0x0e, 0x59, 0xca, 0x54, 0x55, 0xa7, 0x8f, 0x98, 0x7f, 0x07, + 0x00, 0x00, 0xff, 0xff, 0x30, 0xd3, 0x7a, 0x91, 0xb0, 0x01, 0x00, 0x00, } diff --git a/server/proto/server.micro.go b/server/proto/server.pb.micro.go similarity index 97% rename from server/proto/server.micro.go rename to server/proto/server.pb.micro.go index 2f95eaf6..77194020 100644 --- a/server/proto/server.micro.go +++ b/server/proto/server.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: micro/go-micro/server/proto/server.proto +// source: github.com/micro/go-micro/server/proto/server.proto package go_micro_server diff --git a/store/service/proto/store.pb.go b/store/service/proto/store.pb.go index 6b8ddb04..8aaa8a3f 100644 --- a/store/service/proto/store.pb.go +++ b/store/service/proto/store.pb.go @@ -4,10 +4,8 @@ package go_micro_store import ( - context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" math "math" ) @@ -417,202 +415,3 @@ var fileDescriptor_f84ccc98e143ed3e = []byte{ 0xb1, 0x24, 0xdd, 0xc8, 0xa3, 0x7f, 0xb2, 0xab, 0x9d, 0xa3, 0x5e, 0x5c, 0xf3, 0x6f, 0x5f, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x30, 0x48, 0x25, 0x2d, 0x0d, 0x03, 0x00, 0x00, } - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// StoreClient is the client API for Store service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type StoreClient interface { - List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (Store_ListClient, error) - Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error) - Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error) - Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) -} - -type storeClient struct { - cc *grpc.ClientConn -} - -func NewStoreClient(cc *grpc.ClientConn) StoreClient { - return &storeClient{cc} -} - -func (c *storeClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (Store_ListClient, error) { - stream, err := c.cc.NewStream(ctx, &_Store_serviceDesc.Streams[0], "/go.micro.store.Store/List", opts...) - if err != nil { - return nil, err - } - x := &storeListClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Store_ListClient interface { - Recv() (*ListResponse, error) - grpc.ClientStream -} - -type storeListClient struct { - grpc.ClientStream -} - -func (x *storeListClient) Recv() (*ListResponse, error) { - m := new(ListResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *storeClient) Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error) { - out := new(ReadResponse) - err := c.cc.Invoke(ctx, "/go.micro.store.Store/Read", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *storeClient) Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error) { - out := new(WriteResponse) - err := c.cc.Invoke(ctx, "/go.micro.store.Store/Write", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *storeClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) { - out := new(DeleteResponse) - err := c.cc.Invoke(ctx, "/go.micro.store.Store/Delete", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// StoreServer is the server API for Store service. -type StoreServer interface { - List(*ListRequest, Store_ListServer) error - Read(context.Context, *ReadRequest) (*ReadResponse, error) - Write(context.Context, *WriteRequest) (*WriteResponse, error) - Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) -} - -func RegisterStoreServer(s *grpc.Server, srv StoreServer) { - s.RegisterService(&_Store_serviceDesc, srv) -} - -func _Store_List_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(ListRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(StoreServer).List(m, &storeListServer{stream}) -} - -type Store_ListServer interface { - Send(*ListResponse) error - grpc.ServerStream -} - -type storeListServer struct { - grpc.ServerStream -} - -func (x *storeListServer) Send(m *ListResponse) error { - return x.ServerStream.SendMsg(m) -} - -func _Store_Read_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ReadRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(StoreServer).Read(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.store.Store/Read", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(StoreServer).Read(ctx, req.(*ReadRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Store_Write_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(WriteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(StoreServer).Write(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.store.Store/Write", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(StoreServer).Write(ctx, req.(*WriteRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Store_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(StoreServer).Delete(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/go.micro.store.Store/Delete", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(StoreServer).Delete(ctx, req.(*DeleteRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Store_serviceDesc = grpc.ServiceDesc{ - ServiceName: "go.micro.store.Store", - HandlerType: (*StoreServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Read", - Handler: _Store_Read_Handler, - }, - { - MethodName: "Write", - Handler: _Store_Write_Handler, - }, - { - MethodName: "Delete", - Handler: _Store_Delete_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "List", - Handler: _Store_List_Handler, - ServerStreams: true, - }, - }, - Metadata: "micro/go-micro/store/service/proto/store.proto", -} diff --git a/store/service/proto/store.micro.go b/store/service/proto/store.pb.micro.go similarity index 100% rename from store/service/proto/store.micro.go rename to store/service/proto/store.pb.micro.go From 8ee31a63f12475e351ed6a2118fe1af7ca0c8c9b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 26 Nov 2019 14:20:45 +0000 Subject: [PATCH 253/344] Add debug/buffer package as a simple ring buffer --- debug/buffer/buffer.go | 58 +++++++++++++++++++++++++++++++++++++ debug/buffer/buffer_test.go | 52 +++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 debug/buffer/buffer.go create mode 100644 debug/buffer/buffer_test.go diff --git a/debug/buffer/buffer.go b/debug/buffer/buffer.go new file mode 100644 index 00000000..20856582 --- /dev/null +++ b/debug/buffer/buffer.go @@ -0,0 +1,58 @@ +// Package buffer provides a simple ring buffer for storing local data +package buffer + +import ( + "sync" +) + +type Buffer struct { + size int + sync.RWMutex + vals []interface{} +} + +func (b *Buffer) Put(v interface{}) { + b.Lock() + defer b.Unlock() + + // append to values + b.vals = append(b.vals, v) + + // trim if bigger than size required + if len(b.vals) > b.size { + b.vals = b.vals[1:] + } +} + +// Get returns the last n entries +func (b *Buffer) Get(n int) []interface{} { + // reset any invalid values + if n > b.size || n < 0 { + n = b.size + } + + b.RLock() + defer b.RUnlock() + + // create a delta + delta := b.size - n + + // if all the values are less than delta + if len(b.vals) < delta { + return b.vals + } + + // return the delta set + return b.vals[delta:] +} + +func (b *Buffer) Size() int { + return b.size +} + +// New returns a new buffer of the given size +func New(i int) *Buffer { + return &Buffer{ + size: i, + } +} diff --git a/debug/buffer/buffer_test.go b/debug/buffer/buffer_test.go new file mode 100644 index 00000000..c70935ef --- /dev/null +++ b/debug/buffer/buffer_test.go @@ -0,0 +1,52 @@ +package buffer + +import ( + "testing" +) + +func TestBuffer(t *testing.T) { + b := New(10) + + // test one value + b.Put("foo") + v := b.Get(1) + + if val := v[0].(string); val != "foo" { + t.Fatalf("expected foo got %v", val) + } + + b = New(10) + + // test 10 values + for i := 0; i < 10; i++ { + b.Put(i) + } + + v = b.Get(10) + + for i := 0; i < 10; i++ { + val := v[i].(int) + + if val != i { + t.Fatalf("expected %d got %d", i, val) + } + } + + // test more values + + for i := 0; i < 10; i++ { + v := i * 2 + b.Put(v) + } + + v = b.Get(10) + + for i := 0; i < 10; i++ { + val := v[i].(int) + expect := i * 2 + if val != expect { + t.Fatalf("expected %d got %d", expect, val) + } + } + +} From deabf0b8c93a55aa190609dfd0124cc9e52ecd7d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 26 Nov 2019 14:56:23 +0000 Subject: [PATCH 254/344] fix entry into nil map --- runtime/kubernetes/kubernetes.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index ccac8ed4..69b032b7 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -226,6 +226,9 @@ func (k *kubernetes) run(events <-chan runtime.Event) { // technically we should not receive multiple versions but hey ho for _, service := range deployed.Items { // update build time annotation + if service.Spec.Template.Metadata.Annotations == nil { + service.Spec.Template.Metadata.Annotations = make(map[string]string) + } service.Spec.Template.Metadata.Annotations["build"] = event.Timestamp.Format(time.RFC3339) log.Debugf("Runtime updating service: %s", event.Service) From 6475c1f3ada4bb8013611396af101ef6e4ebe8ea Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 26 Nov 2019 17:33:41 +0000 Subject: [PATCH 255/344] Patch spec template annotations and use event timestmap --- runtime/default.go | 71 ++++++++++++++++---------------- runtime/kubernetes/kubernetes.go | 13 +++++- runtime/kubernetes/service.go | 5 ++- runtime/service.go | 7 +++- 4 files changed, 57 insertions(+), 39 deletions(-) diff --git a/runtime/default.go b/runtime/default.go index c9c198e1..4ec72929 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -2,8 +2,6 @@ package runtime import ( "errors" - "fmt" - "strconv" "sync" "time" @@ -60,6 +58,34 @@ func (r *runtime) run(events <-chan Event) { t := time.NewTicker(time.Second * 5) defer t.Stop() + // process event processes an incoming event + processEvent := func(event Event, service *service) error { + // get current vals + r.RLock() + name := service.Name + updated := service.updated + r.RUnlock() + + // only process if the timestamp is newer + if !event.Timestamp.After(updated) { + return nil + } + + log.Debugf("Runtime updating service %s", name) + + // this will cause a delete followed by created + if err := r.Update(service.Service); err != nil { + return err + } + + // update the local timestamp + r.Lock() + service.updated = updated + r.Unlock() + + return nil + } + for { select { case <-t.C: @@ -91,36 +117,6 @@ func (r *runtime) run(events <-chan Event) { // NOTE: we only handle Update events for now switch event.Type { case Update: - // parse returned response to timestamp - updateTimeStamp, err := strconv.ParseInt(event.Version, 10, 64) - if err != nil { - log.Debugf("Runtime error parsing build time for %s: %v", event.Service, err) - continue - } - buildTime := time.Unix(updateTimeStamp, 0) - processEvent := func(event Event, service *Service) error { - r.RLock() - name := service.Name - version := service.Version - r.RUnlock() - - buildTimeStamp, err := strconv.ParseInt(version, 10, 64) - if err != nil { - return err - } - muBuild := time.Unix(buildTimeStamp, 0) - if buildTime.After(muBuild) { - log.Debugf("Runtime updating service %s", name) - if err := r.Update(service); err != nil { - return err - } - r.Lock() - service.Version = fmt.Sprintf("%d", buildTime.Unix()) - r.Unlock() - } - return nil - } - if len(event.Service) > 0 { r.RLock() service, ok := r.services[event.Service] @@ -129,14 +125,19 @@ func (r *runtime) run(events <-chan Event) { log.Debugf("Runtime unknown service: %s", event.Service) continue } - if err := processEvent(event, service.Service); err != nil { + if err := processEvent(event, service); err != nil { log.Debugf("Runtime error updating service %s: %v", event.Service, err) } continue } + + r.RLock() + services := r.services + r.RUnlock() + // if blank service was received we update all services - for _, service := range r.services { - if err := processEvent(event, service.Service); err != nil { + for _, service := range services { + if err := processEvent(event, service); err != nil { log.Debugf("Runtime error updating service %s: %v", service.Name, err) } } diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 69b032b7..29c90925 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -130,7 +130,7 @@ func (k *kubernetes) getService(labels map[string]string) ([]*runtime.Service, e } // parse out deployment build - if build, ok := kdep.Metadata.Annotations["build"]; ok { + if build, ok := kdep.Spec.Template.Metadata.Annotations["build"]; ok { buildTime, err := time.Parse(time.RFC3339, build) if err != nil { log.Debugf("Runtime failed parsing build time for %s: %v", name, err) @@ -228,7 +228,18 @@ func (k *kubernetes) run(events <-chan runtime.Event) { // update build time annotation if service.Spec.Template.Metadata.Annotations == nil { service.Spec.Template.Metadata.Annotations = make(map[string]string) + } + + // check the existing build timestamp + if build, ok := service.Spec.Template.Metadata.Annotations["build"]; ok { + buildTime, err := time.Parse(time.RFC3339, build) + if err == nil && !event.Timestamp.After(buildTime) { + continue + } + } + + // update the build time service.Spec.Template.Metadata.Annotations["build"] = event.Timestamp.Format(time.RFC3339) log.Debugf("Runtime updating service: %s", event.Service) diff --git a/runtime/kubernetes/service.go b/runtime/kubernetes/service.go index 1fcb4029..e4a5c6ad 100644 --- a/runtime/kubernetes/service.go +++ b/runtime/kubernetes/service.go @@ -36,7 +36,10 @@ func newService(s *runtime.Service, c runtime.CreateOptions) *service { kdeploy.Metadata.Annotations["group"] = "micro" // set a build timestamp to the current time - kdeploy.Metadata.Annotations["build"] = time.Now().Format(time.RFC3339) + if kdeploy.Spec.Template.Metadata.Annotations == nil { + kdeploy.Spec.Template.Metadata.Annotations = make(map[string]string) + } + kdeploy.Spec.Template.Metadata.Annotations["build"] = time.Now().Format(time.RFC3339) // define the environment values used by the container env := make([]client.EnvVar, 0, len(c.Env)) diff --git a/runtime/service.go b/runtime/service.go index cf142c16..a3945d64 100644 --- a/runtime/service.go +++ b/runtime/service.go @@ -3,6 +3,7 @@ package runtime import ( "io" "sync" + "time" "github.com/micro/go-micro/runtime/build" @@ -17,6 +18,7 @@ type service struct { running bool closed chan bool err error + updated time.Time // output for logs output io.Writer @@ -64,8 +66,9 @@ func newService(s *Service, c CreateOptions) *service { Env: c.Env, Args: args, }, - closed: make(chan bool), - output: c.Output, + closed: make(chan bool), + output: c.Output, + updated: time.Now(), } } From 3f3fd38601aef041043d2d4709bf8fec38c6e2e3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 26 Nov 2019 18:14:49 +0000 Subject: [PATCH 256/344] Add spec.template.metadata.annotations to the k8s template --- runtime/kubernetes/client/templates.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/runtime/kubernetes/client/templates.go b/runtime/kubernetes/client/templates.go index 8f960051..e3681539 100644 --- a/runtime/kubernetes/client/templates.go +++ b/runtime/kubernetes/client/templates.go @@ -40,6 +40,12 @@ spec: {{ $key }}: "{{ $value }}" {{- end }} {{- end }} + annotations: + {{- with .Spec.Template.Metadata.Annotations }} + {{- range $key, $value := . }} + {{ $key }}: "{{ $value }}" + {{- end }} + {{- end }} spec: containers: {{- with .Spec.Template.PodSpec.Containers }} From 811275be2651cb5cb2b3d820f897aa6e38750d7c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 26 Nov 2019 22:28:08 +0000 Subject: [PATCH 257/344] Add fixes for label selector and skipping things that don't match --- runtime/kubernetes/client/api/request.go | 9 ++++++++- runtime/kubernetes/client/client.go | 5 ++--- runtime/kubernetes/kubernetes.go | 12 ++++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/runtime/kubernetes/client/api/request.go b/runtime/kubernetes/client/api/request.go index bfb8b117..1b454c00 100644 --- a/runtime/kubernetes/client/api/request.go +++ b/runtime/kubernetes/client/api/request.go @@ -119,7 +119,14 @@ func (r *Request) Body(in interface{}) *Request { // Params isused to set paramters on a request func (r *Request) Params(p *Params) *Request { for k, v := range p.LabelSelector { - r.params.Add("labelSelector", k+"="+v) + // create new key=value pair + value := fmt.Sprintf("%s=%s", k, v) + // check if there's an existing value + if label := r.params.Get("labelSelector"); len(label) > 0 { + value = fmt.Sprintf("%s,%s", label, value) + } + // set and overwrite the value + r.params.Set("labelSelector", value) } return r diff --git a/runtime/kubernetes/client/client.go b/runtime/kubernetes/client/client.go index 6206ea15..4637a9d8 100644 --- a/runtime/kubernetes/client/client.go +++ b/runtime/kubernetes/client/client.go @@ -126,9 +126,9 @@ func (c *client) Update(r *Resource) error { switch r.Kind { case "service": - req.Body(r.Value.(*Service).Spec) + req.Body(r.Value.(*Service)) case "deployment": - req.Body(r.Value.(*Deployment).Spec) + req.Body(r.Value.(*Deployment)) default: return errors.New("unsupported resource") } @@ -151,6 +151,5 @@ func (c *client) List(r *Resource) error { labels := map[string]string{ "micro": "service", } - return c.Get(r, labels) } diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 29c90925..7c584eac 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -199,10 +199,13 @@ func (k *kubernetes) run(events <-chan runtime.Event) { continue } + // format the name + name := client.Format(event.Service) + // set the default labels labels := map[string]string{ "micro": "service", - "name": event.Service, + "name": name, } if len(event.Version) > 0 { @@ -225,6 +228,11 @@ func (k *kubernetes) run(events <-chan runtime.Event) { // technically we should not receive multiple versions but hey ho for _, service := range deployed.Items { + // check the name matches + if service.Metadata.Name != name { + continue + } + // update build time annotation if service.Spec.Template.Metadata.Annotations == nil { service.Spec.Template.Metadata.Annotations = make(map[string]string) @@ -242,7 +250,7 @@ func (k *kubernetes) run(events <-chan runtime.Event) { // update the build time service.Spec.Template.Metadata.Annotations["build"] = event.Timestamp.Format(time.RFC3339) - log.Debugf("Runtime updating service: %s", event.Service) + log.Debugf("Runtime updating service: %s deployment: %s", event.Service, service.Metadata.Name) if err := k.client.Update(deploymentResource(&service)); err != nil { log.Debugf("Runtime failed to update service %s: %v", event.Service, err) continue From 8ecd2381a4a9b7823849e7163d182ea5bc5d5832 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 26 Nov 2019 23:10:45 +0000 Subject: [PATCH 258/344] Remove validator regexp as its no longer needed. --- runtime/kubernetes/client/kubernetes.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index 677a2214..80b14d32 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -7,11 +7,6 @@ import ( "github.com/micro/go-micro/util/log" ) -const ( - // https://github.com/kubernetes/apimachinery/blob/master/pkg/util/validation/validation.go#L134 - dns1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?" -) - var ( // DefaultImage is default micro image DefaultImage = "micro/go-micro" From 86a63282547936d96a0dd7ec0209ba56fa7bb084 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Mon, 25 Nov 2019 22:50:59 +0300 Subject: [PATCH 259/344] subscriber recovery Signed-off-by: Vasiliy Tolstov --- server/grpc/subscriber.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/server/grpc/subscriber.go b/server/grpc/subscriber.go index 0e4f4f4f..6d987974 100644 --- a/server/grpc/subscriber.go +++ b/server/grpc/subscriber.go @@ -4,12 +4,15 @@ import ( "context" "fmt" "reflect" + "runtime/debug" "strings" "github.com/micro/go-micro/broker" + "github.com/micro/go-micro/errors" "github.com/micro/go-micro/metadata" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/server" + "github.com/micro/go-micro/util/log" ) const ( @@ -165,6 +168,16 @@ func validateSubscriber(sub server.Subscriber) error { func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broker.Handler { return func(p broker.Event) error { + var err error + + defer func() { + if r := recover(); r != nil { + log.Log("panic recovered: ", r) + log.Logf(string(debug.Stack())) + err = errors.InternalServerError("go.micro.server", "panic recovered: %v", r) + } + }() + msg := p.Message() ct := msg.Header["Content-Type"] if len(ct) == 0 { @@ -201,7 +214,7 @@ func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broke req = req.Elem() } - if err := cf.Unmarshal(msg.Body, req.Interface()); err != nil { + if err = cf.Unmarshal(msg.Body, req.Interface()); err != nil { return err } @@ -217,8 +230,8 @@ func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broke vals = append(vals, reflect.ValueOf(msg.Payload())) returnValues := handler.method.Call(vals) - if err := returnValues[0].Interface(); err != nil { - return err.(error) + if rerr := returnValues[0].Interface(); rerr != nil { + return rerr.(error) } return nil } @@ -245,14 +258,15 @@ func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broke } var errors []string for i := 0; i < len(sb.handlers); i++ { - if err := <-results; err != nil { - errors = append(errors, err.Error()) + if rerr := <-results; err != nil { + errors = append(errors, rerr.Error()) } } if len(errors) > 0 { - return fmt.Errorf("subscriber error: %s", strings.Join(errors, "\n")) + err = fmt.Errorf("subscriber error: %s", strings.Join(errors, "\n")) } - return nil + + return err } } From 266b6dbc64c52ce9d46c4576f0dcc2938734953e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 27 Nov 2019 13:57:19 +0000 Subject: [PATCH 260/344] add debug buffer time based access --- debug/buffer/buffer.go | 43 ++++++++++++++++++++++++++++++++++--- debug/buffer/buffer_test.go | 33 +++++++++++++++++++++++++--- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/debug/buffer/buffer.go b/debug/buffer/buffer.go index 20856582..8c55790c 100644 --- a/debug/buffer/buffer.go +++ b/debug/buffer/buffer.go @@ -3,12 +3,18 @@ package buffer import ( "sync" + "time" ) type Buffer struct { size int sync.RWMutex - vals []interface{} + vals []*Entry +} + +type Entry struct { + Value interface{} + Timestamp time.Time } func (b *Buffer) Put(v interface{}) { @@ -16,7 +22,10 @@ func (b *Buffer) Put(v interface{}) { defer b.Unlock() // append to values - b.vals = append(b.vals, v) + b.vals = append(b.vals, &Entry{ + Value: v, + Timestamp: time.Now(), + }) // trim if bigger than size required if len(b.vals) > b.size { @@ -25,7 +34,7 @@ func (b *Buffer) Put(v interface{}) { } // Get returns the last n entries -func (b *Buffer) Get(n int) []interface{} { +func (b *Buffer) Get(n int) []*Entry { // reset any invalid values if n > b.size || n < 0 { n = b.size @@ -46,6 +55,34 @@ func (b *Buffer) Get(n int) []interface{} { return b.vals[delta:] } +// Return the entries since a specific time +func (b *Buffer) Since(t time.Time) []*Entry { + b.RLock() + defer b.RUnlock() + + // return all the values + if t.IsZero() { + return b.vals + } + + // if its in the future return nothing + if time.Since(t).Seconds() < 0.0 { + return nil + } + + for i, v := range b.vals { + // find the starting point + d := v.Timestamp.Sub(t) + + // return the values + if d.Seconds() > 0.0 { + return b.vals[i:] + } + } + + return nil +} + func (b *Buffer) Size() int { return b.size } diff --git a/debug/buffer/buffer_test.go b/debug/buffer/buffer_test.go index c70935ef..3a107923 100644 --- a/debug/buffer/buffer_test.go +++ b/debug/buffer/buffer_test.go @@ -2,6 +2,7 @@ package buffer import ( "testing" + "time" ) func TestBuffer(t *testing.T) { @@ -11,7 +12,7 @@ func TestBuffer(t *testing.T) { b.Put("foo") v := b.Get(1) - if val := v[0].(string); val != "foo" { + if val := v[0].Value.(string); val != "foo" { t.Fatalf("expected foo got %v", val) } @@ -22,10 +23,11 @@ func TestBuffer(t *testing.T) { b.Put(i) } + d := time.Now() v = b.Get(10) for i := 0; i < 10; i++ { - val := v[i].(int) + val := v[i].Value.(int) if val != i { t.Fatalf("expected %d got %d", i, val) @@ -42,11 +44,36 @@ func TestBuffer(t *testing.T) { v = b.Get(10) for i := 0; i < 10; i++ { - val := v[i].(int) + val := v[i].Value.(int) expect := i * 2 if val != expect { t.Fatalf("expected %d got %d", expect, val) } } + // sleep 100 ms + time.Sleep(time.Millisecond * 100) + + // assume we'll get everything + v = b.Since(d) + + if len(v) != 10 { + t.Fatalf("expected 10 entries but got %d", len(v)) + } + + // write 1 more entry + d = time.Now() + b.Put(100) + + // sleep 100 ms + time.Sleep(time.Millisecond * 100) + + v = b.Since(d) + if len(v) != 1 { + t.Fatalf("expected 1 entries but got %d", len(v)) + } + + if v[0].Value.(int) != 100 { + t.Fatalf("expected value 100 got %v", v[0]) + } } From af94899b540718181a1058f48b0bfaf48f8941b2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 27 Nov 2019 17:12:07 +0000 Subject: [PATCH 261/344] Fix rpc go routine leak --- server/rpc_router.go | 14 +++ server/rpc_server.go | 185 +++++++++++++++++------------------- server/rpc_util.go | 32 +++++++ transport/http_transport.go | 8 +- util/socket/pool.go | 56 +++++++++++ util/socket/socket.go | 4 +- 6 files changed, 198 insertions(+), 101 deletions(-) create mode 100644 server/rpc_util.go create mode 100644 util/socket/pool.go diff --git a/server/rpc_router.go b/server/rpc_router.go index 493f2af7..fddce6fd 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -81,6 +81,20 @@ type router struct { subscribers map[string][]*subscriber } +// rpcRouter encapsulates functions that become a server.Router +type rpcRouter struct { + h func(context.Context, Request, interface{}) error + m func(context.Context, Message) error +} + +func (r rpcRouter) ProcessMessage(ctx context.Context, msg Message) error { + return r.m(ctx, msg) +} + +func (r rpcRouter) ServeRequest(ctx context.Context, req Request, rsp Response) error { + return r.h(ctx, req, rsp) +} + func newRpcRouter() *router { return &router{ serviceMap: make(map[string]*service), diff --git a/server/rpc_server.go b/server/rpc_server.go index 607ead53..f1c3e713 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -58,19 +58,6 @@ func newRpcServer(opts ...Option) Server { } } -type rpcRouter struct { - h func(context.Context, Request, interface{}) error - m func(context.Context, Message) error -} - -func (r rpcRouter) ProcessMessage(ctx context.Context, msg Message) error { - return r.m(ctx, msg) -} - -func (r rpcRouter) ServeRequest(ctx context.Context, req Request, rsp Response) error { - return r.h(ctx, req, rsp) -} - // HandleEvent handles inbound messages to the service directly // TODO: handle requests from an event. We won't send a response. func (s *rpcServer) HandleEvent(e broker.Event) error { @@ -141,26 +128,34 @@ func (s *rpcServer) HandleEvent(e broker.Event) error { // ServeConn serves a single connection func (s *rpcServer) ServeConn(sock transport.Socket) { - var wg sync.WaitGroup - var mtx sync.RWMutex + // global error tracking + var gerr error // streams are multiplexed on Micro-Stream or Micro-Id header - sockets := make(map[string]*socket.Socket) + pool := socket.NewPool() + + // get global waitgroup + s.Lock() + gg := s.wg + s.Unlock() + + // waitgroup to wait for processing to finish + wg := &waitGroup{ + gg: gg, + } defer func() { - // wait till done - wg.Wait() + // only wait if there's no error + if gerr == nil { + // wait till done + wg.Wait() + } + + // close all the sockets for this connection + pool.Close() // close underlying socket sock.Close() - // close the sockets - mtx.Lock() - for id, psock := range sockets { - psock.Close() - delete(sockets, id) - } - mtx.Unlock() - // recover any panics if r := recover(); r != nil { log.Log("panic recovered: ", r) @@ -170,7 +165,12 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { for { var msg transport.Message + // process inbound messages one at a time if err := sock.Recv(&msg); err != nil { + // set a global error and return + // we're saying we essentially can't + // use the socket anymore + gerr = err return } @@ -185,9 +185,12 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { msg.Header["Micro-Error"] = err.Error() } // write back some 200 - sock.Send(&transport.Message{ + if err := sock.Send(&transport.Message{ Header: msg.Header, - }) + }); err != nil { + gerr = err + break + } // we're done continue } @@ -205,57 +208,52 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { id = msg.Header["Micro-Id"] } - // we're starting processing - wg.Add(1) + // check stream id + var stream bool - // add to wait group if "wait" is opt-in - s.Lock() - swg := s.wg - s.Unlock() - - if swg != nil { - swg.Add(1) + if v := getHeader("Micro-Stream", msg.Header); len(v) > 0 { + stream = true } - // check we have an existing socket - mtx.RLock() - psock, ok := sockets[id] - mtx.RUnlock() + // check if we have an existing socket + psock, ok := pool.Get(id) - // got the socket + // if we don't have a socket and its a stream + if !ok && stream { + // check if its a last stream EOS error + err := msg.Header["Micro-Error"] + if err == lastStreamResponseError.Error() { + pool.Release(psock) + continue + } + } + + // got an existing socket already if ok { - // accept the message + // we're starting processing + wg.Add(1) + + // pass the message to that existing socket if err := psock.Accept(&msg); err != nil { - // delete the socket - mtx.Lock() - delete(sockets, id) - mtx.Unlock() - } - - // done(1) - if swg != nil { - swg.Done() + // release the socket if there's an error + pool.Release(psock) } + // done waiting wg.Done() // continue to the next message continue } - // no socket was found - psock = socket.New() + // no socket was found so its new + // set the local and remote values psock.SetLocal(sock.Local()) psock.SetRemote(sock.Remote()) - // load the socket + // load the socket with the current message psock.Accept(&msg) - // save a new socket - mtx.Lock() - sockets[id] = psock - mtx.Unlock() - // now walk the usual path // we use this Timeout header to set a server deadline @@ -292,38 +290,33 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // setup old protocol cf := setupProtocol(&msg) - // no old codec + // no legacy codec needed if cf == nil { - // TODO: needs better error handling var err error + // try get a new codec if cf, err = s.newCodec(ct); err != nil { - sock.Send(&transport.Message{ + // no codec found so send back an error + if err := sock.Send(&transport.Message{ Header: map[string]string{ "Content-Type": "text/plain", }, Body: []byte(err.Error()), - }) - - if swg != nil { - swg.Done() + }); err != nil { + gerr = err } - wg.Done() - - return + // release the socket we just created + pool.Release(psock) + // now continue + continue } } + // create a new rpc codec based on the pseudo socket and codec rcodec := newRpcCodec(&msg, psock, cf) + // check the protocol as well protocol := rcodec.String() - // check stream id - var stream bool - - if v := getHeader("Micro-Stream", msg.Header); len(v) > 0 { - stream = true - } - // internal request request := &rpcRequest{ service: getHeader("Micro-Service", msg.Header), @@ -363,11 +356,11 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { r = rpcRouter{h: handler} } - // wait for processing to exit - wg.Add(1) - // process the outbound messages from the socket go func(id string, psock *socket.Socket) { + // wait for processing to exit + wg.Add(1) + defer func() { // TODO: don't hack this but if its grpc just break out of the stream // We do this because the underlying connection is h2 and its a stream @@ -375,7 +368,9 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { case "grpc": sock.Close() } - + // release the socket + pool.Release(psock) + // signal we're done wg.Done() }() @@ -383,10 +378,6 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // get the message from our internal handler/stream m := new(transport.Message) if err := psock.Process(m); err != nil { - // delete the socket - mtx.Lock() - delete(sockets, id) - mtx.Unlock() return } @@ -399,7 +390,15 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // serve the request in a go routine as this may be a stream go func(id string, psock *socket.Socket) { - defer psock.Close() + // add to the waitgroup + wg.Add(1) + + defer func() { + // release the socket + pool.Release(psock) + // signal we're done + wg.Done() + }() // serve the actual request using the request router if serveRequestError := r.ServeRequest(ctx, request, response); serveRequestError != nil { @@ -416,21 +415,9 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // could not write error response if writeError != nil && !alreadyClosed { - log.Logf("rpc: unable to write error response: %v", writeError) + log.Debugf("rpc: unable to write error response: %v", writeError) } } - - mtx.Lock() - delete(sockets, id) - mtx.Unlock() - - // signal we're done - if swg != nil { - swg.Done() - } - - // done with this socket - wg.Done() }(id, psock) } } diff --git a/server/rpc_util.go b/server/rpc_util.go new file mode 100644 index 00000000..a15be0ac --- /dev/null +++ b/server/rpc_util.go @@ -0,0 +1,32 @@ +package server + +import ( + "sync" +) + +// waitgroup for global management of connections +type waitGroup struct { + // local waitgroup + lg sync.WaitGroup + // global waitgroup + gg *sync.WaitGroup +} + +func (w *waitGroup) Add(i int) { + w.lg.Add(i) + if w.gg != nil { + w.gg.Add(i) + } +} + +func (w *waitGroup) Done() { + w.lg.Done() + if w.gg != nil { + w.gg.Done() + } +} + +func (w *waitGroup) Wait() { + // only wait on local group + w.lg.Wait() +} diff --git a/transport/http_transport.go b/transport/http_transport.go index c9878073..1ce109aa 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -285,8 +285,14 @@ func (h *httpTransportSocket) Recv(m *Message) error { func (h *httpTransportSocket) Send(m *Message) error { if h.r.ProtoMajor == 1 { + // make copy of header + hdr := make(http.Header) + for k, v := range h.r.Header { + hdr[k] = v + } + rsp := &http.Response{ - Header: h.r.Header, + Header: hdr, Body: ioutil.NopCloser(bytes.NewReader(m.Body)), Status: "200 OK", StatusCode: 200, diff --git a/util/socket/pool.go b/util/socket/pool.go new file mode 100644 index 00000000..9439f131 --- /dev/null +++ b/util/socket/pool.go @@ -0,0 +1,56 @@ +package socket + +import ( + "sync" +) + +type Pool struct { + sync.RWMutex + pool map[string]*Socket +} + +func (p *Pool) Get(id string) (*Socket, bool) { + // attempt to get existing socket + p.RLock() + socket, ok := p.pool[id] + if ok { + p.RUnlock() + return socket, ok + } + p.RUnlock() + + // create new socket + socket = New(id) + // save socket + p.Lock() + p.pool[id] = socket + p.Unlock() + // return socket + return socket, false +} + +func (p *Pool) Release(s *Socket) { + p.Lock() + defer p.Unlock() + + // close the socket + s.Close() + delete(p.pool, s.id) +} + +// Close the pool and delete all the sockets +func (p *Pool) Close() { + p.Lock() + defer p.Unlock() + for id, sock := range p.pool { + sock.Close() + delete(p.pool, id) + } +} + +// NewPool returns a new socket pool +func NewPool() *Pool { + return &Pool{ + pool: make(map[string]*Socket), + } +} diff --git a/util/socket/socket.go b/util/socket/socket.go index 29ba5006..f536ad7d 100644 --- a/util/socket/socket.go +++ b/util/socket/socket.go @@ -9,6 +9,7 @@ import ( // Socket is our pseudo socket for transport.Socket type Socket struct { + id string // closed closed chan bool // remote addr @@ -119,8 +120,9 @@ func (s *Socket) Close() error { // New returns a new pseudo socket which can be used in the place of a transport socket. // Messages are sent to the socket via Accept and receives from the socket via Process. // SetLocal/SetRemote should be called before using the socket. -func New() *Socket { +func New(id string) *Socket { return &Socket{ + id: id, closed: make(chan bool), local: "local", remote: "remote", From c3ed83dfba2b7f146800f2286453e346ca0498d4 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 29 Nov 2019 11:35:00 +0000 Subject: [PATCH 262/344] Support service types in runtime --- runtime/default.go | 37 ++++---- runtime/kubernetes/client/kubernetes.go | 8 +- runtime/kubernetes/client/util_test.go | 5 +- runtime/kubernetes/kubernetes.go | 43 +++++---- runtime/kubernetes/service.go | 10 +-- runtime/options.go | 45 ++++++++-- runtime/runtime.go | 6 +- runtime/service.go | 21 ++--- runtime/service/handler/handler.go | 19 ++-- runtime/service/proto/runtime.pb.go | 115 +++++++++++------------- runtime/service/proto/runtime.proto | 17 ++-- runtime/service/service.go | 9 +- 12 files changed, 171 insertions(+), 164 deletions(-) diff --git a/runtime/default.go b/runtime/default.go index 4ec72929..f0c26eec 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -163,7 +163,7 @@ func (r *runtime) Create(s *Service, opts ...CreateOption) error { o(&options) } - if len(s.Exec) == 0 && len(options.Command) == 0 { + if len(options.Command) == 0 { return errors.New("missing exec command") } @@ -179,31 +179,36 @@ func (r *runtime) Create(s *Service, opts ...CreateOption) error { // Read returns all instances of requested service // If no service name is provided we return all the track services. -func (r *runtime) Read(name string, opts ...ReadOption) ([]*Service, error) { +func (r *runtime) Read(opts ...ReadOption) ([]*Service, error) { r.Lock() defer r.Unlock() - if len(name) == 0 { - return nil, errors.New("missing service name") - } - gopts := ReadOptions{} for _, o := range opts { o(&gopts) } - var services []*Service - // if we track the service check if the version is provided - if s, ok := r.services[name]; ok { - if len(gopts.Version) > 0 { - if s.Version == gopts.Version { - services = append(services, s.Service) - } - return services, nil + save := func(k, v string) bool { + if len(k) == 0 { + return true } - // no version has sbeen requested, just append the service - services = append(services, s.Service) + return k == v } + + var services []*Service + + for _, service := range r.services { + if !save(gopts.Service, service.Name) { + continue + } + if !save(gopts.Version, service.Version) { + continue + } + // TODO deal with service type + // no version has sbeen requested, just append the service + services = append(services, service.Service) + } + return services, nil } diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index 80b14d32..9a683b27 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -27,13 +27,13 @@ type Kubernetes interface { } // NewService returns default micro kubernetes service definition -func NewService(name, version string) *Service { +func NewService(name, version, typ string) *Service { log.Tracef("kubernetes default service: name: %s, version: %s", name, version) Labels := map[string]string{ "name": name, "version": version, - "micro": "service", + "micro": typ, } svcName := name @@ -64,13 +64,13 @@ func NewService(name, version string) *Service { } // NewService returns default micro kubernetes deployment definition -func NewDeployment(name, version string) *Deployment { +func NewDeployment(name, version, typ string) *Deployment { log.Tracef("kubernetes default deployment: name: %s, version: %s", name, version) Labels := map[string]string{ "name": name, "version": version, - "micro": "service", + "micro": typ, } depName := name diff --git a/runtime/kubernetes/client/util_test.go b/runtime/kubernetes/client/util_test.go index 39fb3e0c..236f3185 100644 --- a/runtime/kubernetes/client/util_test.go +++ b/runtime/kubernetes/client/util_test.go @@ -8,16 +8,17 @@ import ( func TestTemplates(t *testing.T) { name := "foo" version := "123" + typ := "service" // Render default service - s := NewService(name, version) + s := NewService(name, version, typ) bs := new(bytes.Buffer) if err := renderTemplate(templates["service"], bs, s); err != nil { t.Errorf("Failed to render kubernetes service: %v", err) } // Render default deployment - d := NewDeployment(name, version) + d := NewDeployment(name, version, typ) bd := new(bytes.Buffer) if err := renderTemplate(templates["deployment"], bd, d); err != nil { t.Errorf("Failed to render kubernetes deployment: %v", err) diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 7c584eac..c05f5890 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -2,7 +2,6 @@ package kubernetes import ( - "errors" "fmt" "sync" "time" @@ -204,7 +203,7 @@ func (k *kubernetes) run(events <-chan runtime.Event) { // set the default labels labels := map[string]string{ - "micro": "service", + "micro": k.options.Type, "name": name, } @@ -281,7 +280,9 @@ func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) er k.Lock() defer k.Unlock() - var options runtime.CreateOptions + options := runtime.CreateOptions{ + Type: k.options.Type, + } for _, o := range opts { o(&options) } @@ -310,22 +311,13 @@ func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) er } // Read returns all instances of given service -func (k *kubernetes) Read(name string, opts ...runtime.ReadOption) ([]*runtime.Service, error) { +func (k *kubernetes) Read(opts ...runtime.ReadOption) ([]*runtime.Service, error) { k.Lock() defer k.Unlock() - // if no name has been passed in, return error - if len(name) == 0 { - return nil, errors.New("missing service name") - } - - // format the name - name = client.Format(name) - // set the default labels labels := map[string]string{ - "micro": "service", - "name": name, + "micro": k.options.Type, } var options runtime.ReadOptions @@ -333,12 +325,18 @@ func (k *kubernetes) Read(name string, opts ...runtime.ReadOption) ([]*runtime.S o(&options) } + if len(options.Service) > 0 { + labels["name"] = client.Format(options.Service) + } + // add version to labels if a version has been supplied if len(options.Version) > 0 { labels["version"] = options.Version } - log.Debugf("Runtime querying service %s", name) + if len(options.Type) > 0 { + labels["type"] = options.Type + } return k.getService(labels) } @@ -349,7 +347,7 @@ func (k *kubernetes) List() ([]*runtime.Service, error) { defer k.Unlock() labels := map[string]string{ - "micro": "service", + "micro": k.options.Type, } log.Debugf("Runtime listing all micro services") @@ -360,7 +358,9 @@ func (k *kubernetes) List() ([]*runtime.Service, error) { // Update the service in place func (k *kubernetes) Update(s *runtime.Service) error { // create new kubernetes micro service - service := newService(s, runtime.CreateOptions{}) + service := newService(s, runtime.CreateOptions{ + Type: k.options.Type, + }) // update build time annotation service.kdeploy.Spec.Template.Metadata.Annotations["build"] = time.Now().Format(time.RFC3339) @@ -382,7 +382,9 @@ func (k *kubernetes) Delete(s *runtime.Service) error { defer k.Unlock() // create new kubernetes micro service - service := newService(s, runtime.CreateOptions{}) + service := newService(s, runtime.CreateOptions{ + Type: k.options.Type, + }) log.Debugf("Runtime queueing service %s for delete action", service.Name) @@ -457,7 +459,10 @@ func (k *kubernetes) String() string { // NewRuntime creates new kubernetes runtime func NewRuntime(opts ...runtime.Option) runtime.Runtime { // get default options - options := runtime.Options{} + options := runtime.Options{ + // Create labels with type "micro": "service" + Type: "service", + } // apply requested options for _, o := range opts { diff --git a/runtime/kubernetes/service.go b/runtime/kubernetes/service.go index e4a5c6ad..ec837682 100644 --- a/runtime/kubernetes/service.go +++ b/runtime/kubernetes/service.go @@ -23,8 +23,8 @@ func newService(s *runtime.Service, c runtime.CreateOptions) *service { name := client.Format(s.Name) version := client.Format(s.Version) - kservice := client.NewService(name, version) - kdeploy := client.NewDeployment(name, version) + kservice := client.NewService(name, version, c.Type) + kdeploy := client.NewDeployment(name, version, c.Type) // attach our values to the deployment; name, version, source kdeploy.Metadata.Annotations["name"] = s.Name @@ -53,10 +53,8 @@ func newService(s *runtime.Service, c runtime.CreateOptions) *service { kdeploy.Spec.Template.PodSpec.Containers[0].Env = append(kdeploy.Spec.Template.PodSpec.Containers[0].Env, env...) } - // if Exec/Command has been supplied override the default command - if len(s.Exec) > 0 { - kdeploy.Spec.Template.PodSpec.Containers[0].Command = s.Exec - } else if len(c.Command) > 0 { + // specify the command to exec + if len(c.Command) > 0 { kdeploy.Spec.Template.PodSpec.Containers[0].Command = c.Command } else if len(s.Source) > 0 { // default command for our k8s service should be source diff --git a/runtime/options.go b/runtime/options.go index cbc93952..a61be888 100644 --- a/runtime/options.go +++ b/runtime/options.go @@ -10,17 +10,28 @@ type Option func(o *Options) type Options struct { // Notifier for updates Notifier Notifier + // Service type to manage + Type string } -// AutoUpdate enables micro auto-updates +// WithNotifier specifies a notifier for updates func WithNotifier(n Notifier) Option { return func(o *Options) { o.Notifier = n } } +// WithType sets the service type to manage +func WithType(t string) Option { + return func(o *Options) { + o.Type = t + } +} + type CreateOption func(o *CreateOptions) +type ReadOption func(o *ReadOptions) + // CreateOptions configure runtime services type CreateOptions struct { // command to execute including args @@ -29,6 +40,18 @@ type CreateOptions struct { Env []string // Log output Output io.Writer + // Type of service to create + Type string +} + +// ReadOptions queries runtime services +type ReadOptions struct { + // Service name + Service string + // Version queries services with given version + Version string + // Type of service + Type string } // WithCommand specifies the command to execute @@ -55,17 +78,23 @@ func WithOutput(out io.Writer) CreateOption { } } -type ReadOption func(o *ReadOptions) - -// ReadOptions queries runtime services -type ReadOptions struct { - // Version queries services with given version - Version string +// ReadService returns services with the given name +func ReadService(service string) ReadOption { + return func(o *ReadOptions) { + o.Service = service + } } // WithVersion confifgures service version -func WithVersion(version string) ReadOption { +func ReadVersion(version string) ReadOption { return func(o *ReadOptions) { o.Version = version } } + +// ReadType returns services of the given type +func ReadType(t string) ReadOption { + return func(o *ReadOptions) { + o.Type = t + } +} diff --git a/runtime/runtime.go b/runtime/runtime.go index b6e17c31..ef584960 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -17,7 +17,7 @@ type Runtime interface { // Create registers a service Create(*Service, ...CreateOption) error // Read returns the service - Read(string, ...ReadOption) ([]*Service, error) + Read(...ReadOption) ([]*Service, error) // Update the service in place Update(*Service) error // Remove a service @@ -84,10 +84,6 @@ type Service struct { Version string // url location of source Source string - // Path to store source - Path string - // Exec command - Exec []string // Metadata stores metadata Metadata map[string]string } diff --git a/runtime/service.go b/runtime/service.go index a3945d64..75e96fbf 100644 --- a/runtime/service.go +++ b/runtime/service.go @@ -37,22 +37,11 @@ func newService(s *Service, c CreateOptions) *service { var exec string var args []string - if len(s.Exec) > 0 { - if len(s.Exec) > 0 { - exec = s.Exec[0] - } - args = []string{} - - if len(s.Exec) > 1 { - args = s.Exec[1:] - } - } else { - // set command - exec = c.Command[0] - // set args - if len(c.Command) > 1 { - args = c.Command[1:] - } + // set command + exec = c.Command[0] + // set args + if len(c.Command) > 1 { + args = c.Command[1:] } return &service{ diff --git a/runtime/service/handler/handler.go b/runtime/service/handler/handler.go index 48c714ef..449043f6 100644 --- a/runtime/service/handler/handler.go +++ b/runtime/service/handler/handler.go @@ -17,8 +17,6 @@ func toProto(s *runtime.Service) *pb.Service { Name: s.Name, Version: s.Version, Source: s.Source, - Path: s.Path, - Exec: s.Exec, Metadata: s.Metadata, } } @@ -28,8 +26,6 @@ func toService(s *pb.Service) *runtime.Service { Name: s.Name, Version: s.Version, Source: s.Source, - Path: s.Path, - Exec: s.Exec, Metadata: s.Metadata, } } @@ -56,9 +52,14 @@ func toCreateOptions(opts *pb.CreateOptions) []runtime.CreateOption { func toReadOptions(opts *pb.ReadOptions) []runtime.ReadOption { options := []runtime.ReadOption{} - // version options + if len(opts.Service) > 0 { + options = append(options, runtime.ReadService(opts.Service)) + } if len(opts.Version) > 0 { - options = append(options, runtime.WithVersion(opts.Version)) + options = append(options, runtime.ReadVersion(opts.Version)) + } + if len(opts.Type) > 0 { + options = append(options, runtime.ReadType(opts.Type)) } return options @@ -84,16 +85,12 @@ func (r *Runtime) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.Cre } func (r *Runtime) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error { - if len(req.Name) == 0 { - return errors.BadRequest("go.micro.runtime", "blank service") - } - var options []runtime.ReadOption if req.Options != nil { options = toReadOptions(req.Options) } - services, err := r.Runtime.Read(req.Name, options...) + services, err := r.Runtime.Read(options...) if err != nil { return errors.InternalServerError("go.micro.runtime", err.Error()) } diff --git a/runtime/service/proto/runtime.pb.go b/runtime/service/proto/runtime.pb.go index f6610a97..9d82b555 100644 --- a/runtime/service/proto/runtime.pb.go +++ b/runtime/service/proto/runtime.pb.go @@ -27,12 +27,8 @@ type Service struct { Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // git url of the source Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` - // local path of the source - Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` - // command to execute - Exec []string `protobuf:"bytes,5,rep,name=exec,proto3" json:"exec,omitempty"` // service metadata - 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"` + Metadata map[string]string `protobuf:"bytes,4,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -84,20 +80,6 @@ func (m *Service) GetSource() string { return "" } -func (m *Service) GetPath() string { - if m != nil { - return m.Path - } - return "" -} - -func (m *Service) GetExec() []string { - if m != nil { - return m.Exec - } - return nil -} - func (m *Service) GetMetadata() map[string]string { if m != nil { return m.Metadata @@ -242,8 +224,12 @@ func (m *CreateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_CreateResponse proto.InternalMessageInfo type ReadOptions struct { + // service name + Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` // version of the service - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + // type of service + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -274,6 +260,13 @@ func (m *ReadOptions) XXX_DiscardUnknown() { var xxx_messageInfo_ReadOptions proto.InternalMessageInfo +func (m *ReadOptions) GetService() string { + if m != nil { + return m.Service + } + return "" +} + func (m *ReadOptions) GetVersion() string { if m != nil { return m.Version @@ -281,9 +274,15 @@ func (m *ReadOptions) GetVersion() string { return "" } +func (m *ReadOptions) GetType() string { + if m != nil { + return m.Type + } + return "" +} + type ReadRequest struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Options *ReadOptions `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"` + Options *ReadOptions `protobuf:"bytes,1,opt,name=options,proto3" json:"options,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -314,13 +313,6 @@ func (m *ReadRequest) XXX_DiscardUnknown() { var xxx_messageInfo_ReadRequest proto.InternalMessageInfo -func (m *ReadRequest) GetName() string { - if m != nil { - return m.Name - } - return "" -} - func (m *ReadRequest) GetOptions() *ReadOptions { if m != nil { return m.Options @@ -599,37 +591,36 @@ func init() { } var fileDescriptor_4bc91a8efec81434 = []byte{ - // 498 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4b, 0x6f, 0xd3, 0x40, - 0x10, 0xae, 0xe3, 0xd4, 0x2e, 0x63, 0x8c, 0xa2, 0x15, 0x42, 0x4b, 0x25, 0x20, 0xf2, 0xa5, 0xbd, - 0xe0, 0x48, 0xae, 0x10, 0xaf, 0x63, 0x53, 0x71, 0x21, 0x42, 0x72, 0xc5, 0x85, 0xdb, 0xe2, 0x8c, - 0x8a, 0x45, 0xed, 0x35, 0xde, 0x75, 0x44, 0x4f, 0x5c, 0xf9, 0xcb, 0xdc, 0xd0, 0xbe, 0x42, 0xe2, - 0xda, 0x5c, 0x72, 0x9b, 0x99, 0x9d, 0xfd, 0xfc, 0x3d, 0x56, 0x86, 0xac, 0x2a, 0x8b, 0x96, 0x2f, - 0x6e, 0xf8, 0x4b, 0x53, 0xb4, 0x5d, 0x2d, 0xcb, 0x0a, 0x17, 0x02, 0xdb, 0x4d, 0x59, 0xe0, 0xa2, - 0x69, 0xb9, 0xdc, 0x4e, 0x53, 0xdd, 0x91, 0xd9, 0x0d, 0x4f, 0xf5, 0x76, 0x6a, 0xe7, 0xc9, 0x1f, - 0x0f, 0xc2, 0x6b, 0x73, 0x83, 0x10, 0x98, 0xd6, 0xac, 0x42, 0xea, 0xcd, 0xbd, 0xf3, 0x07, 0xb9, - 0xae, 0x09, 0x85, 0x70, 0x83, 0xad, 0x28, 0x79, 0x4d, 0x27, 0x7a, 0xec, 0x5a, 0xf2, 0x04, 0x02, - 0xc1, 0xbb, 0xb6, 0x40, 0xea, 0xeb, 0x03, 0xdb, 0x29, 0x94, 0x86, 0xc9, 0x6f, 0x74, 0x6a, 0x50, - 0x54, 0xad, 0x66, 0xf8, 0x13, 0x0b, 0x7a, 0x3c, 0xf7, 0xd5, 0x4c, 0xd5, 0xe4, 0x12, 0x4e, 0x2a, - 0x94, 0x6c, 0xcd, 0x24, 0xa3, 0xc1, 0xdc, 0x3f, 0x8f, 0xb2, 0xb3, 0xb4, 0x4f, 0x2f, 0xb5, 0xd4, - 0xd2, 0x95, 0xdd, 0xbc, 0xaa, 0x65, 0x7b, 0x97, 0x6f, 0x2f, 0x9e, 0xbe, 0x87, 0x78, 0xef, 0x88, - 0xcc, 0xc0, 0xff, 0x8e, 0x77, 0x56, 0x82, 0x2a, 0xc9, 0x63, 0x38, 0xde, 0xb0, 0xdb, 0x0e, 0x2d, - 0x7f, 0xd3, 0xbc, 0x9b, 0xbc, 0xf1, 0x92, 0x6b, 0x88, 0x2f, 0x5b, 0x64, 0x12, 0x3f, 0x35, 0xb2, - 0xe4, 0xb5, 0x50, 0x62, 0x0b, 0x5e, 0x55, 0xac, 0x5e, 0x53, 0x4f, 0x33, 0x75, 0xad, 0x82, 0xc5, - 0x7a, 0x43, 0x27, 0x7a, 0xaa, 0x4a, 0x25, 0x9f, 0x77, 0xb2, 0xe9, 0xa4, 0x93, 0x6f, 0xba, 0xe4, - 0x97, 0x03, 0xcd, 0xf1, 0x47, 0x87, 0x42, 0x92, 0x0b, 0x08, 0x6d, 0x24, 0x9a, 0x55, 0x94, 0x3d, - 0x1d, 0x95, 0x99, 0xbb, 0x4d, 0xf2, 0x16, 0x42, 0x6e, 0x48, 0x69, 0xda, 0x51, 0xf6, 0xe2, 0xfe, - 0xa5, 0x3d, 0xee, 0xb9, 0xdb, 0x4f, 0x66, 0xf0, 0xc8, 0x11, 0x10, 0x0d, 0xaf, 0x05, 0x26, 0x67, - 0x10, 0xe5, 0xc8, 0xd6, 0x3b, 0x2a, 0x87, 0x23, 0x4d, 0xbe, 0x98, 0x45, 0xc7, 0x7c, 0xe8, 0x3d, - 0xbc, 0xee, 0x13, 0x7b, 0x76, 0x9f, 0xd8, 0xce, 0xc7, 0xfe, 0xd1, 0xba, 0x82, 0x87, 0x06, 0xdb, - 0x90, 0x22, 0xaf, 0xe0, 0xc4, 0x8a, 0x15, 0xda, 0xec, 0xff, 0xfa, 0xb2, 0x5d, 0x4d, 0x96, 0x10, - 0x2f, 0xf1, 0x16, 0x0f, 0xb3, 0x57, 0x79, 0xe4, 0x50, 0xac, 0x47, 0x4b, 0x88, 0x3f, 0x37, 0x6b, - 0x76, 0x38, 0xae, 0x43, 0xb1, 0xb8, 0x31, 0x44, 0x1f, 0x4b, 0x21, 0x2d, 0xaa, 0x72, 0xc1, 0xb4, - 0x07, 0xb9, 0x90, 0xfd, 0xf6, 0x21, 0xcc, 0xcd, 0x29, 0x59, 0x41, 0x60, 0xf2, 0x26, 0xa3, 0x6f, - 0xc4, 0x7e, 0xfd, 0x74, 0x3e, 0xbe, 0x60, 0xe9, 0x1e, 0x91, 0x0f, 0x30, 0x55, 0x39, 0x91, 0x91, - 0x5c, 0x1d, 0xd4, 0xf3, 0xb1, 0xe3, 0x2d, 0xd0, 0x0a, 0x02, 0xe3, 0xf1, 0x10, 0xaf, 0xbd, 0x0c, - 0x87, 0x78, 0xf5, 0xe2, 0xd1, 0x70, 0xc6, 0xda, 0x21, 0xb8, 0xbd, 0xe8, 0x86, 0xe0, 0x7a, 0xa9, - 0x68, 0x99, 0x2a, 0x88, 0x21, 0x99, 0x3b, 0x79, 0x0d, 0xc9, 0xdc, 0xcd, 0x2f, 0x39, 0xfa, 0x1a, - 0xe8, 0x3f, 0xeb, 0xc5, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbe, 0x95, 0xdf, 0xf9, 0x8f, 0x05, - 0x00, 0x00, + // 492 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcd, 0x6e, 0xd3, 0x40, + 0x10, 0xae, 0xe3, 0x10, 0xb7, 0x63, 0x8c, 0xa2, 0x15, 0x42, 0xa6, 0x12, 0x10, 0xf9, 0x42, 0x2f, + 0x38, 0x92, 0x2b, 0xc4, 0xdf, 0xb1, 0x29, 0x5c, 0x88, 0x90, 0x5c, 0xf5, 0x01, 0x96, 0x64, 0x54, + 0x59, 0xd4, 0x5e, 0xb3, 0xbb, 0x8e, 0x94, 0x13, 0x57, 0x5e, 0x8f, 0x37, 0x42, 0xfb, 0x97, 0xd8, + 0xa9, 0xdd, 0x4b, 0x6e, 0x33, 0xbb, 0xb3, 0xdf, 0x7c, 0x3f, 0x96, 0x21, 0x2b, 0x8b, 0x15, 0x67, + 0xf3, 0x3b, 0xf6, 0xce, 0x14, 0xbc, 0xa9, 0x64, 0x51, 0xe2, 0x5c, 0x20, 0xdf, 0x14, 0x2b, 0x9c, + 0xd7, 0x9c, 0xc9, 0xdd, 0x69, 0xaa, 0x3b, 0x32, 0xbd, 0x63, 0xa9, 0x9e, 0x4e, 0xed, 0x79, 0xf2, + 0xcf, 0x83, 0xe0, 0xc6, 0xbc, 0x20, 0x04, 0xc6, 0x15, 0x2d, 0x31, 0xf6, 0x66, 0xde, 0xc5, 0x59, + 0xae, 0x6b, 0x12, 0x43, 0xb0, 0x41, 0x2e, 0x0a, 0x56, 0xc5, 0x23, 0x7d, 0xec, 0x5a, 0xf2, 0x02, + 0x26, 0x82, 0x35, 0x7c, 0x85, 0xb1, 0xaf, 0x2f, 0x6c, 0x47, 0xae, 0xe0, 0xb4, 0x44, 0x49, 0xd7, + 0x54, 0xd2, 0x78, 0x3c, 0xf3, 0x2f, 0xc2, 0xec, 0x6d, 0x7a, 0xb8, 0x36, 0xb5, 0x2b, 0xd3, 0xa5, + 0x9d, 0xbc, 0xae, 0x24, 0xdf, 0xe6, 0xbb, 0x87, 0xe7, 0x5f, 0x20, 0xea, 0x5c, 0x91, 0x29, 0xf8, + 0xbf, 0x70, 0x6b, 0xa9, 0xa9, 0x92, 0x3c, 0x87, 0x27, 0x1b, 0x7a, 0xdf, 0xa0, 0xe5, 0x65, 0x9a, + 0xcf, 0xa3, 0x8f, 0x5e, 0x72, 0x03, 0xd1, 0x15, 0x47, 0x2a, 0xf1, 0x47, 0x2d, 0x0b, 0x56, 0x09, + 0x25, 0x62, 0xc5, 0xca, 0x92, 0x56, 0xeb, 0xd8, 0x9b, 0xf9, 0x4a, 0x84, 0x6d, 0x15, 0x2c, 0x56, + 0x9b, 0x78, 0xa4, 0x4f, 0x55, 0xa9, 0x64, 0xb1, 0x46, 0xd6, 0x8d, 0x74, 0xb2, 0x4c, 0x97, 0xfc, + 0x71, 0xa0, 0x39, 0xfe, 0x6e, 0x50, 0x48, 0x72, 0x09, 0x81, 0xb5, 0x5a, 0xb3, 0x0a, 0xb3, 0x97, + 0x83, 0x32, 0x73, 0x37, 0x49, 0x3e, 0x41, 0xc0, 0x0c, 0x29, 0x4d, 0x3b, 0xcc, 0xde, 0x3c, 0x7c, + 0xd4, 0xe1, 0x9e, 0xbb, 0xf9, 0x64, 0x0a, 0xcf, 0x1c, 0x01, 0x51, 0xb3, 0x4a, 0x60, 0x72, 0x0b, + 0x61, 0x8e, 0x74, 0xdd, 0x52, 0xd9, 0x26, 0x74, 0xb6, 0xdf, 0x3a, 0x1c, 0x22, 0x81, 0xb1, 0xdc, + 0xd6, 0x2e, 0x42, 0x5d, 0x27, 0x5f, 0x0d, 0xac, 0xd3, 0xf9, 0x61, 0x4f, 0xd9, 0xe8, 0x7c, 0xf5, + 0x90, 0x72, 0x8b, 0xc6, 0x9e, 0xf0, 0x35, 0x3c, 0x35, 0x38, 0x86, 0x2e, 0x79, 0x0f, 0xa7, 0x96, + 0x90, 0xd0, 0x31, 0x3c, 0xea, 0xd8, 0x6e, 0x34, 0x59, 0x40, 0xb4, 0xc0, 0x7b, 0x3c, 0xce, 0x78, + 0xe5, 0x9e, 0x43, 0xb1, 0xee, 0x2d, 0x20, 0xba, 0xad, 0xd7, 0xf4, 0x78, 0x5c, 0x87, 0x62, 0x71, + 0x23, 0x08, 0xbf, 0x17, 0x42, 0x5a, 0x54, 0xe5, 0x82, 0x69, 0x8f, 0x72, 0x21, 0xfb, 0xeb, 0x43, + 0x90, 0x9b, 0x5b, 0xb2, 0x84, 0x89, 0xf9, 0x12, 0xc8, 0xe0, 0xd7, 0x63, 0xb7, 0x9f, 0xcf, 0x86, + 0x07, 0x2c, 0xdd, 0x13, 0xf2, 0x0d, 0xc6, 0x2a, 0x27, 0x32, 0x90, 0xab, 0x83, 0x7a, 0x3d, 0x74, + 0xbd, 0x03, 0x5a, 0xc2, 0xc4, 0x78, 0xdc, 0xc7, 0xab, 0x93, 0x61, 0x1f, 0xaf, 0x83, 0x78, 0x34, + 0x9c, 0xb1, 0xb6, 0x0f, 0xae, 0x13, 0x5d, 0x1f, 0xdc, 0x41, 0x2a, 0x5a, 0xa6, 0x0a, 0xa2, 0x4f, + 0x66, 0x2b, 0xaf, 0x3e, 0x99, 0xed, 0xfc, 0x92, 0x93, 0x9f, 0x13, 0xfd, 0x2f, 0xbd, 0xfc, 0x1f, + 0x00, 0x00, 0xff, 0xff, 0x14, 0x09, 0x5e, 0x98, 0x81, 0x05, 0x00, 0x00, } diff --git a/runtime/service/proto/runtime.proto b/runtime/service/proto/runtime.proto index 86814f9d..3da3b17d 100644 --- a/runtime/service/proto/runtime.proto +++ b/runtime/service/proto/runtime.proto @@ -17,12 +17,8 @@ message Service { string version = 2; // git url of the source string source = 3; - // local path of the source - string path = 4; - // command to execute - repeated string exec = 5; // service metadata - map metadata = 6; + map metadata = 4; } message CreateOptions { @@ -42,13 +38,16 @@ message CreateRequest { message CreateResponse {} message ReadOptions { - // version of the service - string version = 2; + // service name + string service = 1; + // version of the service + string version = 2; + // type of service + string type = 3; } message ReadRequest { - string name = 1; - ReadOptions options = 2; + ReadOptions options = 1; } message ReadResponse { diff --git a/runtime/service/service.go b/runtime/service/service.go index 769f0d69..91e62df8 100644 --- a/runtime/service/service.go +++ b/runtime/service/service.go @@ -76,7 +76,7 @@ func (s *svc) Create(svc *runtime.Service, opts ...runtime.CreateOption) error { } // Read returns the service with the given name from the runtime -func (s *svc) Read(name string, opts ...runtime.ReadOption) ([]*runtime.Service, error) { +func (s *svc) Read(opts ...runtime.ReadOption) ([]*runtime.Service, error) { options := runtime.ReadOptions{} // apply requested options for _, o := range opts { @@ -85,9 +85,10 @@ func (s *svc) Read(name string, opts ...runtime.ReadOption) ([]*runtime.Service, // runtime service create request req := &pb.ReadRequest{ - Name: name, Options: &pb.ReadOptions{ + Service: options.Service, Version: options.Version, + Type: options.Type, }, } @@ -102,8 +103,6 @@ func (s *svc) Read(name string, opts ...runtime.ReadOption) ([]*runtime.Service, Name: service.Name, Version: service.Version, Source: service.Source, - Path: service.Path, - Exec: service.Exec, Metadata: service.Metadata, } services = append(services, svc) @@ -160,8 +159,6 @@ func (s *svc) List() ([]*runtime.Service, error) { Name: service.Name, Version: service.Version, Source: service.Source, - Path: service.Path, - Exec: service.Exec, Metadata: service.Metadata, } services = append(services, svc) From 76b4e78a6ac26a0df7d8bab39b6e9c1ed9a2d1ca Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 29 Nov 2019 11:55:25 +0000 Subject: [PATCH 263/344] fix command to accept variadic args --- runtime/options.go | 6 ++---- runtime/service/handler/handler.go | 8 ++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/runtime/options.go b/runtime/options.go index a61be888..e469346b 100644 --- a/runtime/options.go +++ b/runtime/options.go @@ -55,12 +55,10 @@ type ReadOptions struct { } // WithCommand specifies the command to execute -func WithCommand(c string, args ...string) CreateOption { +func WithCommand(args ...string) CreateOption { return func(o *CreateOptions) { // set command - o.Command = []string{c} - // set args - o.Command = append(o.Command, args...) + o.Command = args } } diff --git a/runtime/service/handler/handler.go b/runtime/service/handler/handler.go index 449043f6..b545eab4 100644 --- a/runtime/service/handler/handler.go +++ b/runtime/service/handler/handler.go @@ -33,12 +33,8 @@ func toService(s *pb.Service) *runtime.Service { func toCreateOptions(opts *pb.CreateOptions) []runtime.CreateOption { options := []runtime.CreateOption{} // command options - l := len(opts.Command) - if l == 1 { - options = append(options, runtime.WithCommand(opts.Command[0])) - } - if l > 1 { - options = append(options, runtime.WithCommand(opts.Command[0], opts.Command[1:]...)) + if len(opts.Command) > 0 { + options = append(options, runtime.WithCommand(opts.Command...)) } // env options if len(opts.Env) > 0 { From 6bf48282963a558b1ed395c60e7f010aad9f00c3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 29 Nov 2019 13:05:07 +0000 Subject: [PATCH 264/344] triple the mdns timeout --- registry/mdns_registry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/mdns_registry.go b/registry/mdns_registry.go index 0046e9b2..7e060290 100644 --- a/registry/mdns_registry.go +++ b/registry/mdns_registry.go @@ -51,7 +51,7 @@ type mdnsRegistry struct { func newRegistry(opts ...Option) Registry { options := Options{ Context: context.Background(), - Timeout: time.Millisecond * 10, + Timeout: time.Millisecond * 30, } for _, o := range opts { From ce4acfa892385eceaf84aa3d277c09ddbd106318 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 29 Nov 2019 13:05:18 +0000 Subject: [PATCH 265/344] fix type filtering for k8s runtime --- runtime/kubernetes/kubernetes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index c05f5890..d451254a 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -335,7 +335,7 @@ func (k *kubernetes) Read(opts ...runtime.ReadOption) ([]*runtime.Service, error } if len(options.Type) > 0 { - labels["type"] = options.Type + labels["micro"] = options.Type } return k.getService(labels) From 107124e5dc58e1c9c5ea36d3046da7f3b6aab19a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 29 Nov 2019 17:27:29 +0000 Subject: [PATCH 266/344] Changes for the storm --- router/default.go | 6 +++--- tunnel/options.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/router/default.go b/router/default.go index b77a3683..5696b731 100644 --- a/router/default.go +++ b/router/default.go @@ -21,17 +21,17 @@ var ( // AdvertiseFlushTick is time the yet unconsumed advertisements are flush i.e. discarded AdvertiseFlushTick = 15 * time.Second // DefaultAdvertTTL is default advertisement TTL - DefaultAdvertTTL = 1 * time.Minute + DefaultAdvertTTL = 2 * time.Minute // AdvertSuppress is advert suppression threshold AdvertSuppress = 200.0 // AdvertRecover is advert recovery threshold - AdvertRecover = 120.0 + AdvertRecover = 20.0 // Penalty for routes processed multiple times Penalty = 100.0 // PenaltyHalfLife is the time the advert penalty decays to half its value PenaltyHalfLife = 30.0 // MaxSuppressTime defines time after which the suppressed advert is deleted - MaxSuppressTime = 5 * time.Minute + MaxSuppressTime = time.Second * 30 // PenaltyDecay is a coefficient which controls the speed the advert penalty decays PenaltyDecay = math.Log(2) / PenaltyHalfLife ) diff --git a/tunnel/options.go b/tunnel/options.go index 7d6360ab..3a8f13db 100644 --- a/tunnel/options.go +++ b/tunnel/options.go @@ -12,7 +12,7 @@ var ( // DefaultAddress is default tunnel bind address DefaultAddress = ":0" // The shared default token - DefaultToken = "micro" + DefaultToken = "go.micro.tunnel" ) type Option func(*Options) From 9678daeafa083d2cba477ae8c7140e5a085b2223 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 30 Nov 2019 01:14:40 +0000 Subject: [PATCH 267/344] fix bug in the tunnel which causes multicast connections to be closed --- tunnel/default.go | 9 ++++++--- tunnel/listener.go | 3 ++- tunnel/session.go | 5 +++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index 72963f0c..fc24ee9d 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -93,6 +93,9 @@ func (t *tun) getSession(channel, session string) (*session, bool) { // delSession deletes a session if it exists func (t *tun) delSession(channel, session string) { t.Lock() + if s, ok := t.sessions[channel+session]; ok { + s.Close() + } delete(t.sessions, channel+session) t.Unlock() } @@ -512,10 +515,10 @@ func (t *tun) listen(link *link) { } // try get the dialing socket - s, exists := t.getSession(channel, sessionId) + _, exists := t.getSession(channel, sessionId) if exists { - // close and continue - s.Close() + // delete and continue + t.delSession(channel, sessionId) continue } // otherwise its a session mapping of sorts diff --git a/tunnel/listener.go b/tunnel/listener.go index cc207d70..62883777 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -66,6 +66,7 @@ func (t *tunListener) process() { sess, ok := conns[m.session] log.Debugf("Tunnel listener received channel %s session %s exists: %t", m.channel, m.session, ok) if !ok { + // we only process open and session types switch m.typ { case "open", "session": default: @@ -87,7 +88,7 @@ func (t *tunListener) process() { // the link the message was received on link: m.link, // set the connection mode - mode: m.mode, + mode: t.session.mode, // close chan closed: make(chan bool), // recv called by the acceptor diff --git a/tunnel/session.go b/tunnel/session.go index 4b8721aa..a0dbef93 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -413,6 +413,11 @@ func (s *session) Close() error { default: close(s.closed) + // don't broadcast the close for multicast + if s.mode != Unicast { + return nil + } + // append to backlog msg := s.newMessage("close") // no error response on close From 5e59db4c6d4027903cfb4db62ac0aadea5df9554 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 30 Nov 2019 01:16:32 +0000 Subject: [PATCH 268/344] revert mdns timeout --- registry/mdns_registry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/mdns_registry.go b/registry/mdns_registry.go index 7e060290..6d1c75f7 100644 --- a/registry/mdns_registry.go +++ b/registry/mdns_registry.go @@ -51,7 +51,7 @@ type mdnsRegistry struct { func newRegistry(opts ...Option) Registry { options := Options{ Context: context.Background(), - Timeout: time.Millisecond * 30, + Timeout: time.Millisecond * 100, } for _, o := range opts { From ce1942c578eb707dfcd8230ef69da58cfeb6d7ce Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 30 Nov 2019 21:00:36 +0000 Subject: [PATCH 269/344] why didn't we think of this before...single service name for http broker --- broker/http_broker.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index 385c7fa0..b6c78b62 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -64,6 +64,7 @@ type httpEvent struct { var ( DefaultSubPath = "/_sub" + serviceName = "go.micro.http.broker" broadcastVersion = "ff.http.broadcast" registerTTL = time.Minute registerInterval = time.Second * 30 @@ -126,7 +127,7 @@ func newHttpBroker(opts ...Option) Broker { } h := &httpBroker{ - id: "go.micro.http.broker-" + uuid.New().String(), + id: uuid.New().String(), address: addr, opts: options, r: reg, @@ -241,7 +242,7 @@ func (h *httpBroker) unsubscribe(s *httpSubscriber) error { // look for subscriber for _, sub := range h.subscribers[s.topic] { // deregister and skip forward - if sub.id == s.id { + if sub == s { _ = h.r.Deregister(sub.svc) continue } @@ -527,7 +528,7 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) // now attempt to get the service h.RLock() - s, err := h.r.GetService(topic) + s, err := h.r.GetService(serviceName) if err != nil { h.RUnlock() // ignore error @@ -656,7 +657,7 @@ func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO // register service node := ®istry.Node{ - Id: h.id, + Id: topic + "-" + h.id, Address: mnet.HostPort(addr, port), Metadata: map[string]string{ "secure": fmt.Sprintf("%t", secure), @@ -672,7 +673,7 @@ func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO } service := ®istry.Service{ - Name: topic, + Name: serviceName, Version: version, Nodes: []*registry.Node{node}, } @@ -681,7 +682,7 @@ func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO subscriber := &httpSubscriber{ opts: options, hb: h, - id: h.id, + id: node.Id, topic: topic, fn: handler, svc: service, From 00bbb3ac610601772fe0a5996217dd8e21f8fc86 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 30 Nov 2019 21:20:33 +0000 Subject: [PATCH 270/344] revert some protocol changes for now --- client/grpc/grpc.go | 7 +------ client/rpc_client.go | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/client/grpc/grpc.go b/client/grpc/grpc.go index 6ca92586..ba7a3842 100644 --- a/client/grpc/grpc.go +++ b/client/grpc/grpc.go @@ -71,13 +71,8 @@ func (g *grpcClient) next(request client.Request, opts client.CallOptions) (sele }, nil } - // only get the things that are of grpc protocol - selectOptions := append(opts.SelectOptions, selector.WithFilter( - selector.FilterLabel("protocol", "grpc"), - )) - // get next nodes from the selector - next, err := g.opts.Selector.Select(service, selectOptions...) + next, err := g.opts.Selector.Select(service, opts.SelectOptions...) if err != nil { if err == selector.ErrNotFound { return nil, errors.InternalServerError("go.micro.client", "service %s: %s", service, err.Error()) diff --git a/client/rpc_client.go b/client/rpc_client.go index 71f55708..c75a67b3 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -350,13 +350,8 @@ func (r *rpcClient) next(request Request, opts CallOptions) (selector.Next, erro }, nil } - // only get the things that are of mucp protocol - selectOptions := append(opts.SelectOptions, selector.WithFilter( - selector.FilterLabel("protocol", "mucp"), - )) - // get next nodes from the selector - next, err := r.opts.Selector.Select(service, selectOptions...) + next, err := r.opts.Selector.Select(service, opts.SelectOptions...) if err != nil { if err == selector.ErrNotFound { return nil, errors.InternalServerError("go.micro.client", "service %s: %s", service, err.Error()) From 6f1c30aef586a02726e005a2d32ef495bba4dcc4 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 30 Nov 2019 21:39:03 +0000 Subject: [PATCH 271/344] remove unused value in router --- router/default.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/router/default.go b/router/default.go index 5696b731..23384d2f 100644 --- a/router/default.go +++ b/router/default.go @@ -18,10 +18,8 @@ var ( AdvertiseEventsTick = 5 * time.Second // AdvertiseTableTick is time interval in which router advertises all routes found in routing table AdvertiseTableTick = 1 * time.Minute - // AdvertiseFlushTick is time the yet unconsumed advertisements are flush i.e. discarded - AdvertiseFlushTick = 15 * time.Second // DefaultAdvertTTL is default advertisement TTL - DefaultAdvertTTL = 2 * time.Minute + DefaultAdvertTTL = 1 * time.Minute // AdvertSuppress is advert suppression threshold AdvertSuppress = 200.0 // AdvertRecover is advert recovery threshold From 4e965e4ce5323eba7dde720c4d1e62bffb6a307b Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 26 Nov 2019 15:39:55 +0000 Subject: [PATCH 272/344] First commit. Modified proto. Added empty handler method. --- debug/handler/debug.go | 4 + debug/proto/debug.pb.go | 157 ++++++++++++++++++++++++++++------ debug/proto/debug.pb.micro.go | 84 +++++++++++++++++- debug/proto/debug.proto | 30 +++++-- 4 files changed, 243 insertions(+), 32 deletions(-) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index 973a6fc4..51a8aa9f 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -39,3 +39,7 @@ func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.S rsp.Threads = uint64(runtime.NumGoroutine()) return nil } + +func (d *Debug) Log(ctx context.Context, req *proto.LogRequest, rsp *proto.Debug_LogStream) error { + return nil +} diff --git a/debug/proto/debug.pb.go b/debug/proto/debug.pb.go index 316df6a8..d4ceaa11 100644 --- a/debug/proto/debug.pb.go +++ b/debug/proto/debug.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/micro/go-micro/debug/proto/debug.proto +// source: debug.proto package debug @@ -30,7 +30,7 @@ func (m *HealthRequest) Reset() { *m = HealthRequest{} } func (m *HealthRequest) String() string { return proto.CompactTextString(m) } func (*HealthRequest) ProtoMessage() {} func (*HealthRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{0} + return fileDescriptor_8d9d361be58531fb, []int{0} } func (m *HealthRequest) XXX_Unmarshal(b []byte) error { @@ -63,7 +63,7 @@ func (m *HealthResponse) Reset() { *m = HealthResponse{} } func (m *HealthResponse) String() string { return proto.CompactTextString(m) } func (*HealthResponse) ProtoMessage() {} func (*HealthResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{1} + return fileDescriptor_8d9d361be58531fb, []int{1} } func (m *HealthResponse) XXX_Unmarshal(b []byte) error { @@ -101,7 +101,7 @@ func (m *StatsRequest) Reset() { *m = StatsRequest{} } func (m *StatsRequest) String() string { return proto.CompactTextString(m) } func (*StatsRequest) ProtoMessage() {} func (*StatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{2} + return fileDescriptor_8d9d361be58531fb, []int{2} } func (m *StatsRequest) XXX_Unmarshal(b []byte) error { @@ -142,7 +142,7 @@ func (m *StatsResponse) Reset() { *m = StatsResponse{} } func (m *StatsResponse) String() string { return proto.CompactTextString(m) } func (*StatsResponse) ProtoMessage() {} func (*StatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{3} + return fileDescriptor_8d9d361be58531fb, []int{3} } func (m *StatsResponse) XXX_Unmarshal(b []byte) error { @@ -198,32 +198,139 @@ func (m *StatsResponse) GetGc() uint64 { return 0 } +// LogRequest queries service for logs +type LogRequest struct { + // count is the count of events + Count uint64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + // relative time in seconds + // before the current time + // from which to show logs + Since uint64 `protobuf:"varint,2,opt,name=since,proto3" json:"since,omitempty"` + // stream logs continuously + Stream bool `protobuf:"varint,3,opt,name=stream,proto3" json:"stream,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LogRequest) Reset() { *m = LogRequest{} } +func (m *LogRequest) String() string { return proto.CompactTextString(m) } +func (*LogRequest) ProtoMessage() {} +func (*LogRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_8d9d361be58531fb, []int{4} +} + +func (m *LogRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LogRequest.Unmarshal(m, b) +} +func (m *LogRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LogRequest.Marshal(b, m, deterministic) +} +func (m *LogRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_LogRequest.Merge(m, src) +} +func (m *LogRequest) XXX_Size() int { + return xxx_messageInfo_LogRequest.Size(m) +} +func (m *LogRequest) XXX_DiscardUnknown() { + xxx_messageInfo_LogRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_LogRequest proto.InternalMessageInfo + +func (m *LogRequest) GetCount() uint64 { + if m != nil { + return m.Count + } + return 0 +} + +func (m *LogRequest) GetSince() uint64 { + if m != nil { + return m.Since + } + return 0 +} + +func (m *LogRequest) GetStream() bool { + if m != nil { + return m.Stream + } + return false +} + +// LogEvent is service log event +type LogEvent struct { + // event log record + // TODO: change this + Record string `protobuf:"bytes,1,opt,name=record,proto3" json:"record,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LogEvent) Reset() { *m = LogEvent{} } +func (m *LogEvent) String() string { return proto.CompactTextString(m) } +func (*LogEvent) ProtoMessage() {} +func (*LogEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_8d9d361be58531fb, []int{5} +} + +func (m *LogEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LogEvent.Unmarshal(m, b) +} +func (m *LogEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LogEvent.Marshal(b, m, deterministic) +} +func (m *LogEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_LogEvent.Merge(m, src) +} +func (m *LogEvent) XXX_Size() int { + return xxx_messageInfo_LogEvent.Size(m) +} +func (m *LogEvent) XXX_DiscardUnknown() { + xxx_messageInfo_LogEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_LogEvent proto.InternalMessageInfo + +func (m *LogEvent) GetRecord() string { + if m != nil { + return m.Record + } + return "" +} + func init() { proto.RegisterType((*HealthRequest)(nil), "HealthRequest") proto.RegisterType((*HealthResponse)(nil), "HealthResponse") proto.RegisterType((*StatsRequest)(nil), "StatsRequest") proto.RegisterType((*StatsResponse)(nil), "StatsResponse") + proto.RegisterType((*LogRequest)(nil), "LogRequest") + proto.RegisterType((*LogEvent)(nil), "LogEvent") } -func init() { - proto.RegisterFile("github.com/micro/go-micro/debug/proto/debug.proto", fileDescriptor_7cb19b1a05a6e0a9) -} +func init() { proto.RegisterFile("debug.proto", fileDescriptor_8d9d361be58531fb) } -var fileDescriptor_7cb19b1a05a6e0a9 = []byte{ - // 237 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0x41, 0x4b, 0xc4, 0x30, - 0x14, 0x84, 0x77, 0xeb, 0xb6, 0xe2, 0xc3, 0x66, 0x21, 0x07, 0x09, 0x7b, 0x92, 0x9c, 0x0a, 0x62, - 0x8a, 0xfa, 0x17, 0x3c, 0x78, 0xae, 0x77, 0x21, 0x6d, 0x43, 0x5a, 0x30, 0xa6, 0x26, 0x2f, 0x07, - 0xcf, 0xfe, 0x71, 0x69, 0x92, 0x82, 0xbd, 0xcd, 0x4c, 0x98, 0x21, 0xdf, 0x83, 0x27, 0x3d, 0xe3, - 0x14, 0x7a, 0x31, 0x58, 0xd3, 0x9a, 0x79, 0x70, 0xb6, 0xd5, 0xf6, 0x31, 0x89, 0x51, 0xf5, 0x41, - 0xb7, 0x8b, 0xb3, 0x98, 0xb5, 0x88, 0x9a, 0x9f, 0xa1, 0x7e, 0x53, 0xf2, 0x13, 0xa7, 0x4e, 0x7d, - 0x07, 0xe5, 0x91, 0x37, 0x40, 0xb6, 0xc0, 0x2f, 0xf6, 0xcb, 0x2b, 0x7a, 0x07, 0x95, 0x47, 0x89, - 0xc1, 0xb3, 0xe3, 0xfd, 0xb1, 0xb9, 0xe9, 0xb2, 0xe3, 0x04, 0x6e, 0xdf, 0x51, 0xa2, 0xdf, 0x9a, - 0xbf, 0x47, 0xa8, 0x73, 0x90, 0x9b, 0x0c, 0xae, 0x3d, 0x4a, 0x87, 0x6a, 0x8c, 0xd5, 0x53, 0xb7, - 0xd9, 0x75, 0x33, 0x2c, 0x38, 0x1b, 0xc5, 0x8a, 0xf8, 0x90, 0xdd, 0x9a, 0x1b, 0x65, 0xac, 0xfb, - 0x61, 0x57, 0x29, 0x4f, 0x6e, 0x5d, 0xc2, 0xc9, 0x29, 0x39, 0x7a, 0x76, 0x4a, 0x4b, 0xd9, 0x52, - 0x02, 0x85, 0x1e, 0x58, 0x19, 0xc3, 0x42, 0x0f, 0xcf, 0x1f, 0x50, 0xbe, 0xae, 0x7c, 0xf4, 0x01, - 0xaa, 0x04, 0x42, 0x89, 0xd8, 0x21, 0x5e, 0xce, 0x62, 0x4f, 0xc8, 0x0f, 0xb4, 0x81, 0x32, 0x7e, - 0x9d, 0xd6, 0xe2, 0x3f, 0xd3, 0x85, 0x88, 0x1d, 0x11, 0x3f, 0xf4, 0x55, 0xbc, 0xdb, 0xcb, 0x5f, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x20, 0xb8, 0xfe, 0x98, 0x6c, 0x01, 0x00, 0x00, +var fileDescriptor_8d9d361be58531fb = []byte{ + // 290 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x91, 0xdd, 0x4a, 0xc3, 0x30, + 0x14, 0xc7, 0xd7, 0x6d, 0x9d, 0xdb, 0x99, 0xeb, 0x20, 0x88, 0x84, 0x5d, 0x69, 0xae, 0x06, 0x42, + 0x10, 0x7d, 0x05, 0x05, 0x2f, 0x76, 0x21, 0xf5, 0x09, 0xb2, 0xf6, 0x90, 0x0d, 0x6c, 0x33, 0x93, + 0x53, 0xc1, 0x4b, 0xf1, 0xc5, 0x25, 0x5f, 0xe8, 0x2e, 0x7f, 0xff, 0xf6, 0x7c, 0xfd, 0x02, 0xcb, + 0x16, 0xf7, 0x83, 0x96, 0x27, 0x6b, 0xc8, 0x88, 0x35, 0xac, 0x5e, 0x50, 0xbd, 0xd3, 0xa1, 0xc6, + 0x8f, 0x01, 0x1d, 0x89, 0x2d, 0x54, 0x39, 0x70, 0x27, 0xd3, 0x3b, 0x64, 0xd7, 0x30, 0x73, 0xa4, + 0x68, 0x70, 0xbc, 0xb8, 0x29, 0xb6, 0x8b, 0x3a, 0x91, 0xa8, 0xe0, 0xf2, 0x8d, 0x14, 0xb9, 0x5c, + 0xf9, 0x53, 0xc0, 0x2a, 0x05, 0xa9, 0x92, 0xc3, 0x85, 0x23, 0x65, 0x09, 0xdb, 0x50, 0x3a, 0xad, + 0x33, 0xfa, 0x9e, 0xc3, 0x89, 0x8e, 0x1d, 0xf2, 0x71, 0xf8, 0x90, 0xc8, 0xe7, 0x1d, 0x76, 0xc6, + 0x7e, 0xf1, 0x49, 0xcc, 0x23, 0xf9, 0x4e, 0x74, 0xb0, 0xa8, 0x5a, 0xc7, 0xa7, 0xb1, 0x53, 0x42, + 0x56, 0xc1, 0x58, 0x37, 0xbc, 0x0c, 0xe1, 0x58, 0x37, 0xe2, 0x15, 0x60, 0x67, 0x74, 0xda, 0x89, + 0x5d, 0x41, 0xd9, 0x98, 0xa1, 0xa7, 0x34, 0x3f, 0x82, 0x4f, 0xdd, 0xb1, 0x6f, 0xf2, 0xf0, 0x08, + 0xf1, 0x4e, 0x8b, 0xaa, 0x0b, 0xb3, 0xe7, 0x75, 0x22, 0x21, 0x60, 0xbe, 0x33, 0xfa, 0xf9, 0x13, + 0x7b, 0xf2, 0xff, 0x58, 0x6c, 0x8c, 0x6d, 0xb3, 0x8b, 0x48, 0x0f, 0xdf, 0x05, 0x94, 0x4f, 0x5e, + 0x2b, 0xbb, 0x83, 0x59, 0xf4, 0xc7, 0x2a, 0x79, 0x66, 0x76, 0xb3, 0x96, 0xe7, 0x62, 0xc5, 0x88, + 0x6d, 0xa1, 0x0c, 0xc6, 0xd8, 0x4a, 0xfe, 0x57, 0xb9, 0xa9, 0xe4, 0x99, 0x48, 0x31, 0x62, 0xb7, + 0x30, 0xd9, 0x19, 0xcd, 0x96, 0xf2, 0xef, 0xb8, 0xcd, 0x42, 0xe6, 0xbd, 0xc4, 0xe8, 0xbe, 0xd8, + 0xcf, 0xc2, 0x8b, 0x3e, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x70, 0x27, 0xbe, 0x8c, 0xe0, 0x01, + 0x00, 0x00, } diff --git a/debug/proto/debug.pb.micro.go b/debug/proto/debug.pb.micro.go index 3dcc256f..97cf7345 100644 --- a/debug/proto/debug.pb.micro.go +++ b/debug/proto/debug.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: github.com/micro/go-micro/debug/proto/debug.proto +// source: debug.proto package debug @@ -36,6 +36,7 @@ var _ server.Option type DebugService interface { Health(ctx context.Context, in *HealthRequest, opts ...client.CallOption) (*HealthResponse, error) Stats(ctx context.Context, in *StatsRequest, opts ...client.CallOption) (*StatsResponse, error) + Log(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogService, error) } type debugService struct { @@ -76,17 +77,63 @@ func (c *debugService) Stats(ctx context.Context, in *StatsRequest, opts ...clie return out, nil } +func (c *debugService) Log(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogService, error) { + req := c.c.NewRequest(c.name, "Debug.Log", &LogRequest{}) + stream, err := c.c.Stream(ctx, req, opts...) + if err != nil { + return nil, err + } + if err := stream.Send(in); err != nil { + return nil, err + } + return &debugServiceLog{stream}, nil +} + +type Debug_LogService interface { + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Recv() (*LogEvent, error) +} + +type debugServiceLog struct { + stream client.Stream +} + +func (x *debugServiceLog) Close() error { + return x.stream.Close() +} + +func (x *debugServiceLog) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *debugServiceLog) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *debugServiceLog) Recv() (*LogEvent, error) { + m := new(LogEvent) + err := x.stream.Recv(m) + if err != nil { + return nil, err + } + return m, nil +} + // Server API for Debug service type DebugHandler interface { Health(context.Context, *HealthRequest, *HealthResponse) error Stats(context.Context, *StatsRequest, *StatsResponse) error + Log(context.Context, *LogRequest, Debug_LogStream) error } func RegisterDebugHandler(s server.Server, hdlr DebugHandler, opts ...server.HandlerOption) error { type debug interface { Health(ctx context.Context, in *HealthRequest, out *HealthResponse) error Stats(ctx context.Context, in *StatsRequest, out *StatsResponse) error + Log(ctx context.Context, stream server.Stream) error } type Debug struct { debug @@ -106,3 +153,38 @@ func (h *debugHandler) Health(ctx context.Context, in *HealthRequest, out *Healt func (h *debugHandler) Stats(ctx context.Context, in *StatsRequest, out *StatsResponse) error { return h.DebugHandler.Stats(ctx, in, out) } + +func (h *debugHandler) Log(ctx context.Context, stream server.Stream) error { + m := new(LogRequest) + if err := stream.Recv(m); err != nil { + return err + } + return h.DebugHandler.Log(ctx, m, &debugLogStream{stream}) +} + +type Debug_LogStream interface { + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Send(*LogEvent) error +} + +type debugLogStream struct { + stream server.Stream +} + +func (x *debugLogStream) Close() error { + return x.stream.Close() +} + +func (x *debugLogStream) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *debugLogStream) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *debugLogStream) Send(m *LogEvent) error { + return x.stream.Send(m) +} diff --git a/debug/proto/debug.proto b/debug/proto/debug.proto index b642cd41..648e48a8 100644 --- a/debug/proto/debug.proto +++ b/debug/proto/debug.proto @@ -1,20 +1,19 @@ syntax = "proto3"; service Debug { - rpc Health(HealthRequest) returns (HealthResponse) {} - rpc Stats(StatsRequest) returns (StatsResponse) {} + rpc Health(HealthRequest) returns (HealthResponse) {}; + rpc Stats(StatsRequest) returns (StatsResponse) {}; + rpc Log(LogRequest) returns (stream LogEvent) {}; } -message HealthRequest { -} +message HealthRequest {} message HealthResponse { // default: ok string status = 1; } -message StatsRequest { -} +message StatsRequest {} message StatsResponse { // unix timestamp @@ -28,3 +27,22 @@ message StatsResponse { // total gc in nanoseconds uint64 gc = 5; } + +// LogRequest queries service for logs +message LogRequest { + // count is the count of events + uint64 count = 1; + // relative time in seconds + // before the current time + // from which to show logs + uint64 since = 2; + // stream logs continuously + bool stream = 3; +} + +// LogEvent is service log event +message LogEvent { + // event log record + // TODO: change this + string record = 1; +} From 3f7f2afc7bc4bd48cd7aad105cba662ac8a915b1 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 26 Nov 2019 17:04:44 +0000 Subject: [PATCH 273/344] Dont be stupid -- stream does not require pointer. --- debug/handler/debug.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index 51a8aa9f..d59d6b75 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -8,15 +8,15 @@ import ( proto "github.com/micro/go-micro/debug/proto" ) -type Debug struct { - proto.DebugHandler - started int64 -} - var ( + // DefaultHandler is default debug handler DefaultHandler = newDebug() ) +type Debug struct { + started int64 +} + func newDebug() *Debug { return &Debug{ started: time.Now().Unix(), @@ -40,6 +40,6 @@ func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.S return nil } -func (d *Debug) Log(ctx context.Context, req *proto.LogRequest, rsp *proto.Debug_LogStream) error { +func (d *Debug) Log(ctx context.Context, req *proto.LogRequest, rsp proto.Debug_LogStream) error { return nil } From ee9776e7b20af25310d0155c4945e8dd62da0797 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 27 Nov 2019 16:02:16 +0000 Subject: [PATCH 274/344] Added debug.Logger interface --- debug/buffer/buffer.go | 16 ++-- debug/log/default.go | 48 +++++++++++ debug/log/default_test.go | 26 ++++++ debug/log/logger.go | 171 ++++++++++++++++++++++++++++++++++++++ debug/log/options.go | 24 ++++++ 5 files changed, 278 insertions(+), 7 deletions(-) create mode 100644 debug/log/default.go create mode 100644 debug/log/default_test.go create mode 100644 debug/log/logger.go create mode 100644 debug/log/options.go diff --git a/debug/buffer/buffer.go b/debug/buffer/buffer.go index 8c55790c..50c511d4 100644 --- a/debug/buffer/buffer.go +++ b/debug/buffer/buffer.go @@ -17,6 +17,14 @@ type Entry struct { Timestamp time.Time } +// New returns a new buffer of the given size +func New(i int) *Buffer { + return &Buffer{ + size: i, + } +} + +// Put adds a new value to ring buffer func (b *Buffer) Put(v interface{}) { b.Lock() defer b.Unlock() @@ -83,13 +91,7 @@ func (b *Buffer) Since(t time.Time) []*Entry { return nil } +// Size returns the size of the ring buffer func (b *Buffer) Size() int { return b.size } - -// New returns a new buffer of the given size -func New(i int) *Buffer { - return &Buffer{ - size: i, - } -} diff --git a/debug/log/default.go b/debug/log/default.go new file mode 100644 index 00000000..9059c104 --- /dev/null +++ b/debug/log/default.go @@ -0,0 +1,48 @@ +package log + +import ( + "fmt" + golog "log" + + "github.com/micro/go-micro/debug/buffer" +) + +var ( + // DefaultSize of the logger buffer + DefaultSize = 1000 +) + +// defaultLogger is default micro logger +type defaultLogger struct { + *buffer.Buffer +} + +// NewLogger returns default Logger with +func NewLogger(opts ...Option) Logger { + // get default options + options := DefaultOptions() + + // apply requested options + for _, o := range opts { + o(&options) + } + + return &defaultLogger{ + Buffer: buffer.New(options.Size), + } +} + +// Write writes log into logger +func (l *defaultLogger) Write(v ...interface{}) { + l.log(fmt.Sprint(v...)) + golog.Print(v...) +} + +// Read reads logs from the logger +func (l *defaultLogger) Read(n int) []interface{} { + return l.Get(n) +} + +func (l *defaultLogger) log(entry string) { + l.Buffer.Put(entry) +} diff --git a/debug/log/default_test.go b/debug/log/default_test.go new file mode 100644 index 00000000..53ce9a92 --- /dev/null +++ b/debug/log/default_test.go @@ -0,0 +1,26 @@ +package log + +import ( + "reflect" + "testing" +) + +func TestLogger(t *testing.T) { + // make sure we have the right size of the logger ring buffer + if logger.(*defaultLogger).Size() != DefaultSize { + t.Errorf("expected buffer size: %d, got: %d", DefaultSize, logger.(*defaultLogger).Size()) + } + + // Log some cruft + Log("foobar") + Logf("foo %s", "bar") + + // Check if the logs are stored in the logger ring buffer + expectedEntries := []string{"foobar", "foo bar"} + entries := logger.Read(len(expectedEntries)) + for i, entry := range entries { + if !reflect.DeepEqual(entry, expectedEntries[i]) { + t.Errorf("expected %s, got %s", expectedEntries[i], entry) + } + } +} diff --git a/debug/log/logger.go b/debug/log/logger.go new file mode 100644 index 00000000..f46666f1 --- /dev/null +++ b/debug/log/logger.go @@ -0,0 +1,171 @@ +// Package log provides debug logging +package log + +import ( + "fmt" + "os" +) + +var ( + // logger is default Logger + logger Logger = NewLogger() + // default log level is info + level = LevelInfo + // prefix for all messages + prefix string +) + +// Logger is event logger +type Logger interface { + // Read reads specified number of log entries + Read(int) []interface{} + // Write writes logs to logger + Write(...interface{}) +} + +// level is a log level +type Level int + +const ( + LevelFatal Level = iota + LevelError + LevelInfo + LevelWarn + LevelDebug + LevelTrace +) + +func init() { + switch os.Getenv("MICRO_LOG_LEVEL") { + case "trace": + level = LevelTrace + case "debug": + level = LevelDebug + case "warn": + level = LevelWarn + case "info": + level = LevelInfo + case "error": + level = LevelError + case "fatal": + level = LevelFatal + } +} + +func Log(v ...interface{}) { + if len(prefix) > 0 { + logger.Write(fmt.Sprint(append([]interface{}{prefix, " "}, v...)...)) + return + } + logger.Write(fmt.Sprint(v...)) +} + +func Logf(format string, v ...interface{}) { + if len(prefix) > 0 { + format = prefix + " " + format + } + logger.Write(fmt.Sprintf(format, v...)) +} + +// WithLevel logs with the level specified +func WithLevel(l Level, v ...interface{}) { + if l > level { + return + } + Log(v...) +} + +// WithLevel logs with the level specified +func WithLevelf(l Level, format string, v ...interface{}) { + if l > level { + return + } + Logf(format, v...) +} + +// Trace provides trace level logging +func Trace(v ...interface{}) { + WithLevel(LevelTrace, v...) +} + +// Tracef provides trace level logging +func Tracef(format string, v ...interface{}) { + WithLevelf(LevelTrace, format, v...) +} + +// Debug provides debug level logging +func Debug(v ...interface{}) { + WithLevel(LevelDebug, v...) +} + +// Debugf provides debug level logging +func Debugf(format string, v ...interface{}) { + WithLevelf(LevelDebug, format, v...) +} + +// Warn provides warn level logging +func Warn(v ...interface{}) { + WithLevel(LevelWarn, v...) +} + +// Warnf provides warn level logging +func Warnf(format string, v ...interface{}) { + WithLevelf(LevelWarn, format, v...) +} + +// Info provides info level logging +func Info(v ...interface{}) { + WithLevel(LevelInfo, v...) +} + +// Infof provides info level logging +func Infof(format string, v ...interface{}) { + WithLevelf(LevelInfo, format, v...) +} + +// Error provides warn level logging +func Error(v ...interface{}) { + WithLevel(LevelError, v...) +} + +// Errorf provides warn level logging +func Errorf(format string, v ...interface{}) { + WithLevelf(LevelError, format, v...) +} + +// Fatal logs with Log and then exits with os.Exit(1) +func Fatal(v ...interface{}) { + WithLevel(LevelFatal, v...) + os.Exit(1) +} + +// Fatalf logs with Logf and then exits with os.Exit(1) +func Fatalf(format string, v ...interface{}) { + WithLevelf(LevelFatal, format, v...) + os.Exit(1) +} + +// GetLogger returns the local logger +func GetLogger() Logger { + return logger +} + +// SetLevel sets the log level +func SetLevel(l Level) { + level = l +} + +// GetLevel returns the current level +func GetLevel() Level { + return level +} + +// Set a prefix for the logger +func SetPrefix(p string) { + prefix = p +} + +// Set service name +func Name(name string) { + prefix = fmt.Sprintf("[%s]", name) +} diff --git a/debug/log/options.go b/debug/log/options.go new file mode 100644 index 00000000..cd2fafcd --- /dev/null +++ b/debug/log/options.go @@ -0,0 +1,24 @@ +package log + +// Option used by the logger +type Option func(*Options) + +// Options are logger options +type Options struct { + // Size is the size of ring buffer + Size int +} + +// Size sets the size of the ring buffer +func Size(s int) Option { + return func(o *Options) { + o.Size = s + } +} + +// DefaultOptions returns default options +func DefaultOptions() Options { + return Options{ + Size: DefaultSize, + } +} From 9e177be560a05e20dd7d041f3e685d76f8ab7b59 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 27 Nov 2019 16:12:39 +0000 Subject: [PATCH 275/344] Embed logger into debug.Handler --- debug/handler/debug.go | 3 +++ debug/log/default.go | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index d59d6b75..c7095605 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -5,6 +5,8 @@ import ( "runtime" "time" + "github.com/micro/go-micro/debug/log" + proto "github.com/micro/go-micro/debug/proto" ) @@ -15,6 +17,7 @@ var ( type Debug struct { started int64 + log.Logger } func newDebug() *Debug { diff --git a/debug/log/default.go b/debug/log/default.go index 9059c104..641bf037 100644 --- a/debug/log/default.go +++ b/debug/log/default.go @@ -40,7 +40,12 @@ func (l *defaultLogger) Write(v ...interface{}) { // Read reads logs from the logger func (l *defaultLogger) Read(n int) []interface{} { - return l.Get(n) + entries := l.Get(n) + vals := make([]interface{}, 0, len(entries)) + for _, val := range entries { + vals = append(vals, val) + } + return vals } func (l *defaultLogger) log(entry string) { From 7deafbc5ce4e91651430b1355b560f5e5efa7947 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 27 Nov 2019 17:31:35 +0000 Subject: [PATCH 276/344] Added ReadOptions; Changed proto; Reimplemented Log(er) --- debug/handler/debug.go | 4 +- debug/log/default.go | 48 +++++++++----- debug/log/default_test.go | 22 +++--- debug/log/{logger.go => log.go} | 34 ++++++---- debug/log/options.go | 27 ++++++++ debug/proto/debug.pb.go | 114 +++++++++++++++++++------------- debug/proto/debug.pb.micro.go | 46 ++++++------- debug/proto/debug.proto | 15 +++-- 8 files changed, 195 insertions(+), 115 deletions(-) rename debug/log/{logger.go => log.go} (86%) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index c7095605..8b8eedfd 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -17,7 +17,7 @@ var ( type Debug struct { started int64 - log.Logger + log.Log } func newDebug() *Debug { @@ -43,6 +43,6 @@ func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.S return nil } -func (d *Debug) Log(ctx context.Context, req *proto.LogRequest, rsp proto.Debug_LogStream) error { +func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, rsp proto.Debug_LogsStream) error { return nil } diff --git a/debug/log/default.go b/debug/log/default.go index 641bf037..b3840909 100644 --- a/debug/log/default.go +++ b/debug/log/default.go @@ -12,13 +12,13 @@ var ( DefaultSize = 1000 ) -// defaultLogger is default micro logger -type defaultLogger struct { +// defaultLog is default micro log +type defaultLog struct { *buffer.Buffer } -// NewLogger returns default Logger with -func NewLogger(opts ...Option) Logger { +// NewLog returns default Logger with +func NewLog(opts ...Option) Log { // get default options options := DefaultOptions() @@ -27,27 +27,43 @@ func NewLogger(opts ...Option) Logger { o(&options) } - return &defaultLogger{ + return &defaultLog{ Buffer: buffer.New(options.Size), } } // Write writes log into logger -func (l *defaultLogger) Write(v ...interface{}) { - l.log(fmt.Sprint(v...)) +func (l *defaultLog) Write(v ...interface{}) { + l.Buffer.Put(fmt.Sprint(v...)) golog.Print(v...) } // Read reads logs from the logger -func (l *defaultLogger) Read(n int) []interface{} { - entries := l.Get(n) - vals := make([]interface{}, 0, len(entries)) - for _, val := range entries { - vals = append(vals, val) +func (l *defaultLog) Read(opts ...ReadOption) []Record { + options := ReadOptions{} + // initialize the read options + for _, o := range opts { + o(&options) } - return vals -} -func (l *defaultLogger) log(entry string) { - l.Buffer.Put(entry) + var entries []*buffer.Entry + // if Since options ha sbeen specified we honor it + if !options.Since.IsZero() { + entries = l.Buffer.Since(options.Since) + } else { + // otherwie return last count entries + entries = l.Buffer.Get(options.Count) + } + + // TODO: if both Since and Count are set should we return + // last Count from the returned time scoped entries? + records := make([]Record, 0, len(entries)) + for _, entry := range entries { + record := Record{ + Timestamp: entry.Timestamp, + Value: entry.Value, + } + records = append(records, record) + } + return records } diff --git a/debug/log/default_test.go b/debug/log/default_test.go index 53ce9a92..0ef6e903 100644 --- a/debug/log/default_test.go +++ b/debug/log/default_test.go @@ -6,21 +6,27 @@ import ( ) func TestLogger(t *testing.T) { + // set size to some value + size := 100 + // override the global logger + logger = NewLog(Size(size)) // make sure we have the right size of the logger ring buffer - if logger.(*defaultLogger).Size() != DefaultSize { - t.Errorf("expected buffer size: %d, got: %d", DefaultSize, logger.(*defaultLogger).Size()) + if logger.(*defaultLog).Size() != size { + t.Errorf("expected buffer size: %d, got: %d", size, logger.(*defaultLog).Size()) } // Log some cruft - Log("foobar") - Logf("foo %s", "bar") + Info("foobar") + // increase the log level + level = LevelDebug + Debugf("foo %s", "bar") // Check if the logs are stored in the logger ring buffer - expectedEntries := []string{"foobar", "foo bar"} - entries := logger.Read(len(expectedEntries)) + expected := []string{"foobar", "foo bar"} + entries := logger.Read(Count(len(expected))) for i, entry := range entries { - if !reflect.DeepEqual(entry, expectedEntries[i]) { - t.Errorf("expected %s, got %s", expectedEntries[i], entry) + if !reflect.DeepEqual(entry.Value, expected[i]) { + t.Errorf("expected %s, got %s", expected[i], entry.Value) } } } diff --git a/debug/log/logger.go b/debug/log/log.go similarity index 86% rename from debug/log/logger.go rename to debug/log/log.go index f46666f1..1c9ae240 100644 --- a/debug/log/logger.go +++ b/debug/log/log.go @@ -4,25 +4,36 @@ package log import ( "fmt" "os" + "time" ) var ( // logger is default Logger - logger Logger = NewLogger() + logger Log = NewLog() // default log level is info level = LevelInfo // prefix for all messages prefix string ) -// Logger is event logger -type Logger interface { - // Read reads specified number of log entries - Read(int) []interface{} +// Log is event log +type Log interface { + // Read reads log entries from the logger + Read(...ReadOption) []Record // Write writes logs to logger Write(...interface{}) } +// Record is log record entry +type Record struct { + // Timestamp of logged event + Timestamp time.Time + // Value contains log entry + Value interface{} + // Metadata to enrich log record + Metadata map[string]string +} + // level is a log level type Level int @@ -52,7 +63,7 @@ func init() { } } -func Log(v ...interface{}) { +func log(v ...interface{}) { if len(prefix) > 0 { logger.Write(fmt.Sprint(append([]interface{}{prefix, " "}, v...)...)) return @@ -60,7 +71,7 @@ func Log(v ...interface{}) { logger.Write(fmt.Sprint(v...)) } -func Logf(format string, v ...interface{}) { +func logf(format string, v ...interface{}) { if len(prefix) > 0 { format = prefix + " " + format } @@ -72,7 +83,7 @@ func WithLevel(l Level, v ...interface{}) { if l > level { return } - Log(v...) + log(v...) } // WithLevel logs with the level specified @@ -80,7 +91,7 @@ func WithLevelf(l Level, format string, v ...interface{}) { if l > level { return } - Logf(format, v...) + logf(format, v...) } // Trace provides trace level logging @@ -145,11 +156,6 @@ func Fatalf(format string, v ...interface{}) { os.Exit(1) } -// GetLogger returns the local logger -func GetLogger() Logger { - return logger -} - // SetLevel sets the log level func SetLevel(l Level) { level = l diff --git a/debug/log/options.go b/debug/log/options.go index cd2fafcd..2320b71e 100644 --- a/debug/log/options.go +++ b/debug/log/options.go @@ -1,5 +1,7 @@ package log +import "time" + // Option used by the logger type Option func(*Options) @@ -22,3 +24,28 @@ func DefaultOptions() Options { Size: DefaultSize, } } + +// ReadOptions for querying the logs +type ReadOptions struct { + // Since what time in past to return the logs + Since time.Time + // Count specifies number of logs to return + Count int +} + +// ReadOption used for reading the logs +type ReadOption func(*ReadOptions) + +// Since sets the time since which to return the log records +func Since(s time.Time) ReadOption { + return func(o *ReadOptions) { + o.Since = s + } +} + +// Count sets the number of log records to return +func Count(c int) ReadOption { + return func(o *ReadOptions) { + o.Count = c + } +} diff --git a/debug/proto/debug.pb.go b/debug/proto/debug.pb.go index d4ceaa11..b8236261 100644 --- a/debug/proto/debug.pb.go +++ b/debug/proto/debug.pb.go @@ -259,78 +259,100 @@ func (m *LogRequest) GetStream() bool { return false } -// LogEvent is service log event -type LogEvent struct { - // event log record - // TODO: change this - Record string `protobuf:"bytes,1,opt,name=record,proto3" json:"record,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +// Log is service log record +type Log struct { + // timestamp of log event + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // log value + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + // metadata + Metadata map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *LogEvent) Reset() { *m = LogEvent{} } -func (m *LogEvent) String() string { return proto.CompactTextString(m) } -func (*LogEvent) ProtoMessage() {} -func (*LogEvent) Descriptor() ([]byte, []int) { +func (m *Log) Reset() { *m = Log{} } +func (m *Log) String() string { return proto.CompactTextString(m) } +func (*Log) ProtoMessage() {} +func (*Log) Descriptor() ([]byte, []int) { return fileDescriptor_8d9d361be58531fb, []int{5} } -func (m *LogEvent) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogEvent.Unmarshal(m, b) +func (m *Log) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Log.Unmarshal(m, b) } -func (m *LogEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogEvent.Marshal(b, m, deterministic) +func (m *Log) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Log.Marshal(b, m, deterministic) } -func (m *LogEvent) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogEvent.Merge(m, src) +func (m *Log) XXX_Merge(src proto.Message) { + xxx_messageInfo_Log.Merge(m, src) } -func (m *LogEvent) XXX_Size() int { - return xxx_messageInfo_LogEvent.Size(m) +func (m *Log) XXX_Size() int { + return xxx_messageInfo_Log.Size(m) } -func (m *LogEvent) XXX_DiscardUnknown() { - xxx_messageInfo_LogEvent.DiscardUnknown(m) +func (m *Log) XXX_DiscardUnknown() { + xxx_messageInfo_Log.DiscardUnknown(m) } -var xxx_messageInfo_LogEvent proto.InternalMessageInfo +var xxx_messageInfo_Log proto.InternalMessageInfo -func (m *LogEvent) GetRecord() string { +func (m *Log) GetTimestamp() int64 { if m != nil { - return m.Record + return m.Timestamp + } + return 0 +} + +func (m *Log) GetValue() string { + if m != nil { + return m.Value } return "" } +func (m *Log) GetMetadata() map[string]string { + if m != nil { + return m.Metadata + } + return nil +} + func init() { proto.RegisterType((*HealthRequest)(nil), "HealthRequest") proto.RegisterType((*HealthResponse)(nil), "HealthResponse") proto.RegisterType((*StatsRequest)(nil), "StatsRequest") proto.RegisterType((*StatsResponse)(nil), "StatsResponse") proto.RegisterType((*LogRequest)(nil), "LogRequest") - proto.RegisterType((*LogEvent)(nil), "LogEvent") + proto.RegisterType((*Log)(nil), "Log") + proto.RegisterMapType((map[string]string)(nil), "Log.MetadataEntry") } func init() { proto.RegisterFile("debug.proto", fileDescriptor_8d9d361be58531fb) } var fileDescriptor_8d9d361be58531fb = []byte{ - // 290 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x91, 0xdd, 0x4a, 0xc3, 0x30, - 0x14, 0xc7, 0xd7, 0x6d, 0x9d, 0xdb, 0x99, 0xeb, 0x20, 0x88, 0x84, 0x5d, 0x69, 0xae, 0x06, 0x42, - 0x10, 0x7d, 0x05, 0x05, 0x2f, 0x76, 0x21, 0xf5, 0x09, 0xb2, 0xf6, 0x90, 0x0d, 0x6c, 0x33, 0x93, - 0x53, 0xc1, 0x4b, 0xf1, 0xc5, 0x25, 0x5f, 0xe8, 0x2e, 0x7f, 0xff, 0xf6, 0x7c, 0xfd, 0x02, 0xcb, - 0x16, 0xf7, 0x83, 0x96, 0x27, 0x6b, 0xc8, 0x88, 0x35, 0xac, 0x5e, 0x50, 0xbd, 0xd3, 0xa1, 0xc6, - 0x8f, 0x01, 0x1d, 0x89, 0x2d, 0x54, 0x39, 0x70, 0x27, 0xd3, 0x3b, 0x64, 0xd7, 0x30, 0x73, 0xa4, - 0x68, 0x70, 0xbc, 0xb8, 0x29, 0xb6, 0x8b, 0x3a, 0x91, 0xa8, 0xe0, 0xf2, 0x8d, 0x14, 0xb9, 0x5c, - 0xf9, 0x53, 0xc0, 0x2a, 0x05, 0xa9, 0x92, 0xc3, 0x85, 0x23, 0x65, 0x09, 0xdb, 0x50, 0x3a, 0xad, - 0x33, 0xfa, 0x9e, 0xc3, 0x89, 0x8e, 0x1d, 0xf2, 0x71, 0xf8, 0x90, 0xc8, 0xe7, 0x1d, 0x76, 0xc6, - 0x7e, 0xf1, 0x49, 0xcc, 0x23, 0xf9, 0x4e, 0x74, 0xb0, 0xa8, 0x5a, 0xc7, 0xa7, 0xb1, 0x53, 0x42, - 0x56, 0xc1, 0x58, 0x37, 0xbc, 0x0c, 0xe1, 0x58, 0x37, 0xe2, 0x15, 0x60, 0x67, 0x74, 0xda, 0x89, - 0x5d, 0x41, 0xd9, 0x98, 0xa1, 0xa7, 0x34, 0x3f, 0x82, 0x4f, 0xdd, 0xb1, 0x6f, 0xf2, 0xf0, 0x08, - 0xf1, 0x4e, 0x8b, 0xaa, 0x0b, 0xb3, 0xe7, 0x75, 0x22, 0x21, 0x60, 0xbe, 0x33, 0xfa, 0xf9, 0x13, - 0x7b, 0xf2, 0xff, 0x58, 0x6c, 0x8c, 0x6d, 0xb3, 0x8b, 0x48, 0x0f, 0xdf, 0x05, 0x94, 0x4f, 0x5e, - 0x2b, 0xbb, 0x83, 0x59, 0xf4, 0xc7, 0x2a, 0x79, 0x66, 0x76, 0xb3, 0x96, 0xe7, 0x62, 0xc5, 0x88, - 0x6d, 0xa1, 0x0c, 0xc6, 0xd8, 0x4a, 0xfe, 0x57, 0xb9, 0xa9, 0xe4, 0x99, 0x48, 0x31, 0x62, 0xb7, - 0x30, 0xd9, 0x19, 0xcd, 0x96, 0xf2, 0xef, 0xb8, 0xcd, 0x42, 0xe6, 0xbd, 0xc4, 0xe8, 0xbe, 0xd8, - 0xcf, 0xc2, 0x8b, 0x3e, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x70, 0x27, 0xbe, 0x8c, 0xe0, 0x01, - 0x00, 0x00, + // 359 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xcd, 0x6a, 0xe3, 0x30, + 0x14, 0x85, 0xe3, 0xbf, 0x4c, 0x72, 0x33, 0x76, 0x06, 0x31, 0x0c, 0xc6, 0xcc, 0x40, 0xd0, 0xca, + 0x30, 0x20, 0x86, 0xcc, 0xa6, 0xb4, 0xdb, 0x16, 0xba, 0x70, 0xa1, 0xb8, 0x4f, 0xa0, 0xd8, 0xc2, + 0x09, 0x8d, 0x2d, 0xd7, 0xba, 0x2e, 0x64, 0xd1, 0x55, 0xdf, 0xa5, 0xcf, 0x59, 0x64, 0xc9, 0x4d, + 0x0d, 0xdd, 0xf9, 0x3b, 0xf2, 0x3d, 0x47, 0xbe, 0xc7, 0xb0, 0x2a, 0xc5, 0xae, 0xaf, 0x58, 0xdb, + 0x49, 0x94, 0x74, 0x0d, 0xe1, 0xad, 0xe0, 0x47, 0xdc, 0xe7, 0xe2, 0xa9, 0x17, 0x0a, 0x69, 0x0a, + 0xd1, 0x28, 0xa8, 0x56, 0x36, 0x4a, 0x90, 0x5f, 0x30, 0x57, 0xc8, 0xb1, 0x57, 0xb1, 0xb3, 0x71, + 0xd2, 0x65, 0x6e, 0x89, 0x46, 0xf0, 0xfd, 0x01, 0x39, 0xaa, 0x71, 0xf2, 0xd5, 0x81, 0xd0, 0x0a, + 0x76, 0x32, 0x86, 0x6f, 0x0a, 0x79, 0x87, 0xa2, 0x1c, 0x46, 0xfd, 0x7c, 0x44, 0xed, 0xd9, 0xb7, + 0x78, 0xa8, 0x45, 0xec, 0x0e, 0x07, 0x96, 0xb4, 0x5e, 0x8b, 0x5a, 0x76, 0xa7, 0xd8, 0x33, 0xba, + 0x21, 0xed, 0x84, 0xfb, 0x4e, 0xf0, 0x52, 0xc5, 0xbe, 0x71, 0xb2, 0x48, 0x22, 0x70, 0xab, 0x22, + 0x0e, 0x06, 0xd1, 0xad, 0x0a, 0x7a, 0x0f, 0x90, 0xc9, 0xca, 0xde, 0x89, 0xfc, 0x84, 0xa0, 0x90, + 0x7d, 0x83, 0x36, 0xdf, 0x80, 0x56, 0xd5, 0xa1, 0x29, 0xc6, 0x70, 0x03, 0xe6, 0x3b, 0x3b, 0xc1, + 0xeb, 0x21, 0x7b, 0x91, 0x5b, 0xa2, 0x6f, 0x0e, 0x78, 0x99, 0xac, 0xc8, 0x6f, 0x58, 0xea, 0x3b, + 0x2a, 0xe4, 0x75, 0x3b, 0xf8, 0x79, 0xf9, 0x59, 0xd0, 0x9e, 0xcf, 0xfc, 0xd8, 0x1b, 0xcf, 0x65, + 0x6e, 0x80, 0x30, 0x58, 0xd4, 0x02, 0x79, 0xc9, 0x91, 0xc7, 0xde, 0xc6, 0x4b, 0x57, 0x5b, 0xc2, + 0x32, 0x59, 0xb1, 0x3b, 0x2b, 0xde, 0x34, 0xd8, 0x9d, 0xf2, 0x8f, 0x77, 0x92, 0x2b, 0x08, 0x27, + 0x47, 0xe4, 0x07, 0x78, 0x8f, 0xe2, 0x64, 0x37, 0xaf, 0x1f, 0xbf, 0x0e, 0xba, 0x74, 0x2f, 0x9c, + 0xed, 0x0b, 0x04, 0xd7, 0xba, 0x5a, 0xf2, 0x17, 0xe6, 0xa6, 0x43, 0x12, 0xb1, 0x49, 0xbb, 0xc9, + 0x9a, 0x4d, 0xcb, 0xa5, 0x33, 0x92, 0x42, 0x30, 0xb4, 0x46, 0x42, 0xf6, 0xb9, 0xce, 0x24, 0x62, + 0x93, 0x32, 0xe9, 0x8c, 0xfc, 0x01, 0x3f, 0x93, 0x95, 0x22, 0x2b, 0x76, 0xde, 0x70, 0xe2, 0x6b, + 0xa0, 0xb3, 0x7f, 0xce, 0x6e, 0x3e, 0xfc, 0x51, 0xff, 0xdf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xbe, + 0xa2, 0x1f, 0x47, 0x60, 0x02, 0x00, 0x00, } diff --git a/debug/proto/debug.pb.micro.go b/debug/proto/debug.pb.micro.go index 97cf7345..6f89d5eb 100644 --- a/debug/proto/debug.pb.micro.go +++ b/debug/proto/debug.pb.micro.go @@ -36,7 +36,7 @@ var _ server.Option type DebugService interface { Health(ctx context.Context, in *HealthRequest, opts ...client.CallOption) (*HealthResponse, error) Stats(ctx context.Context, in *StatsRequest, opts ...client.CallOption) (*StatsResponse, error) - Log(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogService, error) + Logs(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogsService, error) } type debugService struct { @@ -77,8 +77,8 @@ func (c *debugService) Stats(ctx context.Context, in *StatsRequest, opts ...clie return out, nil } -func (c *debugService) Log(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogService, error) { - req := c.c.NewRequest(c.name, "Debug.Log", &LogRequest{}) +func (c *debugService) Logs(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogsService, error) { + req := c.c.NewRequest(c.name, "Debug.Logs", &LogRequest{}) stream, err := c.c.Stream(ctx, req, opts...) if err != nil { return nil, err @@ -86,34 +86,34 @@ func (c *debugService) Log(ctx context.Context, in *LogRequest, opts ...client.C if err := stream.Send(in); err != nil { return nil, err } - return &debugServiceLog{stream}, nil + return &debugServiceLogs{stream}, nil } -type Debug_LogService interface { +type Debug_LogsService interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error - Recv() (*LogEvent, error) + Recv() (*Log, error) } -type debugServiceLog struct { +type debugServiceLogs struct { stream client.Stream } -func (x *debugServiceLog) Close() error { +func (x *debugServiceLogs) Close() error { return x.stream.Close() } -func (x *debugServiceLog) SendMsg(m interface{}) error { +func (x *debugServiceLogs) SendMsg(m interface{}) error { return x.stream.Send(m) } -func (x *debugServiceLog) RecvMsg(m interface{}) error { +func (x *debugServiceLogs) RecvMsg(m interface{}) error { return x.stream.Recv(m) } -func (x *debugServiceLog) Recv() (*LogEvent, error) { - m := new(LogEvent) +func (x *debugServiceLogs) Recv() (*Log, error) { + m := new(Log) err := x.stream.Recv(m) if err != nil { return nil, err @@ -126,14 +126,14 @@ func (x *debugServiceLog) Recv() (*LogEvent, error) { type DebugHandler interface { Health(context.Context, *HealthRequest, *HealthResponse) error Stats(context.Context, *StatsRequest, *StatsResponse) error - Log(context.Context, *LogRequest, Debug_LogStream) error + Logs(context.Context, *LogRequest, Debug_LogsStream) error } func RegisterDebugHandler(s server.Server, hdlr DebugHandler, opts ...server.HandlerOption) error { type debug interface { Health(ctx context.Context, in *HealthRequest, out *HealthResponse) error Stats(ctx context.Context, in *StatsRequest, out *StatsResponse) error - Log(ctx context.Context, stream server.Stream) error + Logs(ctx context.Context, stream server.Stream) error } type Debug struct { debug @@ -154,37 +154,37 @@ func (h *debugHandler) Stats(ctx context.Context, in *StatsRequest, out *StatsRe return h.DebugHandler.Stats(ctx, in, out) } -func (h *debugHandler) Log(ctx context.Context, stream server.Stream) error { +func (h *debugHandler) Logs(ctx context.Context, stream server.Stream) error { m := new(LogRequest) if err := stream.Recv(m); err != nil { return err } - return h.DebugHandler.Log(ctx, m, &debugLogStream{stream}) + return h.DebugHandler.Logs(ctx, m, &debugLogsStream{stream}) } -type Debug_LogStream interface { +type Debug_LogsStream interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error - Send(*LogEvent) error + Send(*Log) error } -type debugLogStream struct { +type debugLogsStream struct { stream server.Stream } -func (x *debugLogStream) Close() error { +func (x *debugLogsStream) Close() error { return x.stream.Close() } -func (x *debugLogStream) SendMsg(m interface{}) error { +func (x *debugLogsStream) SendMsg(m interface{}) error { return x.stream.Send(m) } -func (x *debugLogStream) RecvMsg(m interface{}) error { +func (x *debugLogsStream) RecvMsg(m interface{}) error { return x.stream.Recv(m) } -func (x *debugLogStream) Send(m *LogEvent) error { +func (x *debugLogsStream) Send(m *Log) error { return x.stream.Send(m) } diff --git a/debug/proto/debug.proto b/debug/proto/debug.proto index 648e48a8..25030153 100644 --- a/debug/proto/debug.proto +++ b/debug/proto/debug.proto @@ -3,7 +3,7 @@ syntax = "proto3"; service Debug { rpc Health(HealthRequest) returns (HealthResponse) {}; rpc Stats(StatsRequest) returns (StatsResponse) {}; - rpc Log(LogRequest) returns (stream LogEvent) {}; + rpc Logs(LogRequest) returns (stream Log) {}; } message HealthRequest {} @@ -40,9 +40,12 @@ message LogRequest { bool stream = 3; } -// LogEvent is service log event -message LogEvent { - // event log record - // TODO: change this - string record = 1; +// Log is service log record +message Log { + // timestamp of log event + int64 timestamp = 1; + // log value + string value = 2; + // metadata + map metadata = 3; } From b01357058a8e232c9d36a9e95746963054da3790 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 27 Nov 2019 18:38:26 +0000 Subject: [PATCH 277/344] Regenerate proto cruft --- debug/handler/debug.go | 31 ++++++++++++++++++++++- debug/proto/debug.pb.go | 56 ++++++++++++++++++++--------------------- debug/proto/debug.proto | 4 +-- 3 files changed, 60 insertions(+), 31 deletions(-) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index 8b8eedfd..e532de79 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -43,6 +43,35 @@ func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.S return nil } -func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, rsp proto.Debug_LogsStream) error { +func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.Debug_LogsStream) error { + var records []log.Record + since := time.Unix(0, req.Since) + if !since.IsZero() { + records = d.Log.Read(log.Since(since)) + } else { + records = d.Log.Read(log.Count(int(req.Count))) + } + + defer stream.Close() + + // TODO: figure out the stream later on + // stream the logs + for _, record := range records { + metadata := make(map[string]string) + for k, v := range record.Metadata { + metadata[k] = v + } + + recLog := &proto.Log{ + Timestamp: record.Timestamp.UnixNano(), + Value: record.Value.(string), + Metadata: metadata, + } + + if err := stream.Send(recLog); err != nil { + return err + } + } + return nil } diff --git a/debug/proto/debug.pb.go b/debug/proto/debug.pb.go index b8236261..423e98cc 100644 --- a/debug/proto/debug.pb.go +++ b/debug/proto/debug.pb.go @@ -201,11 +201,11 @@ func (m *StatsResponse) GetGc() uint64 { // LogRequest queries service for logs type LogRequest struct { // count is the count of events - Count uint64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` // relative time in seconds // before the current time // from which to show logs - Since uint64 `protobuf:"varint,2,opt,name=since,proto3" json:"since,omitempty"` + Since int64 `protobuf:"varint,2,opt,name=since,proto3" json:"since,omitempty"` // stream logs continuously Stream bool `protobuf:"varint,3,opt,name=stream,proto3" json:"stream,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -238,14 +238,14 @@ func (m *LogRequest) XXX_DiscardUnknown() { var xxx_messageInfo_LogRequest proto.InternalMessageInfo -func (m *LogRequest) GetCount() uint64 { +func (m *LogRequest) GetCount() int64 { if m != nil { return m.Count } return 0 } -func (m *LogRequest) GetSince() uint64 { +func (m *LogRequest) GetSince() int64 { if m != nil { return m.Since } @@ -331,28 +331,28 @@ func init() { func init() { proto.RegisterFile("debug.proto", fileDescriptor_8d9d361be58531fb) } var fileDescriptor_8d9d361be58531fb = []byte{ - // 359 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xcd, 0x6a, 0xe3, 0x30, - 0x14, 0x85, 0xe3, 0xbf, 0x4c, 0x72, 0x33, 0x76, 0x06, 0x31, 0x0c, 0xc6, 0xcc, 0x40, 0xd0, 0xca, - 0x30, 0x20, 0x86, 0xcc, 0xa6, 0xb4, 0xdb, 0x16, 0xba, 0x70, 0xa1, 0xb8, 0x4f, 0xa0, 0xd8, 0xc2, - 0x09, 0x8d, 0x2d, 0xd7, 0xba, 0x2e, 0x64, 0xd1, 0x55, 0xdf, 0xa5, 0xcf, 0x59, 0x64, 0xc9, 0x4d, - 0x0d, 0xdd, 0xf9, 0x3b, 0xf2, 0x3d, 0x47, 0xbe, 0xc7, 0xb0, 0x2a, 0xc5, 0xae, 0xaf, 0x58, 0xdb, - 0x49, 0x94, 0x74, 0x0d, 0xe1, 0xad, 0xe0, 0x47, 0xdc, 0xe7, 0xe2, 0xa9, 0x17, 0x0a, 0x69, 0x0a, - 0xd1, 0x28, 0xa8, 0x56, 0x36, 0x4a, 0x90, 0x5f, 0x30, 0x57, 0xc8, 0xb1, 0x57, 0xb1, 0xb3, 0x71, - 0xd2, 0x65, 0x6e, 0x89, 0x46, 0xf0, 0xfd, 0x01, 0x39, 0xaa, 0x71, 0xf2, 0xd5, 0x81, 0xd0, 0x0a, - 0x76, 0x32, 0x86, 0x6f, 0x0a, 0x79, 0x87, 0xa2, 0x1c, 0x46, 0xfd, 0x7c, 0x44, 0xed, 0xd9, 0xb7, - 0x78, 0xa8, 0x45, 0xec, 0x0e, 0x07, 0x96, 0xb4, 0x5e, 0x8b, 0x5a, 0x76, 0xa7, 0xd8, 0x33, 0xba, - 0x21, 0xed, 0x84, 0xfb, 0x4e, 0xf0, 0x52, 0xc5, 0xbe, 0x71, 0xb2, 0x48, 0x22, 0x70, 0xab, 0x22, - 0x0e, 0x06, 0xd1, 0xad, 0x0a, 0x7a, 0x0f, 0x90, 0xc9, 0xca, 0xde, 0x89, 0xfc, 0x84, 0xa0, 0x90, - 0x7d, 0x83, 0x36, 0xdf, 0x80, 0x56, 0xd5, 0xa1, 0x29, 0xc6, 0x70, 0x03, 0xe6, 0x3b, 0x3b, 0xc1, - 0xeb, 0x21, 0x7b, 0x91, 0x5b, 0xa2, 0x6f, 0x0e, 0x78, 0x99, 0xac, 0xc8, 0x6f, 0x58, 0xea, 0x3b, - 0x2a, 0xe4, 0x75, 0x3b, 0xf8, 0x79, 0xf9, 0x59, 0xd0, 0x9e, 0xcf, 0xfc, 0xd8, 0x1b, 0xcf, 0x65, - 0x6e, 0x80, 0x30, 0x58, 0xd4, 0x02, 0x79, 0xc9, 0x91, 0xc7, 0xde, 0xc6, 0x4b, 0x57, 0x5b, 0xc2, - 0x32, 0x59, 0xb1, 0x3b, 0x2b, 0xde, 0x34, 0xd8, 0x9d, 0xf2, 0x8f, 0x77, 0x92, 0x2b, 0x08, 0x27, - 0x47, 0xe4, 0x07, 0x78, 0x8f, 0xe2, 0x64, 0x37, 0xaf, 0x1f, 0xbf, 0x0e, 0xba, 0x74, 0x2f, 0x9c, - 0xed, 0x0b, 0x04, 0xd7, 0xba, 0x5a, 0xf2, 0x17, 0xe6, 0xa6, 0x43, 0x12, 0xb1, 0x49, 0xbb, 0xc9, - 0x9a, 0x4d, 0xcb, 0xa5, 0x33, 0x92, 0x42, 0x30, 0xb4, 0x46, 0x42, 0xf6, 0xb9, 0xce, 0x24, 0x62, - 0x93, 0x32, 0xe9, 0x8c, 0xfc, 0x01, 0x3f, 0x93, 0x95, 0x22, 0x2b, 0x76, 0xde, 0x70, 0xe2, 0x6b, - 0xa0, 0xb3, 0x7f, 0xce, 0x6e, 0x3e, 0xfc, 0x51, 0xff, 0xdf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xbe, - 0xa2, 0x1f, 0x47, 0x60, 0x02, 0x00, 0x00, + // 360 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0x5f, 0x6b, 0xdb, 0x30, + 0x14, 0xc5, 0xe3, 0x7f, 0x59, 0x72, 0x33, 0x3b, 0x43, 0x8c, 0x61, 0xcc, 0x06, 0x41, 0x4f, 0x86, + 0x81, 0x18, 0xd9, 0xcb, 0xd8, 0x5e, 0x57, 0xe8, 0x83, 0x0b, 0x45, 0xfd, 0x04, 0x8a, 0x2d, 0x9c, + 0xd0, 0xd8, 0x72, 0xad, 0xeb, 0x42, 0x1e, 0xfa, 0xd4, 0xef, 0xd2, 0xcf, 0x59, 0x64, 0x29, 0x4d, + 0x0d, 0x7d, 0xf3, 0xef, 0xc8, 0xf7, 0x1c, 0xf9, 0x1e, 0xc3, 0xaa, 0x92, 0xbb, 0xa1, 0x66, 0x5d, + 0xaf, 0x50, 0xd1, 0x35, 0xc4, 0xd7, 0x52, 0x1c, 0x71, 0xcf, 0xe5, 0xc3, 0x20, 0x35, 0xd2, 0x1c, + 0x92, 0xb3, 0xa0, 0x3b, 0xd5, 0x6a, 0x49, 0xbe, 0xc1, 0x5c, 0xa3, 0xc0, 0x41, 0xa7, 0xde, 0xc6, + 0xcb, 0x97, 0xdc, 0x11, 0x4d, 0xe0, 0xf3, 0x1d, 0x0a, 0xd4, 0xe7, 0xc9, 0x67, 0x0f, 0x62, 0x27, + 0xb8, 0xc9, 0x14, 0x3e, 0x69, 0x14, 0x3d, 0xca, 0x6a, 0x1c, 0x0d, 0xf9, 0x19, 0x8d, 0xe7, 0xd0, + 0xe1, 0xa1, 0x91, 0xa9, 0x3f, 0x1e, 0x38, 0x32, 0x7a, 0x23, 0x1b, 0xd5, 0x9f, 0xd2, 0xc0, 0xea, + 0x96, 0x8c, 0x13, 0xee, 0x7b, 0x29, 0x2a, 0x9d, 0x86, 0xd6, 0xc9, 0x21, 0x49, 0xc0, 0xaf, 0xcb, + 0x34, 0x1a, 0x45, 0xbf, 0x2e, 0xe9, 0x2d, 0x40, 0xa1, 0x6a, 0x77, 0x27, 0xf2, 0x15, 0xa2, 0x52, + 0x0d, 0x2d, 0x8e, 0xf9, 0x01, 0xb7, 0x60, 0x54, 0x7d, 0x68, 0x4b, 0x1b, 0x1e, 0x70, 0x0b, 0xf6, + 0x3b, 0x7b, 0x29, 0x9a, 0x31, 0x7b, 0xc1, 0x1d, 0xd1, 0x17, 0x0f, 0x82, 0x42, 0xd5, 0xe4, 0x3b, + 0x2c, 0xcd, 0x1d, 0x35, 0x8a, 0xa6, 0x73, 0x7e, 0x17, 0xc1, 0x78, 0x3e, 0x8a, 0xe3, 0x60, 0x3d, + 0x97, 0xdc, 0x02, 0x61, 0xb0, 0x68, 0x24, 0x8a, 0x4a, 0xa0, 0x48, 0x83, 0x4d, 0x90, 0xaf, 0xb6, + 0x84, 0x15, 0xaa, 0x66, 0x37, 0x4e, 0xbc, 0x6a, 0xb1, 0x3f, 0xf1, 0xb7, 0x77, 0xb2, 0x7f, 0x10, + 0x4f, 0x8e, 0xc8, 0x17, 0x08, 0xee, 0xe5, 0xc9, 0x6d, 0xde, 0x3c, 0x7e, 0x1c, 0xf4, 0xd7, 0xff, + 0xe3, 0x6d, 0x9f, 0x20, 0xfa, 0x6f, 0xaa, 0x25, 0x3f, 0x61, 0x6e, 0x3b, 0x24, 0x09, 0x9b, 0xb4, + 0x9b, 0xad, 0xd9, 0xb4, 0x5c, 0x3a, 0x23, 0x39, 0x44, 0x63, 0x6b, 0x24, 0x66, 0xef, 0xeb, 0xcc, + 0x12, 0x36, 0x29, 0x93, 0xce, 0xc8, 0x0f, 0x08, 0x0b, 0x55, 0x6b, 0xb2, 0x62, 0x97, 0x0d, 0x67, + 0xa1, 0x01, 0x3a, 0xfb, 0xe5, 0xed, 0xe6, 0xe3, 0x1f, 0xf5, 0xfb, 0x35, 0x00, 0x00, 0xff, 0xff, + 0x95, 0x24, 0xad, 0xbc, 0x60, 0x02, 0x00, 0x00, } diff --git a/debug/proto/debug.proto b/debug/proto/debug.proto index 25030153..830423b3 100644 --- a/debug/proto/debug.proto +++ b/debug/proto/debug.proto @@ -31,11 +31,11 @@ message StatsResponse { // LogRequest queries service for logs message LogRequest { // count is the count of events - uint64 count = 1; + int64 count = 1; // relative time in seconds // before the current time // from which to show logs - uint64 since = 2; + int64 since = 2; // stream logs continuously bool stream = 3; } From 60e0e81523ed564be9206c117ddd4bd36d4f3323 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Wed, 27 Nov 2019 20:32:54 +0000 Subject: [PATCH 278/344] Added debug/service to grab the logs from a service --- debug/debug.go | 7 ++++ debug/service/service.go | 83 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 debug/debug.go create mode 100644 debug/service/service.go diff --git a/debug/debug.go b/debug/debug.go new file mode 100644 index 00000000..a34d7f28 --- /dev/null +++ b/debug/debug.go @@ -0,0 +1,7 @@ +// Package debug provides micro debug packages +package debug + +var ( + // DefaultName is the name of debug service + DefaultName = "go.micro.debug" +) diff --git a/debug/service/service.go b/debug/service/service.go new file mode 100644 index 00000000..5089058e --- /dev/null +++ b/debug/service/service.go @@ -0,0 +1,83 @@ +package service + +import ( + "context" + "fmt" + "time" + + "github.com/micro/go-micro/client" + + "github.com/micro/go-micro/debug/log" + pb "github.com/micro/go-micro/debug/proto" +) + +// Debug provides debug service client +type Debug struct { + dbg pb.DebugService +} + +// NewDebug provides Debug service implementation +func NewDebug(name string) *Debug { + // create default client + cli := client.DefaultClient + + return &Debug{ + dbg: pb.NewDebugService(name, cli), + } +} + +func (d *Debug) Logs(opts ...log.ReadOption) (<-chan log.Record, error) { + options := log.ReadOptions{} + // initialize the read options + for _, o := range opts { + o(&options) + } + + req := &pb.LogRequest{} + if !options.Since.IsZero() { + req.Since = options.Since.UnixNano() + } + + if options.Count > 0 { + req.Count = int64(options.Count) + } + + // get the log stream + stream, err := d.dbg.Logs(context.Background(), req) + if err != nil { + return nil, fmt.Errorf("failed getting log stream: %s", err) + } + + // log channel for streaming logs + logChan := make(chan log.Record) + // go stream logs + go d.streamLogs(logChan, stream) + + return logChan, nil +} + +func (d *Debug) streamLogs(logChan chan log.Record, stream pb.Debug_LogsService) { + defer stream.Close() + + for { + resp, err := stream.Recv() + if err != nil { + break + } + + metadata := make(map[string]string) + for k, v := range resp.Metadata { + metadata[k] = v + } + + record := log.Record{ + Timestamp: time.Unix(0, resp.Timestamp), + Value: resp.Value, + Metadata: metadata, + } + + logChan <- record + } + + close(logChan) +} From 265e8ade05ab184e9d5fb248bad2ecfd0b854a9b Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 28 Nov 2019 11:05:35 +0000 Subject: [PATCH 279/344] Embed DebugHandler proto --- debug/handler/debug.go | 2 +- debug/log/default.go | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index e532de79..7dd11b69 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -17,6 +17,7 @@ var ( type Debug struct { started int64 + proto.DebugHandler log.Log } @@ -55,7 +56,6 @@ func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.De defer stream.Close() // TODO: figure out the stream later on - // stream the logs for _, record := range records { metadata := make(map[string]string) for k, v := range record.Metadata { diff --git a/debug/log/default.go b/debug/log/default.go index b3840909..9e546cb4 100644 --- a/debug/log/default.go +++ b/debug/log/default.go @@ -32,13 +32,13 @@ func NewLog(opts ...Option) Log { } } -// Write writes log into logger +// Write writes logs into logger func (l *defaultLog) Write(v ...interface{}) { l.Buffer.Put(fmt.Sprint(v...)) golog.Print(v...) } -// Read reads logs from the logger +// Read reads logs and returns them func (l *defaultLog) Read(opts ...ReadOption) []Record { options := ReadOptions{} // initialize the read options @@ -55,8 +55,9 @@ func (l *defaultLog) Read(opts ...ReadOption) []Record { entries = l.Buffer.Get(options.Count) } - // TODO: if both Since and Count are set should we return + // TODO: if both Since and Count are set should we return? // last Count from the returned time scoped entries? + records := make([]Record, 0, len(entries)) for _, entry := range entries { record := Record{ From 9fab47ecdbe3b14a31f73f2bd0e85cf00be93f75 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 28 Nov 2019 11:36:38 +0000 Subject: [PATCH 280/344] Added DefaultLog variables --- debug/handler/debug.go | 7 ++++--- debug/log/log.go | 34 +++++++++++++++++----------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index 7dd11b69..02f853f7 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -18,12 +18,13 @@ var ( type Debug struct { started int64 proto.DebugHandler - log.Log + log log.Log } func newDebug() *Debug { return &Debug{ started: time.Now().Unix(), + log: log.DefaultLog, } } @@ -48,9 +49,9 @@ func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.De var records []log.Record since := time.Unix(0, req.Since) if !since.IsZero() { - records = d.Log.Read(log.Since(since)) + records = d.log.Read(log.Since(since)) } else { - records = d.Log.Read(log.Count(int(req.Count))) + records = d.log.Read(log.Count(int(req.Count))) } defer stream.Close() diff --git a/debug/log/log.go b/debug/log/log.go index 1c9ae240..f56fa5de 100644 --- a/debug/log/log.go +++ b/debug/log/log.go @@ -8,10 +8,10 @@ import ( ) var ( - // logger is default Logger - logger Log = NewLog() - // default log level is info - level = LevelInfo + // DefaultLog logger + DefaultLog = NewLog() + // DefaultLevel is default log level + DefaultLevel = LevelInfo // prefix for all messages prefix string ) @@ -49,38 +49,38 @@ const ( func init() { switch os.Getenv("MICRO_LOG_LEVEL") { case "trace": - level = LevelTrace + DefaultLevel = LevelTrace case "debug": - level = LevelDebug + DefaultLevel = LevelDebug case "warn": - level = LevelWarn + DefaultLevel = LevelWarn case "info": - level = LevelInfo + DefaultLevel = LevelInfo case "error": - level = LevelError + DefaultLevel = LevelError case "fatal": - level = LevelFatal + DefaultLevel = LevelFatal } } func log(v ...interface{}) { if len(prefix) > 0 { - logger.Write(fmt.Sprint(append([]interface{}{prefix, " "}, v...)...)) + DefaultLog.Write(fmt.Sprint(append([]interface{}{prefix, " "}, v...)...)) return } - logger.Write(fmt.Sprint(v...)) + DefaultLog.Write(fmt.Sprint(v...)) } func logf(format string, v ...interface{}) { if len(prefix) > 0 { format = prefix + " " + format } - logger.Write(fmt.Sprintf(format, v...)) + DefaultLog.Write(fmt.Sprintf(format, v...)) } // WithLevel logs with the level specified func WithLevel(l Level, v ...interface{}) { - if l > level { + if l > DefaultLevel { return } log(v...) @@ -88,7 +88,7 @@ func WithLevel(l Level, v ...interface{}) { // WithLevel logs with the level specified func WithLevelf(l Level, format string, v ...interface{}) { - if l > level { + if l > DefaultLevel { return } logf(format, v...) @@ -158,12 +158,12 @@ func Fatalf(format string, v ...interface{}) { // SetLevel sets the log level func SetLevel(l Level) { - level = l + DefaultLevel = l } // GetLevel returns the current level func GetLevel() Level { - return level + return DefaultLevel } // Set a prefix for the logger From 13d2a9ec7a4b620606333079d4aba06578c91f6e Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 28 Nov 2019 11:55:49 +0000 Subject: [PATCH 281/344] Register proto handler properly --- service.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/service.go b/service.go index 3058a3b2..e0c53a98 100644 --- a/service.go +++ b/service.go @@ -16,6 +16,8 @@ import ( "github.com/micro/go-micro/server" "github.com/micro/go-micro/util/log" "github.com/micro/go-micro/util/wrapper" + + pb "github.com/micro/go-micro/debug/proto" ) type service struct { @@ -141,12 +143,9 @@ func (s *service) Stop() error { func (s *service) Run() error { // register the debug handler - s.opts.Server.Handle( - s.opts.Server.NewHandler( - handler.DefaultHandler, - server.InternalHandler(true), - ), - ) + pb.RegisterDebugHandler(s.opts.Server, + handler.DefaultHandler, + server.InternalHandler(true)) // start the profiler // TODO: set as an option to the service, don't just use pprof From 612f872f76d2a5cf1785ce8a34174fd89f2f9b0a Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 28 Nov 2019 15:50:03 +0000 Subject: [PATCH 282/344] Server should not close the stream when done --- debug/handler/debug.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index 02f853f7..144be48d 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -54,8 +54,6 @@ func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.De records = d.log.Read(log.Count(int(req.Count))) } - defer stream.Close() - // TODO: figure out the stream later on for _, record := range records { metadata := make(map[string]string) From 7f1dea72f27a3c06be3240dc0cd13030f59e4f93 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 28 Nov 2019 18:08:48 +0000 Subject: [PATCH 283/344] Simplified Logs RPC. Cleaned up code. Added comments. --- debug/buffer/buffer.go | 8 +++++--- debug/handler/debug.go | 19 ++++++++++++++----- debug/log/default.go | 22 +++++++++++++++++----- debug/log/default_test.go | 10 +++++----- debug/log/options.go | 9 +++++++++ debug/service/service.go | 1 + 6 files changed, 51 insertions(+), 18 deletions(-) diff --git a/debug/buffer/buffer.go b/debug/buffer/buffer.go index 50c511d4..881e832a 100644 --- a/debug/buffer/buffer.go +++ b/debug/buffer/buffer.go @@ -6,12 +6,14 @@ import ( "time" ) +// Buffer is ring buffer type Buffer struct { size int sync.RWMutex vals []*Entry } +// Entry is ring buffer data entry type Entry struct { Value interface{} Timestamp time.Time @@ -43,14 +45,14 @@ func (b *Buffer) Put(v interface{}) { // Get returns the last n entries func (b *Buffer) Get(n int) []*Entry { + b.RLock() + defer b.RUnlock() + // reset any invalid values if n > b.size || n < 0 { n = b.size } - b.RLock() - defer b.RUnlock() - // create a delta delta := b.size - n diff --git a/debug/handler/debug.go b/debug/handler/debug.go index 144be48d..d5a9ea6c 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -1,3 +1,4 @@ +// Pacjage handler implements service debug handler package handler import ( @@ -46,15 +47,23 @@ func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.S } func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.Debug_LogsStream) error { - var records []log.Record + var options []log.ReadOption + since := time.Unix(0, req.Since) if !since.IsZero() { - records = d.log.Read(log.Since(since)) - } else { - records = d.log.Read(log.Count(int(req.Count))) + options = append(options, log.Since(since)) } - // TODO: figure out the stream later on + count := int(req.Count) + if count > 0 { + options = append(options, log.Count(count)) + } + + // get the log records + records := d.log.Read(options...) + + // TODO: figure out the stream + for _, record := range records { metadata := make(map[string]string) for k, v := range record.Metadata { diff --git a/debug/log/default.go b/debug/log/default.go index 9e546cb4..35b11fe4 100644 --- a/debug/log/default.go +++ b/debug/log/default.go @@ -50,13 +50,24 @@ func (l *defaultLog) Read(opts ...ReadOption) []Record { // if Since options ha sbeen specified we honor it if !options.Since.IsZero() { entries = l.Buffer.Since(options.Since) - } else { - // otherwie return last count entries - entries = l.Buffer.Get(options.Count) } - // TODO: if both Since and Count are set should we return? - // last Count from the returned time scoped entries? + // only if we specified valid count constraint + // do we do some serious if-else kung-fu + // if since has been given we return *count* number of + // logs since the requested timestamp; + // otherwise we retourn last count number of logs + if options.Count > 0 { + switch len(entries) > 0 { + case true: + // if we request fewer logs than what since constraint gives us + if options.Count < len(entries) { + entries = entries[0:options.Count] + } + default: + entries = l.Buffer.Get(options.Count) + } + } records := make([]Record, 0, len(entries)) for _, entry := range entries { @@ -66,5 +77,6 @@ func (l *defaultLog) Read(opts ...ReadOption) []Record { } records = append(records, record) } + return records } diff --git a/debug/log/default_test.go b/debug/log/default_test.go index 0ef6e903..e0f08a7c 100644 --- a/debug/log/default_test.go +++ b/debug/log/default_test.go @@ -9,21 +9,21 @@ func TestLogger(t *testing.T) { // set size to some value size := 100 // override the global logger - logger = NewLog(Size(size)) + DefaultLog = NewLog(Size(size)) // make sure we have the right size of the logger ring buffer - if logger.(*defaultLog).Size() != size { - t.Errorf("expected buffer size: %d, got: %d", size, logger.(*defaultLog).Size()) + if DefaultLog.(*defaultLog).Size() != size { + t.Errorf("expected buffer size: %d, got: %d", size, DefaultLog.(*defaultLog).Size()) } // Log some cruft Info("foobar") // increase the log level - level = LevelDebug + DefaultLevel = LevelDebug Debugf("foo %s", "bar") // Check if the logs are stored in the logger ring buffer expected := []string{"foobar", "foo bar"} - entries := logger.Read(Count(len(expected))) + entries := DefaultLog.Read(Count(len(expected))) for i, entry := range entries { if !reflect.DeepEqual(entry.Value, expected[i]) { t.Errorf("expected %s, got %s", expected[i], entry.Value) diff --git a/debug/log/options.go b/debug/log/options.go index 2320b71e..03dece38 100644 --- a/debug/log/options.go +++ b/debug/log/options.go @@ -31,6 +31,8 @@ type ReadOptions struct { Since time.Time // Count specifies number of logs to return Count int + // Stream requests continuous log stream + Stream bool } // ReadOption used for reading the logs @@ -49,3 +51,10 @@ func Count(c int) ReadOption { o.Count = c } } + +// Stream requests continuous log stream +func Stream(s bool) ReadOption { + return func(o *ReadOptions) { + o.Stream = s + } +} diff --git a/debug/service/service.go b/debug/service/service.go index 5089058e..aa3fd2e7 100644 --- a/debug/service/service.go +++ b/debug/service/service.go @@ -26,6 +26,7 @@ func NewDebug(name string) *Debug { } } +// Logs queries the service logs and returns a channel to read the logs from func (d *Debug) Logs(opts ...log.ReadOption) (<-chan log.Record, error) { options := log.ReadOptions{} // initialize the read options From ecdadef633b995d4c01d663e46830feb2cba5d4d Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Sat, 30 Nov 2019 12:39:29 +0000 Subject: [PATCH 284/344] Added hack support for logs streaming cruft --- debug/buffer/buffer.go | 45 +++++++++++++++++++++++++++++--- debug/handler/debug.go | 55 +++++++++++++++++++++++++++++----------- debug/log/default.go | 32 +++++++++++++++++++---- debug/log/log.go | 2 ++ debug/service/service.go | 2 ++ 5 files changed, 112 insertions(+), 24 deletions(-) diff --git a/debug/buffer/buffer.go b/debug/buffer/buffer.go index 881e832a..007293aa 100644 --- a/debug/buffer/buffer.go +++ b/debug/buffer/buffer.go @@ -4,13 +4,22 @@ package buffer import ( "sync" "time" + + "github.com/google/uuid" ) +type stream struct { + id string + entries chan *Entry + stop chan bool +} + // Buffer is ring buffer type Buffer struct { size int sync.RWMutex - vals []*Entry + vals []*Entry + streams map[string]stream } // Entry is ring buffer data entry @@ -22,7 +31,8 @@ type Entry struct { // New returns a new buffer of the given size func New(i int) *Buffer { return &Buffer{ - size: i, + size: i, + streams: make(map[string]stream), } } @@ -32,15 +42,26 @@ func (b *Buffer) Put(v interface{}) { defer b.Unlock() // append to values - b.vals = append(b.vals, &Entry{ + entry := &Entry{ Value: v, Timestamp: time.Now(), - }) + } + b.vals = append(b.vals, entry) // trim if bigger than size required if len(b.vals) > b.size { b.vals = b.vals[1:] } + + // TODO: this is fucking ugly + for _, stream := range b.streams { + select { + case <-stream.stop: + delete(b.streams, stream.id) + close(stream.entries) + case stream.entries <- entry: + } + } } // Get returns the last n entries @@ -93,6 +114,22 @@ func (b *Buffer) Since(t time.Time) []*Entry { return nil } +// Stream logs from the buffer +func (b *Buffer) Stream(stop chan bool) <-chan *Entry { + b.Lock() + defer b.Unlock() + + entries := make(chan *Entry, 128) + id := uuid.New().String() + b.streams[id] = stream{ + id: id, + entries: entries, + stop: stop, + } + + return entries +} + // Size returns the size of the ring buffer func (b *Buffer) Size() int { return b.size diff --git a/debug/handler/debug.go b/debug/handler/debug.go index d5a9ea6c..f21dd644 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -59,27 +59,52 @@ func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.De options = append(options, log.Count(count)) } + if req.Stream { + stop := make(chan bool) + defer close(stop) + + // TODO: figure out how to close log stream + // It seems when the client disconnects, + // the connection stays open until some timeout expires + // or something like that; that means the map of streams + // might end up bloating if not cleaned up properly + records := d.log.Stream(stop) + for record := range records { + if err := d.sendRecord(record, stream); err != nil { + return err + } + } + // done streaming, return + return nil + } + // get the log records records := d.log.Read(options...) - - // TODO: figure out the stream - + // send all the logs downstream for _, record := range records { - metadata := make(map[string]string) - for k, v := range record.Metadata { - metadata[k] = v - } - - recLog := &proto.Log{ - Timestamp: record.Timestamp.UnixNano(), - Value: record.Value.(string), - Metadata: metadata, - } - - if err := stream.Send(recLog); err != nil { + if err := d.sendRecord(record, stream); err != nil { return err } } return nil } + +func (d *Debug) sendRecord(record log.Record, stream proto.Debug_LogsStream) error { + metadata := make(map[string]string) + for k, v := range record.Metadata { + metadata[k] = v + } + + recLog := &proto.Log{ + Timestamp: record.Timestamp.UnixNano(), + Value: record.Value.(string), + Metadata: metadata, + } + + if err := stream.Send(recLog); err != nil { + return err + } + + return nil +} diff --git a/debug/log/default.go b/debug/log/default.go index 35b11fe4..d715e0c6 100644 --- a/debug/log/default.go +++ b/debug/log/default.go @@ -34,8 +34,8 @@ func NewLog(opts ...Option) Log { // Write writes logs into logger func (l *defaultLog) Write(v ...interface{}) { - l.Buffer.Put(fmt.Sprint(v...)) golog.Print(v...) + l.Buffer.Put(fmt.Sprint(v...)) } // Read reads logs and returns them @@ -53,10 +53,10 @@ func (l *defaultLog) Read(opts ...ReadOption) []Record { } // only if we specified valid count constraint - // do we do some serious if-else kung-fu - // if since has been given we return *count* number of - // logs since the requested timestamp; - // otherwise we retourn last count number of logs + // do we end up doing some serious if-else kung-fu + // if since constraint has been provided + // we return *count* number of logs since the given timestamp; + // otherwise we return last count number of logs if options.Count > 0 { switch len(entries) > 0 { case true: @@ -80,3 +80,25 @@ func (l *defaultLog) Read(opts ...ReadOption) []Record { return records } + +// Stream returns channel for reading log records +func (l *defaultLog) Stream(stop chan bool) <-chan Record { + // get stream channel from ring buffer + stream := l.Buffer.Stream(stop) + records := make(chan Record) + + fmt.Println("requested log stream") + + // stream the log records + go func() { + for entry := range stream { + records <- Record{ + Timestamp: entry.Timestamp, + Value: entry.Value, + Metadata: make(map[string]string), + } + } + }() + + return records +} diff --git a/debug/log/log.go b/debug/log/log.go index f56fa5de..c70ce00c 100644 --- a/debug/log/log.go +++ b/debug/log/log.go @@ -22,6 +22,8 @@ type Log interface { Read(...ReadOption) []Record // Write writes logs to logger Write(...interface{}) + // Stream logs + Stream(chan bool) <-chan Record } // Record is log record entry diff --git a/debug/service/service.go b/debug/service/service.go index aa3fd2e7..9fda358c 100644 --- a/debug/service/service.go +++ b/debug/service/service.go @@ -43,6 +43,8 @@ func (d *Debug) Logs(opts ...log.ReadOption) (<-chan log.Record, error) { req.Count = int64(options.Count) } + req.Stream = options.Stream + // get the log stream stream, err := d.dbg.Logs(context.Background(), req) if err != nil { From 4613a820ca6341ce151b15fa394eebf230c10318 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Sun, 1 Dec 2019 13:15:10 +0000 Subject: [PATCH 285/344] Small refactoring og logs * log.Write now accepts log.Record * we stream last 10 records first * regenerate proto because of the above --- debug/handler/debug.go | 14 ++--- debug/log/default.go | 22 +++++-- debug/log/log.go | 12 ++-- debug/proto/debug.pb.go | 104 +++++++++++++++++----------------- debug/proto/debug.pb.micro.go | 10 ++-- debug/proto/debug.proto | 22 +++---- debug/service/service.go | 2 +- 7 files changed, 98 insertions(+), 88 deletions(-) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index f21dd644..0e077c7f 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -49,7 +49,7 @@ func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.S func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.Debug_LogsStream) error { var options []log.ReadOption - since := time.Unix(0, req.Since) + since := time.Unix(req.Since, 0) if !since.IsZero() { options = append(options, log.Since(since)) } @@ -63,11 +63,11 @@ func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.De stop := make(chan bool) defer close(stop) - // TODO: figure out how to close log stream - // It seems when the client disconnects, + // TODO: we need to figure out how to close ithe log stream + // It seems like when a client disconnects, // the connection stays open until some timeout expires // or something like that; that means the map of streams - // might end up bloating if not cleaned up properly + // might end up leaking memory if not cleaned up properly records := d.log.Stream(stop) for record := range records { if err := d.sendRecord(record, stream); err != nil { @@ -96,13 +96,13 @@ func (d *Debug) sendRecord(record log.Record, stream proto.Debug_LogsStream) err metadata[k] = v } - recLog := &proto.Log{ - Timestamp: record.Timestamp.UnixNano(), + pbRecord := &proto.Record{ + Timestamp: record.Timestamp.Unix(), Value: record.Value.(string), Metadata: metadata, } - if err := stream.Send(recLog); err != nil { + if err := stream.Send(pbRecord); err != nil { return err } diff --git a/debug/log/default.go b/debug/log/default.go index d715e0c6..6f7bddab 100644 --- a/debug/log/default.go +++ b/debug/log/default.go @@ -33,9 +33,9 @@ func NewLog(opts ...Option) Log { } // Write writes logs into logger -func (l *defaultLog) Write(v ...interface{}) { - golog.Print(v...) - l.Buffer.Put(fmt.Sprint(v...)) +func (l *defaultLog) Write(r Record) { + golog.Print(r.Value) + l.Buffer.Put(fmt.Sprint(r.Value)) } // Read reads logs and returns them @@ -85,12 +85,22 @@ func (l *defaultLog) Read(opts ...ReadOption) []Record { func (l *defaultLog) Stream(stop chan bool) <-chan Record { // get stream channel from ring buffer stream := l.Buffer.Stream(stop) - records := make(chan Record) - - fmt.Println("requested log stream") + // make a buffered channel + records := make(chan Record, 128) + // get last 10 records + last10 := l.Buffer.Get(10) // stream the log records go func() { + // first send last 10 records + for _, entry := range last10 { + records <- Record{ + Timestamp: entry.Timestamp, + Value: entry.Value, + Metadata: make(map[string]string), + } + } + // now stream continuously for entry := range stream { records <- Record{ Timestamp: entry.Timestamp, diff --git a/debug/log/log.go b/debug/log/log.go index c70ce00c..42a8f558 100644 --- a/debug/log/log.go +++ b/debug/log/log.go @@ -20,9 +20,9 @@ var ( type Log interface { // Read reads log entries from the logger Read(...ReadOption) []Record - // Write writes logs to logger - Write(...interface{}) - // Stream logs + // Write writes records to log + Write(Record) + // Stream log records Stream(chan bool) <-chan Record } @@ -67,17 +67,17 @@ func init() { func log(v ...interface{}) { if len(prefix) > 0 { - DefaultLog.Write(fmt.Sprint(append([]interface{}{prefix, " "}, v...)...)) + DefaultLog.Write(Record{Value: fmt.Sprint(append([]interface{}{prefix, " "}, v...)...)}) return } - DefaultLog.Write(fmt.Sprint(v...)) + DefaultLog.Write(Record{Value: fmt.Sprint(v...)}) } func logf(format string, v ...interface{}) { if len(prefix) > 0 { format = prefix + " " + format } - DefaultLog.Write(fmt.Sprintf(format, v...)) + DefaultLog.Write(Record{Value: fmt.Sprintf(format, v...)}) } // WithLevel logs with the level specified diff --git a/debug/proto/debug.pb.go b/debug/proto/debug.pb.go index 423e98cc..a94a55ce 100644 --- a/debug/proto/debug.pb.go +++ b/debug/proto/debug.pb.go @@ -198,15 +198,15 @@ func (m *StatsResponse) GetGc() uint64 { return 0 } -// LogRequest queries service for logs +// LogRequest requests service logs type LogRequest struct { - // count is the count of events + // count of records to request Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` // relative time in seconds // before the current time // from which to show logs Since int64 `protobuf:"varint,2,opt,name=since,proto3" json:"since,omitempty"` - // stream logs continuously + // stream records continuously Stream bool `protobuf:"varint,3,opt,name=stream,proto3" json:"stream,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -259,59 +259,59 @@ func (m *LogRequest) GetStream() bool { return false } -// Log is service log record -type Log struct { - // timestamp of log event +// Record is service log record +type Record struct { + // timestamp of log record Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - // log value + // record value Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - // metadata + // record metadata Metadata map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } -func (m *Log) Reset() { *m = Log{} } -func (m *Log) String() string { return proto.CompactTextString(m) } -func (*Log) ProtoMessage() {} -func (*Log) Descriptor() ([]byte, []int) { +func (m *Record) Reset() { *m = Record{} } +func (m *Record) String() string { return proto.CompactTextString(m) } +func (*Record) ProtoMessage() {} +func (*Record) Descriptor() ([]byte, []int) { return fileDescriptor_8d9d361be58531fb, []int{5} } -func (m *Log) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Log.Unmarshal(m, b) +func (m *Record) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Record.Unmarshal(m, b) } -func (m *Log) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Log.Marshal(b, m, deterministic) +func (m *Record) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Record.Marshal(b, m, deterministic) } -func (m *Log) XXX_Merge(src proto.Message) { - xxx_messageInfo_Log.Merge(m, src) +func (m *Record) XXX_Merge(src proto.Message) { + xxx_messageInfo_Record.Merge(m, src) } -func (m *Log) XXX_Size() int { - return xxx_messageInfo_Log.Size(m) +func (m *Record) XXX_Size() int { + return xxx_messageInfo_Record.Size(m) } -func (m *Log) XXX_DiscardUnknown() { - xxx_messageInfo_Log.DiscardUnknown(m) +func (m *Record) XXX_DiscardUnknown() { + xxx_messageInfo_Record.DiscardUnknown(m) } -var xxx_messageInfo_Log proto.InternalMessageInfo +var xxx_messageInfo_Record proto.InternalMessageInfo -func (m *Log) GetTimestamp() int64 { +func (m *Record) GetTimestamp() int64 { if m != nil { return m.Timestamp } return 0 } -func (m *Log) GetValue() string { +func (m *Record) GetValue() string { if m != nil { return m.Value } return "" } -func (m *Log) GetMetadata() map[string]string { +func (m *Record) GetMetadata() map[string]string { if m != nil { return m.Metadata } @@ -324,35 +324,35 @@ func init() { proto.RegisterType((*StatsRequest)(nil), "StatsRequest") proto.RegisterType((*StatsResponse)(nil), "StatsResponse") proto.RegisterType((*LogRequest)(nil), "LogRequest") - proto.RegisterType((*Log)(nil), "Log") - proto.RegisterMapType((map[string]string)(nil), "Log.MetadataEntry") + proto.RegisterType((*Record)(nil), "Record") + proto.RegisterMapType((map[string]string)(nil), "Record.MetadataEntry") } func init() { proto.RegisterFile("debug.proto", fileDescriptor_8d9d361be58531fb) } var fileDescriptor_8d9d361be58531fb = []byte{ - // 360 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0x5f, 0x6b, 0xdb, 0x30, - 0x14, 0xc5, 0xe3, 0x7f, 0x59, 0x72, 0x33, 0x3b, 0x43, 0x8c, 0x61, 0xcc, 0x06, 0x41, 0x4f, 0x86, - 0x81, 0x18, 0xd9, 0xcb, 0xd8, 0x5e, 0x57, 0xe8, 0x83, 0x0b, 0x45, 0xfd, 0x04, 0x8a, 0x2d, 0x9c, - 0xd0, 0xd8, 0x72, 0xad, 0xeb, 0x42, 0x1e, 0xfa, 0xd4, 0xef, 0xd2, 0xcf, 0x59, 0x64, 0x29, 0x4d, - 0x0d, 0x7d, 0xf3, 0xef, 0xc8, 0xf7, 0x1c, 0xf9, 0x1e, 0xc3, 0xaa, 0x92, 0xbb, 0xa1, 0x66, 0x5d, - 0xaf, 0x50, 0xd1, 0x35, 0xc4, 0xd7, 0x52, 0x1c, 0x71, 0xcf, 0xe5, 0xc3, 0x20, 0x35, 0xd2, 0x1c, - 0x92, 0xb3, 0xa0, 0x3b, 0xd5, 0x6a, 0x49, 0xbe, 0xc1, 0x5c, 0xa3, 0xc0, 0x41, 0xa7, 0xde, 0xc6, - 0xcb, 0x97, 0xdc, 0x11, 0x4d, 0xe0, 0xf3, 0x1d, 0x0a, 0xd4, 0xe7, 0xc9, 0x67, 0x0f, 0x62, 0x27, - 0xb8, 0xc9, 0x14, 0x3e, 0x69, 0x14, 0x3d, 0xca, 0x6a, 0x1c, 0x0d, 0xf9, 0x19, 0x8d, 0xe7, 0xd0, - 0xe1, 0xa1, 0x91, 0xa9, 0x3f, 0x1e, 0x38, 0x32, 0x7a, 0x23, 0x1b, 0xd5, 0x9f, 0xd2, 0xc0, 0xea, - 0x96, 0x8c, 0x13, 0xee, 0x7b, 0x29, 0x2a, 0x9d, 0x86, 0xd6, 0xc9, 0x21, 0x49, 0xc0, 0xaf, 0xcb, - 0x34, 0x1a, 0x45, 0xbf, 0x2e, 0xe9, 0x2d, 0x40, 0xa1, 0x6a, 0x77, 0x27, 0xf2, 0x15, 0xa2, 0x52, - 0x0d, 0x2d, 0x8e, 0xf9, 0x01, 0xb7, 0x60, 0x54, 0x7d, 0x68, 0x4b, 0x1b, 0x1e, 0x70, 0x0b, 0xf6, - 0x3b, 0x7b, 0x29, 0x9a, 0x31, 0x7b, 0xc1, 0x1d, 0xd1, 0x17, 0x0f, 0x82, 0x42, 0xd5, 0xe4, 0x3b, - 0x2c, 0xcd, 0x1d, 0x35, 0x8a, 0xa6, 0x73, 0x7e, 0x17, 0xc1, 0x78, 0x3e, 0x8a, 0xe3, 0x60, 0x3d, - 0x97, 0xdc, 0x02, 0x61, 0xb0, 0x68, 0x24, 0x8a, 0x4a, 0xa0, 0x48, 0x83, 0x4d, 0x90, 0xaf, 0xb6, - 0x84, 0x15, 0xaa, 0x66, 0x37, 0x4e, 0xbc, 0x6a, 0xb1, 0x3f, 0xf1, 0xb7, 0x77, 0xb2, 0x7f, 0x10, - 0x4f, 0x8e, 0xc8, 0x17, 0x08, 0xee, 0xe5, 0xc9, 0x6d, 0xde, 0x3c, 0x7e, 0x1c, 0xf4, 0xd7, 0xff, - 0xe3, 0x6d, 0x9f, 0x20, 0xfa, 0x6f, 0xaa, 0x25, 0x3f, 0x61, 0x6e, 0x3b, 0x24, 0x09, 0x9b, 0xb4, - 0x9b, 0xad, 0xd9, 0xb4, 0x5c, 0x3a, 0x23, 0x39, 0x44, 0x63, 0x6b, 0x24, 0x66, 0xef, 0xeb, 0xcc, - 0x12, 0x36, 0x29, 0x93, 0xce, 0xc8, 0x0f, 0x08, 0x0b, 0x55, 0x6b, 0xb2, 0x62, 0x97, 0x0d, 0x67, - 0xa1, 0x01, 0x3a, 0xfb, 0xe5, 0xed, 0xe6, 0xe3, 0x1f, 0xf5, 0xfb, 0x35, 0x00, 0x00, 0xff, 0xff, - 0x95, 0x24, 0xad, 0xbc, 0x60, 0x02, 0x00, 0x00, + // 364 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0x41, 0x6b, 0xdb, 0x30, + 0x1c, 0xc5, 0x63, 0x3b, 0x76, 0x92, 0x7f, 0x66, 0x67, 0x88, 0x6d, 0x18, 0xb3, 0x43, 0xd0, 0xc9, + 0x30, 0x10, 0x5b, 0x76, 0x19, 0xdb, 0x75, 0x85, 0x1e, 0x52, 0x28, 0xea, 0x27, 0x50, 0x6c, 0xe1, + 0x84, 0xc6, 0x96, 0x6b, 0xfd, 0x5d, 0xc8, 0xad, 0xd0, 0xaf, 0xd3, 0x0f, 0x59, 0x64, 0x29, 0x4d, + 0x0d, 0xbd, 0xf9, 0xf7, 0xe4, 0xff, 0x7b, 0x92, 0x9e, 0x60, 0x59, 0xca, 0x5d, 0x5f, 0xb1, 0xb6, + 0x53, 0xa8, 0xe8, 0x0a, 0xe2, 0x6b, 0x29, 0x8e, 0xb8, 0xe7, 0xf2, 0xa1, 0x97, 0x1a, 0x69, 0x0e, + 0xc9, 0x59, 0xd0, 0xad, 0x6a, 0xb4, 0x24, 0xdf, 0x20, 0xd2, 0x28, 0xb0, 0xd7, 0xa9, 0xb7, 0xf6, + 0xf2, 0x05, 0x77, 0x44, 0x13, 0xf8, 0x74, 0x87, 0x02, 0xf5, 0x79, 0xf2, 0xd9, 0x83, 0xd8, 0x09, + 0x6e, 0x32, 0x85, 0x99, 0x46, 0xd1, 0xa1, 0x2c, 0x87, 0xd1, 0x29, 0x3f, 0xa3, 0xf1, 0xec, 0x5b, + 0x3c, 0xd4, 0x32, 0xf5, 0x87, 0x05, 0x47, 0x46, 0xaf, 0x65, 0xad, 0xba, 0x53, 0x1a, 0x58, 0xdd, + 0x92, 0x71, 0xc2, 0x7d, 0x27, 0x45, 0xa9, 0xd3, 0xa9, 0x75, 0x72, 0x48, 0x12, 0xf0, 0xab, 0x22, + 0x0d, 0x07, 0xd1, 0xaf, 0x0a, 0x7a, 0x0b, 0xb0, 0x55, 0x95, 0xdb, 0x13, 0xf9, 0x02, 0x61, 0xa1, + 0xfa, 0x06, 0x87, 0xfc, 0x80, 0x5b, 0x30, 0xaa, 0x3e, 0x34, 0x85, 0x0d, 0x0f, 0xb8, 0x05, 0x7b, + 0xce, 0x4e, 0x8a, 0x7a, 0xc8, 0x9e, 0x73, 0x47, 0xf4, 0xc5, 0x83, 0x88, 0xcb, 0x42, 0x75, 0x25, + 0xf9, 0x0e, 0x0b, 0xb3, 0x4d, 0x8d, 0xa2, 0x6e, 0x9d, 0xe5, 0x45, 0x30, 0xb6, 0x8f, 0xe2, 0xd8, + 0x5b, 0xdb, 0x05, 0xb7, 0x40, 0x7e, 0xc1, 0xbc, 0x96, 0x28, 0x4a, 0x81, 0x22, 0x0d, 0xd6, 0x41, + 0xbe, 0xdc, 0x7c, 0x65, 0xd6, 0x8e, 0xdd, 0x38, 0xfd, 0xaa, 0xc1, 0xee, 0xc4, 0xdf, 0x7e, 0xcb, + 0xfe, 0x41, 0x3c, 0x5a, 0x22, 0x9f, 0x21, 0xb8, 0x97, 0x27, 0x77, 0xff, 0xe6, 0xf3, 0xe3, 0xac, + 0xbf, 0xfe, 0x1f, 0x6f, 0xf3, 0xe4, 0x41, 0xf8, 0xdf, 0x34, 0x4c, 0x7e, 0x40, 0x64, 0xab, 0x24, + 0x09, 0x1b, 0x95, 0x9c, 0xad, 0xd8, 0xb8, 0x63, 0x3a, 0x21, 0x39, 0x84, 0x43, 0x79, 0x24, 0x66, + 0xef, 0x5b, 0xcd, 0x12, 0x36, 0xea, 0x94, 0x4e, 0xc8, 0x1a, 0xa6, 0x5b, 0x55, 0x69, 0xb2, 0x64, + 0x97, 0x8b, 0xce, 0x66, 0xee, 0x4c, 0x74, 0xf2, 0xd3, 0xdb, 0x45, 0xc3, 0xdb, 0xfa, 0xfd, 0x1a, + 0x00, 0x00, 0xff, 0xff, 0xea, 0x2d, 0x15, 0xdb, 0x6a, 0x02, 0x00, 0x00, } diff --git a/debug/proto/debug.pb.micro.go b/debug/proto/debug.pb.micro.go index 6f89d5eb..3381c2af 100644 --- a/debug/proto/debug.pb.micro.go +++ b/debug/proto/debug.pb.micro.go @@ -93,7 +93,7 @@ type Debug_LogsService interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error - Recv() (*Log, error) + Recv() (*Record, error) } type debugServiceLogs struct { @@ -112,8 +112,8 @@ func (x *debugServiceLogs) RecvMsg(m interface{}) error { return x.stream.Recv(m) } -func (x *debugServiceLogs) Recv() (*Log, error) { - m := new(Log) +func (x *debugServiceLogs) Recv() (*Record, error) { + m := new(Record) err := x.stream.Recv(m) if err != nil { return nil, err @@ -166,7 +166,7 @@ type Debug_LogsStream interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error - Send(*Log) error + Send(*Record) error } type debugLogsStream struct { @@ -185,6 +185,6 @@ func (x *debugLogsStream) RecvMsg(m interface{}) error { return x.stream.Recv(m) } -func (x *debugLogsStream) Send(m *Log) error { +func (x *debugLogsStream) Send(m *Record) error { return x.stream.Send(m) } diff --git a/debug/proto/debug.proto b/debug/proto/debug.proto index 830423b3..a666068a 100644 --- a/debug/proto/debug.proto +++ b/debug/proto/debug.proto @@ -1,9 +1,9 @@ syntax = "proto3"; service Debug { - rpc Health(HealthRequest) returns (HealthResponse) {}; - rpc Stats(StatsRequest) returns (StatsResponse) {}; - rpc Logs(LogRequest) returns (stream Log) {}; + rpc Health(HealthRequest) returns (HealthResponse) {}; + rpc Stats(StatsRequest) returns (StatsResponse) {}; + rpc Logs(LogRequest) returns (stream Record) {}; } message HealthRequest {} @@ -28,24 +28,24 @@ message StatsResponse { uint64 gc = 5; } -// LogRequest queries service for logs +// LogRequest requests service logs message LogRequest { - // count is the count of events + // count of records to request int64 count = 1; // relative time in seconds // before the current time // from which to show logs int64 since = 2; - // stream logs continuously + // stream records continuously bool stream = 3; } -// Log is service log record -message Log { - // timestamp of log event +// Record is service log record +message Record { + // timestamp of log record int64 timestamp = 1; - // log value + // record value string value = 2; - // metadata + // record metadata map metadata = 3; } diff --git a/debug/service/service.go b/debug/service/service.go index 9fda358c..2a0ea006 100644 --- a/debug/service/service.go +++ b/debug/service/service.go @@ -74,7 +74,7 @@ func (d *Debug) streamLogs(logChan chan log.Record, stream pb.Debug_LogsService) } record := log.Record{ - Timestamp: time.Unix(0, resp.Timestamp), + Timestamp: time.Unix(resp.Timestamp, 0), Value: resp.Value, Metadata: metadata, } From b2ecd93404c7c563c0935b2945b88b46d7cf5a81 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Sun, 1 Dec 2019 18:33:08 +0000 Subject: [PATCH 286/344] Time resolution change to be in line with debug/handler.Handler --- debug/service/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debug/service/service.go b/debug/service/service.go index 2a0ea006..a30d2836 100644 --- a/debug/service/service.go +++ b/debug/service/service.go @@ -36,7 +36,7 @@ func (d *Debug) Logs(opts ...log.ReadOption) (<-chan log.Record, error) { req := &pb.LogRequest{} if !options.Since.IsZero() { - req.Since = options.Since.UnixNano() + req.Since = options.Since.Unix() } if options.Count > 0 { From c840cee404cfd25c67bdd3e10c084036834554ec Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 1 Dec 2019 19:36:16 +0000 Subject: [PATCH 287/344] A variety of fixes to try combat the multicast issue --- network/default.go | 10 +++++----- tunnel/default.go | 17 +++++++++++------ tunnel/listener.go | 2 +- tunnel/session.go | 5 ----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/network/default.go b/network/default.go index 5d4a9711..0b19a848 100644 --- a/network/default.go +++ b/network/default.go @@ -939,17 +939,17 @@ func (n *network) Connect() error { log.Debugf("Network failed to resolve nodes: %v", err) } - // initialize the tunnel to resolved nodes - n.tunnel.Init( - tunnel.Nodes(nodes...), - ) - // connect network tunnel if err := n.tunnel.Connect(); err != nil { n.Unlock() return err } + // initialize the tunnel to resolved nodes + n.tunnel.Init( + tunnel.Nodes(nodes...), + ) + // return if already connected if n.connected { // unlock first diff --git a/tunnel/default.go b/tunnel/default.go index fc24ee9d..1a3e3c35 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -502,22 +502,26 @@ func (t *tun) listen(link *link) { // TODO: handle the close message // maybe report io.EOF or kill the link - // close the link entirely + // if there is no channel then we close the link + // as its a signal from the other side to close the connection if len(channel) == 0 { log.Debugf("Tunnel link %s received close message", link.Remote()) return } - // the entire listener was closed so remove it from the mapping + // the entire listener was closed by the remote side so we need to + // remove the channel mapping for it. should we also close sessions? if sessionId == "listener" { link.delChannel(channel) continue } + // assuming there's a channel and session // try get the dialing socket - _, exists := t.getSession(channel, sessionId) - if exists { - // delete and continue + s, exists := t.getSession(channel, sessionId) + if exists && s.mode == Unicast && !loopback { + // only delete this if its unicast + // but not if its a loopback conn t.delSession(channel, sessionId) continue } @@ -673,6 +677,7 @@ func (t *tun) listen(link *link) { typ: mtype, channel: channel, session: sessionId, + mode: s.mode, data: tmsg, link: link.id, loopback: loopback, @@ -703,7 +708,7 @@ func (t *tun) discover(link *link) { "Micro-Tunnel-Id": t.id, }, }); err != nil { - log.Debugf("Tunnel failed to send discover to link %s: %v", link.id, err) + log.Debugf("Tunnel failed to send discover to link %s: %v", link.Remote(), err) } case <-link.closed: return diff --git a/tunnel/listener.go b/tunnel/listener.go index 62883777..7ba6074e 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -88,7 +88,7 @@ func (t *tunListener) process() { // the link the message was received on link: m.link, // set the connection mode - mode: t.session.mode, + mode: m.mode, // close chan closed: make(chan bool), // recv called by the acceptor diff --git a/tunnel/session.go b/tunnel/session.go index a0dbef93..4b8721aa 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -413,11 +413,6 @@ func (s *session) Close() error { default: close(s.closed) - // don't broadcast the close for multicast - if s.mode != Unicast { - return nil - } - // append to backlog msg := s.newMessage("close") // no error response on close From 93d66afe8c22513d6915569ae9b2ee1718326381 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 1 Dec 2019 19:43:36 +0000 Subject: [PATCH 288/344] fix that broken logic --- tunnel/default.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index 1a3e3c35..16ab2e59 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -519,11 +519,13 @@ func (t *tun) listen(link *link) { // assuming there's a channel and session // try get the dialing socket s, exists := t.getSession(channel, sessionId) - if exists && s.mode == Unicast && !loopback { - // only delete this if its unicast - // but not if its a loopback conn - t.delSession(channel, sessionId) - continue + if exists && !loopback { + if s.mode == Unicast { + // only delete this if its unicast + // but not if its a loopback conn + t.delSession(channel, sessionId) + continue + } } // otherwise its a session mapping of sorts case "keepalive": From 3356b83f2499ddad5592c51434035652aadaff16 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 1 Dec 2019 21:04:09 +0000 Subject: [PATCH 289/344] register debug handler --- util/mux/mux.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/util/mux/mux.go b/util/mux/mux.go index 741dafcd..ecc3c680 100644 --- a/util/mux/mux.go +++ b/util/mux/mux.go @@ -5,6 +5,7 @@ import ( "context" "sync" + proto "github.com/micro/go-micro/debug/proto" "github.com/micro/go-micro/debug/handler" "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/server" @@ -39,11 +40,10 @@ func (s *Server) ServeRequest(ctx context.Context, req server.Request, rsp serve func New(name string, p proxy.Proxy) *Server { // only register this once once.Do(func() { - server.DefaultRouter.Handle( - server.DefaultRouter.NewHandler( - handler.DefaultHandler, - server.InternalHandler(true), - ), + proto.RegisterDebugHandler( + server.DefaultServer, + handler.DefaultHandler, + server.InternalHandler(true), ) }) From 91e9c0cb622e5e4a6118cb97059915cbef953f38 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 2 Dec 2019 14:55:35 +0000 Subject: [PATCH 290/344] ultra hacks to make debug handler work in proxy --- debug/handler/debug.go | 11 ++++++++--- service.go | 11 ++++++----- util/mux/mux.go | 10 +++++----- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/debug/handler/debug.go b/debug/handler/debug.go index 0e077c7f..002dccba 100644 --- a/debug/handler/debug.go +++ b/debug/handler/debug.go @@ -7,8 +7,8 @@ import ( "time" "github.com/micro/go-micro/debug/log" - proto "github.com/micro/go-micro/debug/proto" + "github.com/micro/go-micro/server" ) var ( @@ -46,7 +46,12 @@ func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.S return nil } -func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.Debug_LogsStream) error { +func (d *Debug) Logs(ctx context.Context, stream server.Stream) error { + req := new(proto.LogRequest) + if err := stream.Recv(req); err != nil { + return err + } + var options []log.ReadOption since := time.Unix(req.Since, 0) @@ -90,7 +95,7 @@ func (d *Debug) Logs(ctx context.Context, req *proto.LogRequest, stream proto.De return nil } -func (d *Debug) sendRecord(record log.Record, stream proto.Debug_LogsStream) error { +func (d *Debug) sendRecord(record log.Record, stream server.Stream) error { metadata := make(map[string]string) for k, v := range record.Metadata { metadata[k] = v diff --git a/service.go b/service.go index e0c53a98..3058a3b2 100644 --- a/service.go +++ b/service.go @@ -16,8 +16,6 @@ import ( "github.com/micro/go-micro/server" "github.com/micro/go-micro/util/log" "github.com/micro/go-micro/util/wrapper" - - pb "github.com/micro/go-micro/debug/proto" ) type service struct { @@ -143,9 +141,12 @@ func (s *service) Stop() error { func (s *service) Run() error { // register the debug handler - pb.RegisterDebugHandler(s.opts.Server, - handler.DefaultHandler, - server.InternalHandler(true)) + s.opts.Server.Handle( + s.opts.Server.NewHandler( + handler.DefaultHandler, + server.InternalHandler(true), + ), + ) // start the profiler // TODO: set as an option to the service, don't just use pprof diff --git a/util/mux/mux.go b/util/mux/mux.go index ecc3c680..741dafcd 100644 --- a/util/mux/mux.go +++ b/util/mux/mux.go @@ -5,7 +5,6 @@ import ( "context" "sync" - proto "github.com/micro/go-micro/debug/proto" "github.com/micro/go-micro/debug/handler" "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/server" @@ -40,10 +39,11 @@ func (s *Server) ServeRequest(ctx context.Context, req server.Request, rsp serve func New(name string, p proxy.Proxy) *Server { // only register this once once.Do(func() { - proto.RegisterDebugHandler( - server.DefaultServer, - handler.DefaultHandler, - server.InternalHandler(true), + server.DefaultRouter.Handle( + server.DefaultRouter.NewHandler( + handler.DefaultHandler, + server.InternalHandler(true), + ), ) }) From da04aa8ae8f255a1faafe97ab7842c727435d241 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 2 Dec 2019 17:36:20 +0000 Subject: [PATCH 291/344] Switch to AdvertiseLocal by default --- router/default_test.go | 2 +- router/options.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/router/default_test.go b/router/default_test.go index 2d12a14f..d3edf67d 100644 --- a/router/default_test.go +++ b/router/default_test.go @@ -63,7 +63,7 @@ func TestRouterAdvertise(t *testing.T) { Gateway: "dest.gw", Network: "dest.network", Router: "src.router", - Link: "det.link", + Link: "local", Metric: 10, } diff --git a/router/options.go b/router/options.go index 31d82ea8..0fa67b4f 100644 --- a/router/options.go +++ b/router/options.go @@ -80,6 +80,6 @@ func DefaultOptions() Options { Address: DefaultAddress, Network: DefaultNetwork, Registry: registry.DefaultRegistry, - Advertise: AdvertiseBest, + Advertise: AdvertiseLocal, } } From 5f04fd58ab7cce48ca772c659f8b7623bda978de Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 2 Dec 2019 18:48:19 +0000 Subject: [PATCH 292/344] optimizations to connect fast --- network/default.go | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/network/default.go b/network/default.go index 0b19a848..b9dfe13f 100644 --- a/network/default.go +++ b/network/default.go @@ -476,6 +476,24 @@ func (n *network) processNetChan(listener tunnel.Listener) { n.Lock() delete(n.peerLinks, pbNetClose.Node.Address) n.Unlock() + case "solicit": + // received a peer solicit message + pbRtrSolicit := &pbRtr.Solicit{} + if err := proto.Unmarshal(m.msg.Body, pbRtrSolicit); err != nil { + log.Debugf("Network fail to unmarshal solicit message: %v", err) + continue + } + log.Debugf("Network received peer solicit message from: %s", pbRtrSolicit.Id) + // ignore solicitation when requested by you + if pbRtrSolicit.Id == n.options.Id { + continue + } + // get node peers down to MaxDepth encoded in protobuf + msg := PeersToProto(n.node, MaxDepth) + // advertise yourself to the network + if err := n.sendMsg("peer", msg, NetworkChannel); err != nil { + log.Debugf("Network failed to advertise peers: %v", err) + } } case <-n.closed: return @@ -767,6 +785,13 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { // loookup advertising node in our peer topology advertNode := n.node.GetPeerNode(pbRtrAdvert.Id) if advertNode == nil { + msg := &pbRtr.Solicit{ + Id: pbRtrAdvert.Id, + } + // go solicit the peer + if err := n.sendMsg("solicit", msg, NetworkChannel); err != nil { + log.Debugf("Network failed to send solicit message: %s", err) + } // if we can't find the node in our topology (MaxDepth) we skipp prcessing adverts log.Debugf("Network skipping advert message from unknown peer: %s", pbRtrAdvert.Id) continue @@ -1020,8 +1045,23 @@ func (n *network) Connect() error { } n.Unlock() - // send the connect message - n.sendConnect() + // send connect after there's a link established + go func() { + // wait for 30 ticks e.g 30 seconds + for i := 0; i < 30; i++ { + // get the current links + links := n.tunnel.Links() + + // if there are no links wait until we have one + if len(links) == 0 { + time.Sleep(time.Second) + continue + } + + // send the connect message + n.sendConnect() + } + }() // go resolving network nodes go n.resolve() From 90f9b0d0c9c7ac9c2872fb8ed9c3e761353b9b31 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 Dec 2019 01:35:59 +0300 Subject: [PATCH 293/344] initialize client options context if not provided Signed-off-by: Vasiliy Tolstov --- client/options.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/options.go b/client/options.go index 9f363d74..5a7654a4 100644 --- a/client/options.go +++ b/client/options.go @@ -125,6 +125,10 @@ func newOptions(options ...Option) Options { opts.Transport = transport.DefaultTransport } + if opts.Context == nil { + opts.Context = context.Background() + } + return opts } From b8e96f45d48d4fcaf8fc00638834db69eb2a2802 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 Dec 2019 01:36:14 +0300 Subject: [PATCH 294/344] add recovery in case of panics Signed-off-by: Vasiliy Tolstov --- server/rpc_router.go | 35 ++++++++++++++++++++++++----------- transport/grpc/handler.go | 7 ++++++- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/server/rpc_router.go b/server/rpc_router.go index fddce6fd..19f672f4 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -12,12 +12,14 @@ import ( "fmt" "io" "reflect" + "runtime/debug" "strings" "sync" "unicode" "unicode/utf8" "github.com/micro/go-micro/codec" + merrors "github.com/micro/go-micro/errors" "github.com/micro/go-micro/util/log" ) @@ -505,6 +507,17 @@ func (router *router) Subscribe(s Subscriber) error { } func (router *router) ProcessMessage(ctx context.Context, msg Message) error { + var err error + + defer func() { + // recover any panics + if r := recover(); r != nil { + log.Log("panic recovered: ", r) + log.Log(string(debug.Stack())) + err = merrors.InternalServerError("go.micro.server", "panic recovered: %v", r) + } + }() + router.su.RLock() // get the subscribers by topic @@ -517,7 +530,7 @@ func (router *router) ProcessMessage(ctx context.Context, msg Message) error { // unlock since we only need to get the subs router.su.RUnlock() - var results []string + var errResults []string // we may have multiple subscribers for the topic for _, sub := range subs { @@ -557,12 +570,12 @@ func (router *router) ProcessMessage(ctx context.Context, msg Message) error { cc := msg.Codec() // read the header. mostly a noop - if err := cc.ReadHeader(&codec.Message{}, codec.Event); err != nil { + if err = cc.ReadHeader(&codec.Message{}, codec.Event); err != nil { return err } // read the body into the handler request value - if err := cc.ReadBody(req.Interface()); err != nil { + if err = cc.ReadBody(req.Interface()); err != nil { return err } @@ -581,10 +594,10 @@ func (router *router) ProcessMessage(ctx context.Context, msg Message) error { // execute the actuall call of the handler returnValues := handler.method.Call(vals) - if err := returnValues[0].Interface(); err != nil { - return err.(error) + if rerr := returnValues[0].Interface(); rerr != nil { + err = rerr.(error) } - return nil + return err } // wrap with subscriber wrappers @@ -603,16 +616,16 @@ func (router *router) ProcessMessage(ctx context.Context, msg Message) error { } // execute the message handler - if err := fn(ctx, rpcMsg); err != nil { - results = append(results, err.Error()) + if err = fn(ctx, rpcMsg); err != nil { + errResults = append(errResults, err.Error()) } } } // if no errors just return - if len(results) == 0 { - return nil + if len(errResults) > 0 { + err = merrors.InternalServerError("go.micro.server", "subscriber error: %v", strings.Join(errResults, "\n")) } - return errors.New("subscriber error: " + strings.Join(results, "\n")) + return err } diff --git a/transport/grpc/handler.go b/transport/grpc/handler.go index 3220f7dd..e02e1445 100644 --- a/transport/grpc/handler.go +++ b/transport/grpc/handler.go @@ -3,6 +3,7 @@ package grpc import ( "runtime/debug" + "github.com/micro/go-micro/errors" "github.com/micro/go-micro/transport" pb "github.com/micro/go-micro/transport/grpc/proto" "github.com/micro/go-micro/util/log" @@ -16,6 +17,8 @@ type microTransport struct { } func (m *microTransport) Stream(ts pb.Transport_StreamServer) error { + var err error + sock := &grpcTransportSocket{ stream: ts, local: m.addr, @@ -30,10 +33,12 @@ func (m *microTransport) Stream(ts pb.Transport_StreamServer) error { if r := recover(); r != nil { log.Log(r, string(debug.Stack())) sock.Close() + err = errors.InternalServerError("go.micro.transport", "panic recovered: %v", r) } }() // execute socket func m.fn(sock) - return nil + + return err } From f9b900b2caa031c3e342623a7a3449ad256b1eac Mon Sep 17 00:00:00 2001 From: Astone Date: Tue, 3 Dec 2019 12:47:29 +0800 Subject: [PATCH 295/344] optimize: a better way for return error --- server/grpc/grpc.go | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index 942d1a8f..0fa3d0f0 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -343,27 +343,22 @@ func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service, } // define the handler func - fn := func(ctx context.Context, req server.Request, rsp interface{}) error { - ch := make(chan error, 1) - defer close(ch) - + fn := func(ctx context.Context, req server.Request, rsp interface{}) (err error) { defer func() { if r := recover(); r != nil { log.Log("panic recovered: ", r) log.Logf(string(debug.Stack())) - ch <- errors.InternalServerError("go.micro.server", "panic recovered: %v", r) + err = errors.InternalServerError("go.micro.server", "panic recovered: %v", r) } }() returnValues = function.Call([]reflect.Value{service.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 { - ch <- err.(error) + if rerr := returnValues[0].Interface(); rerr != nil { + err = rerr.(error) } - ch <- nil - - return <-ch + return err } // wrap the handler func From 2c0801fc1cebed87517fb8b1cf6619c8b80cce3f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 3 Dec 2019 08:11:36 +0000 Subject: [PATCH 296/344] couple bug fixes in tunnel --- network/default.go | 2 ++ tunnel/session.go | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/network/default.go b/network/default.go index b9dfe13f..92ba4a84 100644 --- a/network/default.go +++ b/network/default.go @@ -1060,6 +1060,8 @@ func (n *network) Connect() error { // send the connect message n.sendConnect() + // most importantly + break } }() diff --git a/tunnel/session.go b/tunnel/session.go index 4b8721aa..b5b724b0 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -354,14 +354,14 @@ func (s *session) Send(m *transport.Message) error { // Recv is used to receive a message func (s *session) Recv(m *transport.Message) error { + var msg *message + select { case <-s.closed: return errors.New("session is closed") - default: - // no op - } // recv from backlog - msg := <-s.recv + case msg = <-s.recv: + } // check the error if one exists select { From 29fb58db3946b54621449d124358fa3ba891db10 Mon Sep 17 00:00:00 2001 From: Astone Date: Tue, 3 Dec 2019 15:25:58 +0800 Subject: [PATCH 297/344] improve code quality --- agent/input/telegram/conn.go | 8 +++----- client/grpc/grpc.go | 4 +++- client/rpc_client.go | 5 +++-- codec/bytes/bytes.go | 13 +++++------- codec/bytes/marshaler.go | 11 ++++------ codec/text/text.go | 14 ++++--------- network/default.go | 2 +- network/service/handler/handler.go | 5 ----- proxy/mucp/mucp.go | 11 ++++------ registry/mdns_registry.go | 8 ++++++-- registry/service/watcher.go | 32 ++++++++++++++---------------- router/default.go | 2 +- server/grpc/grpc.go | 4 +++- server/rpc_server.go | 4 +++- server/server.go | 2 +- sync/leader/etcd/etcd.go | 17 ++++------------ sync/lock/etcd/etcd.go | 4 +--- sync/task/task.go | 4 +++- tunnel/link.go | 4 ++-- web/service.go | 2 +- 20 files changed, 67 insertions(+), 89 deletions(-) diff --git a/agent/input/telegram/conn.go b/agent/input/telegram/conn.go index 44d1ada1..1012dece 100644 --- a/agent/input/telegram/conn.go +++ b/agent/input/telegram/conn.go @@ -44,11 +44,9 @@ func (tc *telegramConn) run() { tc.recv = updates tc.syncCond.Signal() - for { - select { - case <-tc.exit: - return - } + select { + case <-tc.exit: + return } } diff --git a/client/grpc/grpc.go b/client/grpc/grpc.go index ba7a3842..62b8d5db 100644 --- a/client/grpc/grpc.go +++ b/client/grpc/grpc.go @@ -339,7 +339,9 @@ func (g *grpcClient) Call(ctx context.Context, req client.Request, rsp interface d, ok := ctx.Deadline() if !ok { // no deadline so we create a new one - ctx, _ = context.WithTimeout(ctx, callOpts.RequestTimeout) + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, callOpts.RequestTimeout) + defer cancel() } else { // got a deadline so no need to setup context // but we need to set the timeout we pass along diff --git a/client/rpc_client.go b/client/rpc_client.go index c75a67b3..75ce75ac 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -162,7 +162,6 @@ func (r *rpcClient) call(ctx context.Context, node *registry.Node, req Request, select { case err := <-ch: - grr = err return err case <-ctx.Done(): grr = errors.Timeout("go.micro.client", fmt.Sprintf("%v", ctx.Err())) @@ -378,7 +377,9 @@ func (r *rpcClient) Call(ctx context.Context, request Request, response interfac d, ok := ctx.Deadline() if !ok { // no deadline so we create a new one - ctx, _ = context.WithTimeout(ctx, callOpts.RequestTimeout) + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, callOpts.RequestTimeout) + defer cancel() } else { // got a deadline so no need to setup context // but we need to set the timeout we pass along diff --git a/codec/bytes/bytes.go b/codec/bytes/bytes.go index 67ff4038..69d36235 100644 --- a/codec/bytes/bytes.go +++ b/codec/bytes/bytes.go @@ -29,12 +29,10 @@ func (c *Codec) ReadBody(b interface{}) error { return err } - switch b.(type) { + switch v := 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) @@ -45,14 +43,13 @@ func (c *Codec) ReadBody(b interface{}) error { func (c *Codec) Write(m *codec.Message, b interface{}) error { var v []byte - switch b.(type) { + switch vb := b.(type) { case *Frame: - v = b.(*Frame).Data + v = vb.Data case *[]byte: - ve := b.(*[]byte) - v = *ve + v = *vb case []byte: - v = b.([]byte) + v = vb default: return fmt.Errorf("failed to write: %v is not type of *[]byte or []byte", b) } diff --git a/codec/bytes/marshaler.go b/codec/bytes/marshaler.go index 76599b65..86af8984 100644 --- a/codec/bytes/marshaler.go +++ b/codec/bytes/marshaler.go @@ -12,25 +12,22 @@ type Message struct { } func (n Marshaler) Marshal(v interface{}) ([]byte, error) { - switch v.(type) { + switch ve := v.(type) { case *[]byte: - ve := v.(*[]byte) return *ve, nil case []byte: - return v.([]byte), nil + return ve, nil case *Message: - return v.(*Message).Body, nil + return ve.Body, nil } return nil, errors.New("invalid message") } func (n Marshaler) Unmarshal(d []byte, v interface{}) error { - switch v.(type) { + switch ve := v.(type) { case *[]byte: - ve := v.(*[]byte) *ve = d case *Message: - ve := v.(*Message) ve.Body = d } return errors.New("invalid message") diff --git a/codec/text/text.go b/codec/text/text.go index da43da50..799cf6c1 100644 --- a/codec/text/text.go +++ b/codec/text/text.go @@ -29,15 +29,12 @@ func (c *Codec) ReadBody(b interface{}) error { return err } - switch b.(type) { + switch v := b.(type) { case *string: - v := b.(*string) *v = string(buf) 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) @@ -48,20 +45,17 @@ func (c *Codec) ReadBody(b interface{}) error { func (c *Codec) Write(m *codec.Message, b interface{}) error { var v []byte - switch b.(type) { + switch ve := b.(type) { case *Frame: - v = b.(*Frame).Data + v = ve.Data case *[]byte: - ve := b.(*[]byte) v = *ve case *string: - ve := b.(*string) v = []byte(*ve) case string: - ve := b.(string) v = []byte(ve) case []byte: - v = b.([]byte) + v = ve default: return fmt.Errorf("failed to write: %v is not type of *[]byte or []byte", b) } diff --git a/network/default.go b/network/default.go index b9dfe13f..ac5c902e 100644 --- a/network/default.go +++ b/network/default.go @@ -823,7 +823,7 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { log.Tracef("Network metric for router %s and gateway %s: %v", event.Route.Router, event.Route.Gateway, metric) // check we don't overflow max int 64 - if d := route.Metric + metric; d > math.MaxInt64 || d <= 0 { + if d := route.Metric + metric; d <= 0 { // set to max int64 if we overflow route.Metric = math.MaxInt64 } else { diff --git a/network/service/handler/handler.go b/network/service/handler/handler.go index c47c0b30..62e8910c 100644 --- a/network/service/handler/handler.go +++ b/network/service/handler/handler.go @@ -94,11 +94,6 @@ func (n *Network) Connect(ctx context.Context, req *pbNet.ConnectRequest, resp * // Nodes returns the list of nodes func (n *Network) Nodes(ctx context.Context, req *pbNet.NodesRequest, resp *pbNet.NodesResponse) error { - depth := uint(req.Depth) - if depth <= 0 || depth > network.MaxDepth { - depth = network.MaxDepth - } - // root node nodes := map[string]network.Node{} diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index 1036f722..856657a1 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -274,7 +274,7 @@ func (p *Proxy) watchRoutes() { return } - if err := p.manageRoutes(event.Route, fmt.Sprintf("%s", event.Type)); err != nil { + if err := p.manageRoutes(event.Route, event.Type.String()); err != nil { // TODO: should we bail here? continue } @@ -562,12 +562,9 @@ func NewProxy(opts ...options.Option) proxy.Proxy { defer t.Stop() // we must refresh route metrics since they do not trigger new events - for { - select { - case <-t.C: - // refresh route metrics - p.refreshMetrics() - } + for range t.C { + // refresh route metrics + p.refreshMetrics() } }() diff --git a/registry/mdns_registry.go b/registry/mdns_registry.go index 6d1c75f7..48782f76 100644 --- a/registry/mdns_registry.go +++ b/registry/mdns_registry.go @@ -230,7 +230,9 @@ func (m *mdnsRegistry) GetService(service string) ([]*Service, error) { p := mdns.DefaultParams(service) // set context with timeout - p.Context, _ = context.WithTimeout(context.Background(), m.opts.Timeout) + var cancel context.CancelFunc + p.Context, cancel = context.WithTimeout(context.Background(), m.opts.Timeout) + defer cancel() // set entries channel p.Entries = entries // set the domain @@ -308,7 +310,9 @@ func (m *mdnsRegistry) ListServices() ([]*Service, error) { p := mdns.DefaultParams("_services") // set context with timeout - p.Context, _ = context.WithTimeout(context.Background(), m.opts.Timeout) + var cancel context.CancelFunc + p.Context, cancel = context.WithTimeout(context.Background(), m.opts.Timeout) + defer cancel() // set entries channel p.Entries = entries // set domain diff --git a/registry/service/watcher.go b/registry/service/watcher.go index c17085a0..973f9547 100644 --- a/registry/service/watcher.go +++ b/registry/service/watcher.go @@ -11,24 +11,22 @@ type serviceWatcher struct { } func (s *serviceWatcher) Next() (*registry.Result, error) { - for { - // check if closed - select { - case <-s.closed: - return nil, registry.ErrWatcherStopped - default: - } - - r, err := s.stream.Recv() - if err != nil { - return nil, err - } - - return ®istry.Result{ - Action: r.Action, - Service: ToService(r.Service), - }, nil + // check if closed + select { + case <-s.closed: + return nil, registry.ErrWatcherStopped + default: } + + r, err := s.stream.Recv() + if err != nil { + return nil, err + } + + return ®istry.Result{ + Action: r.Action, + Service: ToService(r.Service), + }, nil } func (s *serviceWatcher) Stop() { diff --git a/router/default.go b/router/default.go index 23384d2f..f938d1d5 100644 --- a/router/default.go +++ b/router/default.go @@ -718,7 +718,7 @@ func (r *router) Process(a *Advert) error { route := event.Route action := event.Type log.Debugf("Router %s applying %s from router %s for service %s %s", r.options.Id, action, route.Router, route.Service, route.Address) - if err := r.manageRoute(route, fmt.Sprintf("%s", action)); err != nil { + if err := r.manageRoute(route, action.String()); err != nil { return fmt.Errorf("failed applying action %s to routing table: %s", action, err) } } diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index 942d1a8f..ff180207 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -222,7 +222,9 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) error { // 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)) + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, time.Duration(n)) + defer cancel() } } diff --git a/server/rpc_server.go b/server/rpc_server.go index f1c3e713..8fee1470 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -277,7 +277,9 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // set the timeout from the header 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)) + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, time.Duration(n)) + defer cancel() } } diff --git a/server/server.go b/server/server.go index 34c38258..0fcc3436 100644 --- a/server/server.go +++ b/server/server.go @@ -201,7 +201,7 @@ func Run() error { } ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) + signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) log.Logf("Received signal %s", <-ch) return Stop() diff --git a/sync/leader/etcd/etcd.go b/sync/leader/etcd/etcd.go index 6179bf0b..f8e5baa5 100644 --- a/sync/leader/etcd/etcd.go +++ b/sync/leader/etcd/etcd.go @@ -39,9 +39,7 @@ func (e *etcdLeader) Elect(id string, opts ...leader.ElectOption) (leader.Electe l := cc.NewElection(s, path) - ctx, _ := context.WithCancel(context.Background()) - - if err := l.Campaign(ctx, id); err != nil { + if err := l.Campaign(context.TODO(), id); err != nil { return nil, err } @@ -63,14 +61,8 @@ func (e *etcdLeader) Follow() chan string { ech := l.Observe(context.Background()) go func() { - for { - select { - case r, ok := <-ech: - if !ok { - return - } - ch <- string(r.Kvs[0].Value) - } + for r := range ech { + ch <- string(r.Kvs[0].Value) } }() @@ -82,8 +74,7 @@ func (e *etcdLeader) String() string { } func (e *etcdElected) Reelect() error { - ctx, _ := context.WithCancel(context.Background()) - return e.e.Campaign(ctx, e.id) + return e.e.Campaign(context.TODO(), e.id) } func (e *etcdElected) Revoked() chan bool { diff --git a/sync/lock/etcd/etcd.go b/sync/lock/etcd/etcd.go index 0b8ba823..9c55ddde 100644 --- a/sync/lock/etcd/etcd.go +++ b/sync/lock/etcd/etcd.go @@ -49,9 +49,7 @@ func (e *etcdLock) Acquire(id string, opts ...lock.AcquireOption) error { m := cc.NewMutex(s, path) - ctx, _ := context.WithCancel(context.Background()) - - if err := m.Lock(ctx); err != nil { + if err := m.Lock(context.TODO()); err != nil { return err } diff --git a/sync/task/task.go b/sync/task/task.go index 031355ca..c9b9b5d6 100644 --- a/sync/task/task.go +++ b/sync/task/task.go @@ -63,7 +63,9 @@ func (s Schedule) Run() <-chan time.Time { } // start ticker - for t := range time.Tick(s.Interval) { + ticker := time.NewTicker(s.Interval) + defer ticker.Stop() + for t := range ticker.C { ch <- t } }() diff --git a/tunnel/link.go b/tunnel/link.go index d135c152..25083138 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -228,7 +228,7 @@ func (l *link) manage() { } // check the type of message switch { - case bytes.Compare(p.message.Body, linkRequest) == 0: + case bytes.Equal(p.message.Body, linkRequest): log.Tracef("Link %s received link request %v", l.id, p.message.Body) // send response if err := send(linkResponse); err != nil { @@ -236,7 +236,7 @@ func (l *link) manage() { l.errCount++ l.Unlock() } - case bytes.Compare(p.message.Body, linkResponse) == 0: + case bytes.Equal(p.message.Body, linkResponse): // set round trip time d := time.Since(now) log.Tracef("Link %s received link response in %v", p.message.Body, d) diff --git a/web/service.go b/web/service.go index da78d6c8..97c5255a 100644 --- a/web/service.go +++ b/web/service.go @@ -376,7 +376,7 @@ func (s *service) Run() error { go s.run(ex) ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) + signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) select { // wait on kill signal From c581ceb1dc1c7a6457988b84b6cadaa4c5253a81 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 Dec 2019 16:23:09 +0300 Subject: [PATCH 298/344] add golanglint-ci Signed-off-by: Vasiliy Tolstov --- .golangci.yml | 26 ++++++++++++++++++++++++++ .travis.yml | 6 ++++++ 2 files changed, 32 insertions(+) create mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..0228bfc5 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,26 @@ +run: + deadline: 10m +linters: + disable-all: false + enable-all: false + enable: + - megacheck + - staticcheck + - deadcode + - varcheck + - gosimple + - unused + - prealloc + - scopelint + - gocritic + - goimports + - unconvert + - govet + - nakedret + - structcheck + - gosec + disable: + - maligned + - interfacer + - typecheck + - dupl diff --git a/.travis.yml b/.travis.yml index e2a018e2..d26a9c52 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,12 @@ go: - 1.13.x env: - GO111MODULE=on IN_TRAVIS_CI=yes +before_script: + - go install github.com/golangci/golangci-lint/cmd/golangci-lint +script: + - golangci-lint run || true + - go test -v -race ./... || true + - go test -v ./... notifications: slack: secure: aEvhLbhujaGaKSrOokiG3//PaVHTIrc3fBpoRbCRqfZpyq6WREoapJJhF+tIpWWOwaC9GmChbD6aHo/jMUgwKXVyPSaNjiEL87YzUUpL8B2zslNp1rgfTg/LrzthOx3Q1TYwpaAl3to0fuHUVFX4yMeC2vuThq7WSXgMMxFCtbc= From 265233517e88f2ce37d08815f453f646fad89df4 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 3 Dec 2019 14:49:24 +0000 Subject: [PATCH 299/344] Fix memory registry race --- registry/memory/memory.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/registry/memory/memory.go b/registry/memory/memory.go index 83990377..3d7b782e 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -87,9 +87,8 @@ func (m *Registry) ttlPrune() { } func (m *Registry) sendEvent(r *registry.Result) { - watchers := make([]*Watcher, 0, len(m.watchers)) - m.RLock() + watchers := make([]*Watcher, 0, len(m.watchers)) for _, w := range m.watchers { watchers = append(watchers, w) } From 4a11a4c546561d5189c6777f3512ccf5a4bea873 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Tue, 3 Dec 2019 15:22:54 +0000 Subject: [PATCH 300/344] Fix router race condition --- router/default.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/router/default.go b/router/default.go index f938d1d5..e4305436 100644 --- a/router/default.go +++ b/router/default.go @@ -513,25 +513,28 @@ func (r *router) advertiseEvents() error { // close closes exit channels func (r *router) close() { - // notify all goroutines to finish - close(r.exit) - + log.Debugf("Router closing remaining channels") // drain the advertise channel only if advertising if r.status.Code == Advertising { // drain the event channel for range r.eventChan { } - r.sub.RLock() // close advert subscribers for id, sub := range r.subscribers { + select { + case <-sub: + default: + } + // close the channel close(sub) // delete the subscriber + r.sub.Lock() delete(r.subscribers, id) + r.sub.Unlock() } - r.sub.RUnlock() } // mark the router as Stopped and set its Error to nil @@ -552,6 +555,9 @@ func (r *router) watchErrors() { defer r.Unlock() // if the router is not stopped, stop it if r.status.Code != Stopped { + // notify all goroutines to finish + close(r.exit) + // close all the channels r.close() // set the status error @@ -857,6 +863,9 @@ func (r *router) Stop() error { r.Unlock() return r.status.Error case Running, Advertising: + // notify all goroutines to finish + close(r.exit) + // close all the channels // NOTE: close marks the router status as Stopped r.close() From 7d5bdcf993d6e758257e0e73899eefd0189ae0f9 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 Dec 2019 18:47:11 +0300 Subject: [PATCH 301/344] fix pointer dereference in memory registry Signed-off-by: Vasiliy Tolstov --- registry/memory/util.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/memory/util.go b/registry/memory/util.go index e49f30c8..965c75b5 100644 --- a/registry/memory/util.go +++ b/registry/memory/util.go @@ -44,9 +44,9 @@ func recordToService(r *record) *registry.Service { endpoints := make([]*registry.Endpoint, len(r.Endpoints)) for i, e := range r.Endpoints { request := new(registry.Value) - request = e.Request + *request = *e.Request response := new(registry.Value) - response = e.Response + *response = *e.Response metadata := make(map[string]string) for k, v := range e.Metadata { From becaeefcba62cef6127cf3d13f2a41ddf1a5ec82 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 3 Dec 2019 20:32:02 +0000 Subject: [PATCH 302/344] Revert. DO NOT peer solicit until we know better --- network/default.go | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/network/default.go b/network/default.go index 92ba4a84..57e75373 100644 --- a/network/default.go +++ b/network/default.go @@ -476,24 +476,6 @@ func (n *network) processNetChan(listener tunnel.Listener) { n.Lock() delete(n.peerLinks, pbNetClose.Node.Address) n.Unlock() - case "solicit": - // received a peer solicit message - pbRtrSolicit := &pbRtr.Solicit{} - if err := proto.Unmarshal(m.msg.Body, pbRtrSolicit); err != nil { - log.Debugf("Network fail to unmarshal solicit message: %v", err) - continue - } - log.Debugf("Network received peer solicit message from: %s", pbRtrSolicit.Id) - // ignore solicitation when requested by you - if pbRtrSolicit.Id == n.options.Id { - continue - } - // get node peers down to MaxDepth encoded in protobuf - msg := PeersToProto(n.node, MaxDepth) - // advertise yourself to the network - if err := n.sendMsg("peer", msg, NetworkChannel); err != nil { - log.Debugf("Network failed to advertise peers: %v", err) - } } case <-n.closed: return @@ -785,13 +767,6 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { // loookup advertising node in our peer topology advertNode := n.node.GetPeerNode(pbRtrAdvert.Id) if advertNode == nil { - msg := &pbRtr.Solicit{ - Id: pbRtrAdvert.Id, - } - // go solicit the peer - if err := n.sendMsg("solicit", msg, NetworkChannel); err != nil { - log.Debugf("Network failed to send solicit message: %s", err) - } // if we can't find the node in our topology (MaxDepth) we skipp prcessing adverts log.Debugf("Network skipping advert message from unknown peer: %s", pbRtrAdvert.Id) continue From a1eaf9cc202edad3b500f1b2b6ad9f292aae605f Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 3 Dec 2019 22:59:44 +0300 Subject: [PATCH 303/344] linting fixes Signed-off-by: Vasiliy Tolstov --- agent/input/telegram/conn.go | 2 +- agent/input/telegram/telegram.go | 2 +- api/handler/cloudevents/event.go | 2 +- api/handler/rpc/rpc_test.go | 2 +- api/server/acme/certmagic/storage.go | 5 +++-- broker/http_broker.go | 2 ++ broker/nats/nats.go | 1 + broker/nats/nats_test.go | 1 - client/grpc/codec.go | 10 ---------- client/grpc/grpc.go | 10 ---------- client/grpc/grpc_pool_test.go | 2 +- client/selector/dns/dns.go | 10 +++------- client/selector/router/router.go | 2 -- client/selector/selector.go | 1 + client/selector/strategy.go | 2 +- config/loader/memory/memory.go | 1 + config/options/options.go | 5 ++++- config/source/env/options.go | 1 + network/default.go | 1 + network/resolver/dns/dns.go | 1 + network/resolver/dnssrv/dnssrv.go | 2 +- network/service/handler/handler.go | 3 ++- proxy/mucp/mucp.go | 4 +++- registry/etcd/etcd.go | 4 +--- registry/memory/memory_watcher.go | 6 ++---- registry/memory/util.go | 8 ++++++-- router/table_test.go | 2 ++ runtime/default.go | 4 +++- runtime/source/git/git.go | 2 +- server/grpc/grpc.go | 2 +- server/rpc_server.go | 11 ++++------- store/cloudflare/cloudflare.go | 1 + store/etcd/etcd.go | 5 +++-- store/memory/memory.go | 2 ++ store/postgresql/postgresql_test.go | 22 +++++++++++----------- store/service/handler/handler.go | 2 +- store/service/service.go | 5 +++-- sync/lock/memory/memory.go | 4 ++-- transport/quic/quic.go | 2 +- tunnel/default.go | 1 + util/addr/addr.go | 1 + 41 files changed, 76 insertions(+), 80 deletions(-) diff --git a/agent/input/telegram/conn.go b/agent/input/telegram/conn.go index 1012dece..78a8ff3a 100644 --- a/agent/input/telegram/conn.go +++ b/agent/input/telegram/conn.go @@ -8,7 +8,7 @@ import ( "github.com/forestgiant/sliceutil" "github.com/micro/go-micro/agent/input" "github.com/micro/go-micro/util/log" - "gopkg.in/telegram-bot-api.v4" + tgbotapi "gopkg.in/telegram-bot-api.v4" ) type telegramConn struct { diff --git a/agent/input/telegram/telegram.go b/agent/input/telegram/telegram.go index 87566e4e..a1510527 100644 --- a/agent/input/telegram/telegram.go +++ b/agent/input/telegram/telegram.go @@ -7,7 +7,7 @@ import ( "github.com/micro/cli" "github.com/micro/go-micro/agent/input" - "gopkg.in/telegram-bot-api.v4" + tgbotapi "gopkg.in/telegram-bot-api.v4" ) type telegramInput struct { diff --git a/api/handler/cloudevents/event.go b/api/handler/cloudevents/event.go index 6c0c6cf9..4869188b 100644 --- a/api/handler/cloudevents/event.go +++ b/api/handler/cloudevents/event.go @@ -32,7 +32,7 @@ import ( "unicode" "github.com/google/uuid" - "gopkg.in/go-playground/validator.v9" + validator "gopkg.in/go-playground/validator.v9" ) const ( diff --git a/api/handler/rpc/rpc_test.go b/api/handler/rpc/rpc_test.go index 2804a84c..f50cdedf 100644 --- a/api/handler/rpc/rpc_test.go +++ b/api/handler/rpc/rpc_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/golang/protobuf/proto" - "github.com/micro/go-micro/api/proto" + go_api "github.com/micro/go-micro/api/proto" ) func TestRequestPayloadFromRequest(t *testing.T) { diff --git a/api/server/acme/certmagic/storage.go b/api/server/acme/certmagic/storage.go index 6b8e04fb..24d187f5 100644 --- a/api/server/acme/certmagic/storage.go +++ b/api/server/acme/certmagic/storage.go @@ -81,8 +81,7 @@ func (s *storage) Delete(key string) error { } func (s *storage) Exists(key string) bool { - _, err := s.store.Read(key) - if err != nil { + if _, err := s.store.Read(key); err != nil { return false } return true @@ -93,6 +92,8 @@ func (s *storage) List(prefix string, recursive bool) ([]string, error) { if err != nil { return nil, err } + + //nolint:prealloc var results []string for _, r := range records { if strings.HasPrefix(r.Key, prefix) { diff --git a/broker/http_broker.go b/broker/http_broker.go index b6c78b62..53dd48f1 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -237,6 +237,7 @@ func (h *httpBroker) unsubscribe(s *httpSubscriber) error { h.Lock() defer h.Unlock() + //nolint:prealloc var subscribers []*httpSubscriber // look for subscriber @@ -325,6 +326,7 @@ func (h *httpBroker) ServeHTTP(w http.ResponseWriter, req *http.Request) { p := &httpEvent{m: m, t: topic} id := req.Form.Get("id") + //nolint:prealloc var subs []Handler h.RLock() diff --git a/broker/nats/nats.go b/broker/nats/nats.go index eecb16ec..a72f7682 100644 --- a/broker/nats/nats.go +++ b/broker/nats/nats.go @@ -70,6 +70,7 @@ func (n *natsBroker) Address() string { } func setAddrs(addrs []string) []string { + //nolint:prealloc var cAddrs []string for _, addr := range addrs { if len(addr) == 0 { diff --git a/broker/nats/nats_test.go b/broker/nats/nats_test.go index 36625da2..e58362e5 100644 --- a/broker/nats/nats_test.go +++ b/broker/nats/nats_test.go @@ -94,6 +94,5 @@ func TestInitAddrs(t *testing.T) { } } }) - } } diff --git a/client/grpc/codec.go b/client/grpc/codec.go index c792abbd..2f32a0b1 100644 --- a/client/grpc/codec.go +++ b/client/grpc/codec.go @@ -11,8 +11,6 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/codec/bytes" - "github.com/micro/go-micro/codec/jsonrpc" - "github.com/micro/go-micro/codec/protorpc" "google.golang.org/grpc" "google.golang.org/grpc/encoding" ) @@ -36,14 +34,6 @@ var ( "application/grpc+bytes": bytesCodec{}, } - defaultRPCCodecs = 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, - } - json = jsoniter.ConfigCompatibleWithStandardLibrary ) diff --git a/client/grpc/grpc.go b/client/grpc/grpc.go index 62b8d5db..a593b690 100644 --- a/client/grpc/grpc.go +++ b/client/grpc/grpc.go @@ -282,16 +282,6 @@ func (g *grpcClient) newGRPCCodec(contentType string) (encoding.Codec, error) { return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) } -func (g *grpcClient) newCodec(contentType string) (codec.NewCodec, error) { - if c, ok := g.opts.Codecs[contentType]; ok { - return c, nil - } - if cf, ok := defaultRPCCodecs[contentType]; ok { - return cf, nil - } - return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) -} - func (g *grpcClient) Init(opts ...client.Option) error { size := g.opts.PoolSize ttl := g.opts.PoolTTL diff --git a/client/grpc/grpc_pool_test.go b/client/grpc/grpc_pool_test.go index 955e18c5..d5c1fdb0 100644 --- a/client/grpc/grpc_pool_test.go +++ b/client/grpc/grpc_pool_test.go @@ -1,11 +1,11 @@ package grpc import ( + "context" "net" "testing" "time" - "context" "google.golang.org/grpc" pgrpc "google.golang.org/grpc" pb "google.golang.org/grpc/examples/helloworld/helloworld" diff --git a/client/selector/dns/dns.go b/client/selector/dns/dns.go index 4248fe3d..450ae412 100644 --- a/client/selector/dns/dns.go +++ b/client/selector/dns/dns.go @@ -63,7 +63,7 @@ func (d *dnsSelector) Select(service string, opts ...selector.SelectOption) (sel } } - var nodes []*registry.Node + nodes := make([]*registry.Node, 0, len(srv)) for _, node := range srv { nodes = append(nodes, ®istry.Node{ Id: node.Target, @@ -99,13 +99,9 @@ func (d *dnsSelector) Select(service string, opts ...selector.SelectOption) (sel return sopts.Strategy(services), nil } -func (d *dnsSelector) Mark(service string, node *registry.Node, err error) { - return -} +func (d *dnsSelector) Mark(service string, node *registry.Node, err error) {} -func (d *dnsSelector) Reset(service string) { - return -} +func (d *dnsSelector) Reset(service string) {} func (d *dnsSelector) Close() error { return nil diff --git a/client/selector/router/router.go b/client/selector/router/router.go index 4a6ad671..ed7c10e6 100644 --- a/client/selector/router/router.go +++ b/client/selector/router/router.go @@ -176,12 +176,10 @@ func (r *routerSelector) Select(service string, opts ...selector.SelectOption) ( func (r *routerSelector) Mark(service string, node *registry.Node, err error) { // TODO: pass back metrics or information to the router - return } func (r *routerSelector) Reset(service string) { // TODO: reset the metrics or information at the router - return } func (r *routerSelector) Close() error { diff --git a/client/selector/selector.go b/client/selector/selector.go index 5c9a2499..83d82974 100644 --- a/client/selector/selector.go +++ b/client/selector/selector.go @@ -3,6 +3,7 @@ package selector import ( "errors" + "github.com/micro/go-micro/registry" ) diff --git a/client/selector/strategy.go b/client/selector/strategy.go index 559ed030..5014d25d 100644 --- a/client/selector/strategy.go +++ b/client/selector/strategy.go @@ -32,7 +32,7 @@ func Random(services []*registry.Service) Next { // RoundRobin is a roundrobin strategy algorithm for node selection func RoundRobin(services []*registry.Service) Next { - var nodes []*registry.Node + nodes := make([]*registry.Node, 0, len(services)) for _, service := range services { nodes = append(nodes, service.Nodes...) diff --git a/config/loader/memory/memory.go b/config/loader/memory/memory.go index 62f1e0ae..21141c5b 100644 --- a/config/loader/memory/memory.go +++ b/config/loader/memory/memory.go @@ -193,6 +193,7 @@ func (m *memory) Snapshot() (*loader.Snapshot, error) { // Sync loads all the sources, calls the parser and updates the config func (m *memory) Sync() error { + //nolint:prealloc var sets []*source.ChangeSet m.Lock() diff --git a/config/options/options.go b/config/options/options.go index 588f4838..b465ba63 100644 --- a/config/options/options.go +++ b/config/options/options.go @@ -2,6 +2,7 @@ package options import ( + "log" "sync" ) @@ -68,6 +69,8 @@ func WithString(s string) Option { // NewOptions returns a new initialiser func NewOptions(opts ...Option) Options { o := new(defaultOptions) - o.Init(opts...) + if err := o.Init(opts...); err != nil { + log.Fatal(err) + } return o } diff --git a/config/source/env/options.go b/config/source/env/options.go index 112a7db2..495672b5 100644 --- a/config/source/env/options.go +++ b/config/source/env/options.go @@ -35,6 +35,7 @@ func WithPrefix(p ...string) source.Option { } func appendUnderscore(prefixes []string) []string { + //nolint:prealloc var result []string for _, p := range prefixes { if !strings.HasSuffix(p, "_") { diff --git a/network/default.go b/network/default.go index 4ddcc2e4..2cee7aec 100644 --- a/network/default.go +++ b/network/default.go @@ -195,6 +195,7 @@ func (n *network) resolveNodes() ([]string, error) { nodeMap := make(map[string]bool) // collect network node addresses + //nolint:prealloc var nodes []string var i int diff --git a/network/resolver/dns/dns.go b/network/resolver/dns/dns.go index aaa3a744..b4029f06 100644 --- a/network/resolver/dns/dns.go +++ b/network/resolver/dns/dns.go @@ -38,6 +38,7 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { return nil, err } + //nolint:prealloc var records []*resolver.Record for _, answer := range rec.Answer { diff --git a/network/resolver/dnssrv/dnssrv.go b/network/resolver/dnssrv/dnssrv.go index 75a11795..9bfe9638 100644 --- a/network/resolver/dnssrv/dnssrv.go +++ b/network/resolver/dnssrv/dnssrv.go @@ -17,7 +17,7 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { if err != nil { return nil, err } - var records []*resolver.Record + records := make([]*resolver.Record, len(addrs)) for _, addr := range addrs { address := addr.Target if addr.Port > 0 { diff --git a/network/service/handler/handler.go b/network/service/handler/handler.go index 62e8910c..5a9f9379 100644 --- a/network/service/handler/handler.go +++ b/network/service/handler/handler.go @@ -29,10 +29,11 @@ func flatten(n network.Node, visited map[string]bool) []network.Node { } // create new list of nodes + //nolint:prealloc var nodes []network.Node // check if already visited - if visited[n.Id()] == false { + if !visited[n.Id()] { // append the current node nodes = append(nodes, n) } diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index 856657a1..a202fe3d 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -83,7 +83,7 @@ func readLoop(r server.Request, s client.Stream) error { // toNodes returns a list of node addresses from given routes func toNodes(routes []router.Route) []string { - var nodes []string + nodes := make([]string, len(routes)) for _, node := range routes { address := node.Address if len(node.Gateway) > 0 { @@ -112,6 +112,7 @@ func (p *Proxy) filterRoutes(ctx context.Context, routes []router.Route) []route return routes } + //nolint:prealloc var filteredRoutes []router.Route // filter the routes based on our headers @@ -361,6 +362,7 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server routes = addr } + //nolint:prealloc var opts []client.CallOption // set strategy to round robin diff --git a/registry/etcd/etcd.go b/registry/etcd/etcd.go index 182ddbf8..a48932fc 100644 --- a/registry/etcd/etcd.go +++ b/registry/etcd/etcd.go @@ -335,9 +335,7 @@ func (e *etcdRegistry) GetService(name string) ([]*registry.Service, error) { serviceMap[s.Version] = s } - for _, node := range sn.Nodes { - s.Nodes = append(s.Nodes, node) - } + s.Nodes = append(s.Nodes, sn.Nodes...) } } diff --git a/registry/memory/memory_watcher.go b/registry/memory/memory_watcher.go index 3ec2071b..8eb3cfd1 100644 --- a/registry/memory/memory_watcher.go +++ b/registry/memory/memory_watcher.go @@ -13,10 +13,8 @@ type memoryWatcher struct { func (m *memoryWatcher) Next() (*registry.Result, error) { // not implement so we just block until exit - select { - case <-m.exit: - return nil, errors.New("watcher stopped") - } + <-m.exit + return nil, errors.New("watcher stopped") } func (m *memoryWatcher) Stop() { diff --git a/registry/memory/util.go b/registry/memory/util.go index 965c75b5..d78e3324 100644 --- a/registry/memory/util.go +++ b/registry/memory/util.go @@ -44,9 +44,13 @@ func recordToService(r *record) *registry.Service { endpoints := make([]*registry.Endpoint, len(r.Endpoints)) for i, e := range r.Endpoints { request := new(registry.Value) - *request = *e.Request + if e.Request != nil { + *request = *e.Request + } response := new(registry.Value) - *response = *e.Response + if e.Response != nil { + *response = *e.Response + } metadata := make(map[string]string) for k, v := range e.Metadata { diff --git a/router/table_test.go b/router/table_test.go index 50966f99..a05cb956 100644 --- a/router/table_test.go +++ b/router/table_test.go @@ -127,6 +127,8 @@ func TestQuery(t *testing.T) { routes, err := table.Query() if err != nil { t.Errorf("error looking up routes: %s", err) + } else if len(routes) == 0 { + t.Errorf("error looking up routes: not found") } // query routes particular network diff --git a/runtime/default.go b/runtime/default.go index f0c26eec..11ab7d32 100644 --- a/runtime/default.go +++ b/runtime/default.go @@ -195,6 +195,7 @@ func (r *runtime) Read(opts ...ReadOption) ([]*Service, error) { return k == v } + //nolint:prealloc var services []*Service for _, service := range r.services { @@ -258,10 +259,11 @@ func (r *runtime) Delete(s *Service) error { // List returns a slice of all services tracked by the runtime func (r *runtime) List() ([]*Service, error) { - var services []*Service r.RLock() defer r.RUnlock() + services := make([]*Service, 0, len(r.services)) + for _, service := range r.services { services = append(services, service.Service) } diff --git a/runtime/source/git/git.go b/runtime/source/git/git.go index f8d8000b..deaaa7ef 100644 --- a/runtime/source/git/git.go +++ b/runtime/source/git/git.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/micro/go-micro/runtime/source" - "gopkg.in/src-d/go-git.v4" + git "gopkg.in/src-d/go-git.v4" ) // Source retrieves source code diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index c365d33d..7d3d7426 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -178,7 +178,7 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) error { fullMethod, ok := grpc.MethodFromServerStream(stream) if !ok { - return grpc.Errorf(codes.Internal, "method does not exist in context") + return status.Errorf(codes.Internal, "method does not exist in context") } serviceName, methodName, err := mgrpc.ServiceMethod(fullMethod) diff --git a/server/rpc_server.go b/server/rpc_server.go index 8fee1470..a22f13b6 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -880,13 +880,10 @@ func (s *rpcServer) Stop() error { ch := make(chan error) s.exit <- ch - var err error - select { - case err = <-ch: - s.Lock() - s.started = false - s.Unlock() - } + err := <-ch + s.Lock() + s.started = false + s.Unlock() return err } diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index 24ca69f0..3b9a5e8c 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -136,6 +136,7 @@ func (w *workersKV) Read(keys ...string) ([]*store.Record, error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() + //nolint:prealloc var records []*store.Record for _, k := range keys { diff --git a/store/etcd/etcd.go b/store/etcd/etcd.go index e45ce2d1..8ffa2d7d 100644 --- a/store/etcd/etcd.go +++ b/store/etcd/etcd.go @@ -17,6 +17,7 @@ type ekv struct { } func (e *ekv) Read(keys ...string) ([]*store.Record, error) { + //nolint:prealloc var values []*mvccpb.KeyValue for _, key := range keys { @@ -73,10 +74,10 @@ func (e *ekv) List() ([]*store.Record, error) { if err != nil { return nil, err } - var vals []*store.Record if keyval == nil || len(keyval.Kvs) == 0 { - return vals, nil + return nil, nil } + vals := make([]*store.Record, 0, len(keyval.Kvs)) for _, keyv := range keyval.Kvs { vals = append(vals, &store.Record{ Key: string(keyv.Key), diff --git a/store/memory/memory.go b/store/memory/memory.go index aa5f645f..01d1a44c 100644 --- a/store/memory/memory.go +++ b/store/memory/memory.go @@ -25,6 +25,7 @@ func (m *memoryStore) List() ([]*store.Record, error) { m.RLock() defer m.RUnlock() + //nolint:prealloc var values []*store.Record for _, v := range m.values { @@ -52,6 +53,7 @@ func (m *memoryStore) Read(keys ...string) ([]*store.Record, error) { m.RLock() defer m.RUnlock() + //nolint:prealloc var records []*store.Record for _, key := range keys { diff --git a/store/postgresql/postgresql_test.go b/store/postgresql/postgresql_test.go index 65d97e78..fffc974e 100644 --- a/store/postgresql/postgresql_test.go +++ b/store/postgresql/postgresql_test.go @@ -76,20 +76,20 @@ func TestSQL(t *testing.T) { records, err = sqlStore.Read("test") if err != nil { t.Error(err) - } else { - t.Logf("%# v\n", pretty.Formatter(records)) - if string(records[0].Value) != "bar" { - t.Error("Expected bar, got ", string(records[0].Value)) - } + } + t.Logf("%# v\n", pretty.Formatter(records)) + if string(records[0].Value) != "bar" { + t.Error("Expected bar, got ", string(records[0].Value)) } time.Sleep(61 * time.Second) - records, err = sqlStore.Read("test") - if err == nil { + _, err = sqlStore.Read("test") + switch err { + case nil: t.Error("Key test should have expired") - } else { - if err != store.ErrNotFound { - t.Error(err) - } + default: + t.Error(err) + case store.ErrNotFound: + break } } diff --git a/store/service/handler/handler.go b/store/service/handler/handler.go index f4dd0710..3f546a9d 100644 --- a/store/service/handler/handler.go +++ b/store/service/handler/handler.go @@ -30,7 +30,7 @@ func (s *Store) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadRespo } func (s *Store) Write(ctx context.Context, req *pb.WriteRequest, rsp *pb.WriteResponse) error { - var records []*store.Record + records := make([]*store.Record, 0, len(req.Records)) for _, record := range req.Records { records = append(records, &store.Record{ diff --git a/store/service/service.go b/store/service/service.go index b3f8ad56..1cb486bc 100644 --- a/store/service/service.go +++ b/store/service/service.go @@ -60,7 +60,8 @@ func (s *serviceStore) Read(keys ...string) ([]*store.Record, error) { if err != nil { return nil, err } - var records []*store.Record + + records := make([]*store.Record, 0, len(rsp.Records)) for _, val := range rsp.Records { records = append(records, &store.Record{ Key: val.Key, @@ -73,7 +74,7 @@ func (s *serviceStore) Read(keys ...string) ([]*store.Record, error) { // Write a record func (s *serviceStore) Write(recs ...*store.Record) error { - var records []*pb.Record + records := make([]*pb.Record, 0, len(recs)) for _, record := range recs { records = append(records, &pb.Record{ diff --git a/sync/lock/memory/memory.go b/sync/lock/memory/memory.go index 84e0ca73..f8e46c7f 100644 --- a/sync/lock/memory/memory.go +++ b/sync/lock/memory/memory.go @@ -61,7 +61,7 @@ func (m *memoryLock) Acquire(id string, opts ...lock.AcquireOption) error { // set a timer for the leftover ttl if live > lk.ttl { // release the lock if it expired - m.Release(id) + _ = m.Release(id) } else { ttl = time.After(live) } @@ -94,7 +94,7 @@ lockLoop: break lockLoop case <-ttl: // ttl exceeded - m.Release(id) + _ = m.Release(id) // TODO: check the ttl again above ttl = nil // try acquire diff --git a/transport/quic/quic.go b/transport/quic/quic.go index 956c58f9..a39e9519 100644 --- a/transport/quic/quic.go +++ b/transport/quic/quic.go @@ -7,7 +7,7 @@ import ( "encoding/gob" "time" - "github.com/lucas-clemente/quic-go" + quic "github.com/lucas-clemente/quic-go" "github.com/micro/go-micro/transport" utls "github.com/micro/go-micro/util/tls" ) diff --git a/tunnel/default.go b/tunnel/default.go index 16ab2e59..da96540c 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -105,6 +105,7 @@ func (t *tun) listChannels() []string { t.RLock() defer t.RUnlock() + //nolint:prealloc var channels []string for _, session := range t.sessions { if session.session != "listener" { diff --git a/util/addr/addr.go b/util/addr/addr.go index 911dacb0..eb0a5972 100644 --- a/util/addr/addr.go +++ b/util/addr/addr.go @@ -39,6 +39,7 @@ func Extract(addr string) (string, error) { return "", fmt.Errorf("Failed to get interfaces! Err: %v", err) } + //nolint:prealloc var addrs []net.Addr var loAddrs []net.Addr for _, iface := range ifaces { From 5200febaeabcd023ba1014cd68be15976a428fc3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 4 Dec 2019 11:53:20 +0000 Subject: [PATCH 304/344] add stats debug interface --- debug/stats/stats.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 debug/stats/stats.go diff --git a/debug/stats/stats.go b/debug/stats/stats.go new file mode 100644 index 00000000..16e9faf3 --- /dev/null +++ b/debug/stats/stats.go @@ -0,0 +1,24 @@ +// Package stats provides runtime stats +package stats + +// Stats provides stats interface +type Stats interface { + // Read a stat snapshot + Read() (*Stat, error) + // Write a stat snapshot + Write(*Stat) error +} + +// A runtime stat +type Stat struct { + // Start time as unix timestamp + Started int64 + // Uptime in nanoseconds + Uptime int64 + // Memory usage in bytes + Memory uint64 + // Threads aka go routines + Threads uint64 + // Garbage collection in nanoseconds + GC uint64 +} From 97433f716fd0d647394f9ddd421d16b58d6c31ef Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 4 Dec 2019 12:02:44 +0000 Subject: [PATCH 305/344] add service name to debug proto --- debug/proto/debug.pb.go | 121 +++++++++++++++++++++------------- debug/proto/debug.pb.micro.go | 2 +- debug/proto/debug.proto | 20 ++++-- 3 files changed, 91 insertions(+), 52 deletions(-) diff --git a/debug/proto/debug.pb.go b/debug/proto/debug.pb.go index a94a55ce..0ee2536f 100644 --- a/debug/proto/debug.pb.go +++ b/debug/proto/debug.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: debug.proto +// source: github.com/micro/go-micro/debug/proto/debug.proto package debug @@ -21,6 +21,8 @@ var _ = math.Inf const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type HealthRequest struct { + // optional service name + Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -30,7 +32,7 @@ func (m *HealthRequest) Reset() { *m = HealthRequest{} } func (m *HealthRequest) String() string { return proto.CompactTextString(m) } func (*HealthRequest) ProtoMessage() {} func (*HealthRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_8d9d361be58531fb, []int{0} + return fileDescriptor_7cb19b1a05a6e0a9, []int{0} } func (m *HealthRequest) XXX_Unmarshal(b []byte) error { @@ -51,6 +53,13 @@ func (m *HealthRequest) XXX_DiscardUnknown() { var xxx_messageInfo_HealthRequest proto.InternalMessageInfo +func (m *HealthRequest) GetService() string { + if m != nil { + return m.Service + } + return "" +} + type HealthResponse struct { // default: ok Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` @@ -63,7 +72,7 @@ func (m *HealthResponse) Reset() { *m = HealthResponse{} } func (m *HealthResponse) String() string { return proto.CompactTextString(m) } func (*HealthResponse) ProtoMessage() {} func (*HealthResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_8d9d361be58531fb, []int{1} + return fileDescriptor_7cb19b1a05a6e0a9, []int{1} } func (m *HealthResponse) XXX_Unmarshal(b []byte) error { @@ -92,6 +101,8 @@ func (m *HealthResponse) GetStatus() string { } type StatsRequest struct { + // optional service name + Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -101,7 +112,7 @@ func (m *StatsRequest) Reset() { *m = StatsRequest{} } func (m *StatsRequest) String() string { return proto.CompactTextString(m) } func (*StatsRequest) ProtoMessage() {} func (*StatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_8d9d361be58531fb, []int{2} + return fileDescriptor_7cb19b1a05a6e0a9, []int{2} } func (m *StatsRequest) XXX_Unmarshal(b []byte) error { @@ -122,6 +133,13 @@ func (m *StatsRequest) XXX_DiscardUnknown() { var xxx_messageInfo_StatsRequest proto.InternalMessageInfo +func (m *StatsRequest) GetService() string { + if m != nil { + return m.Service + } + return "" +} + type StatsResponse struct { // unix timestamp Started uint64 `protobuf:"varint,1,opt,name=started,proto3" json:"started,omitempty"` @@ -142,7 +160,7 @@ func (m *StatsResponse) Reset() { *m = StatsResponse{} } func (m *StatsResponse) String() string { return proto.CompactTextString(m) } func (*StatsResponse) ProtoMessage() {} func (*StatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_8d9d361be58531fb, []int{3} + return fileDescriptor_7cb19b1a05a6e0a9, []int{3} } func (m *StatsResponse) XXX_Unmarshal(b []byte) error { @@ -200,14 +218,16 @@ func (m *StatsResponse) GetGc() uint64 { // LogRequest requests service logs type LogRequest struct { + // service to request logs for + Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` + // stream records continuously + Stream bool `protobuf:"varint,2,opt,name=stream,proto3" json:"stream,omitempty"` // count of records to request - Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + Count int64 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` // relative time in seconds // before the current time // from which to show logs - Since int64 `protobuf:"varint,2,opt,name=since,proto3" json:"since,omitempty"` - // stream records continuously - Stream bool `protobuf:"varint,3,opt,name=stream,proto3" json:"stream,omitempty"` + Since int64 `protobuf:"varint,4,opt,name=since,proto3" json:"since,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -217,7 +237,7 @@ func (m *LogRequest) Reset() { *m = LogRequest{} } func (m *LogRequest) String() string { return proto.CompactTextString(m) } func (*LogRequest) ProtoMessage() {} func (*LogRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_8d9d361be58531fb, []int{4} + return fileDescriptor_7cb19b1a05a6e0a9, []int{4} } func (m *LogRequest) XXX_Unmarshal(b []byte) error { @@ -238,6 +258,20 @@ func (m *LogRequest) XXX_DiscardUnknown() { var xxx_messageInfo_LogRequest proto.InternalMessageInfo +func (m *LogRequest) GetService() string { + if m != nil { + return m.Service + } + return "" +} + +func (m *LogRequest) GetStream() bool { + if m != nil { + return m.Stream + } + return false +} + func (m *LogRequest) GetCount() int64 { if m != nil { return m.Count @@ -252,13 +286,6 @@ func (m *LogRequest) GetSince() int64 { return 0 } -func (m *LogRequest) GetStream() bool { - if m != nil { - return m.Stream - } - return false -} - // Record is service log record type Record struct { // timestamp of log record @@ -276,7 +303,7 @@ func (m *Record) Reset() { *m = Record{} } func (m *Record) String() string { return proto.CompactTextString(m) } func (*Record) ProtoMessage() {} func (*Record) Descriptor() ([]byte, []int) { - return fileDescriptor_8d9d361be58531fb, []int{5} + return fileDescriptor_7cb19b1a05a6e0a9, []int{5} } func (m *Record) XXX_Unmarshal(b []byte) error { @@ -328,31 +355,35 @@ func init() { proto.RegisterMapType((map[string]string)(nil), "Record.MetadataEntry") } -func init() { proto.RegisterFile("debug.proto", fileDescriptor_8d9d361be58531fb) } - -var fileDescriptor_8d9d361be58531fb = []byte{ - // 364 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0x41, 0x6b, 0xdb, 0x30, - 0x1c, 0xc5, 0x63, 0x3b, 0x76, 0x92, 0x7f, 0x66, 0x67, 0x88, 0x6d, 0x18, 0xb3, 0x43, 0xd0, 0xc9, - 0x30, 0x10, 0x5b, 0x76, 0x19, 0xdb, 0x75, 0x85, 0x1e, 0x52, 0x28, 0xea, 0x27, 0x50, 0x6c, 0xe1, - 0x84, 0xc6, 0x96, 0x6b, 0xfd, 0x5d, 0xc8, 0xad, 0xd0, 0xaf, 0xd3, 0x0f, 0x59, 0x64, 0x29, 0x4d, - 0x0d, 0xbd, 0xf9, 0xf7, 0xe4, 0xff, 0x7b, 0x92, 0x9e, 0x60, 0x59, 0xca, 0x5d, 0x5f, 0xb1, 0xb6, - 0x53, 0xa8, 0xe8, 0x0a, 0xe2, 0x6b, 0x29, 0x8e, 0xb8, 0xe7, 0xf2, 0xa1, 0x97, 0x1a, 0x69, 0x0e, - 0xc9, 0x59, 0xd0, 0xad, 0x6a, 0xb4, 0x24, 0xdf, 0x20, 0xd2, 0x28, 0xb0, 0xd7, 0xa9, 0xb7, 0xf6, - 0xf2, 0x05, 0x77, 0x44, 0x13, 0xf8, 0x74, 0x87, 0x02, 0xf5, 0x79, 0xf2, 0xd9, 0x83, 0xd8, 0x09, - 0x6e, 0x32, 0x85, 0x99, 0x46, 0xd1, 0xa1, 0x2c, 0x87, 0xd1, 0x29, 0x3f, 0xa3, 0xf1, 0xec, 0x5b, - 0x3c, 0xd4, 0x32, 0xf5, 0x87, 0x05, 0x47, 0x46, 0xaf, 0x65, 0xad, 0xba, 0x53, 0x1a, 0x58, 0xdd, - 0x92, 0x71, 0xc2, 0x7d, 0x27, 0x45, 0xa9, 0xd3, 0xa9, 0x75, 0x72, 0x48, 0x12, 0xf0, 0xab, 0x22, - 0x0d, 0x07, 0xd1, 0xaf, 0x0a, 0x7a, 0x0b, 0xb0, 0x55, 0x95, 0xdb, 0x13, 0xf9, 0x02, 0x61, 0xa1, - 0xfa, 0x06, 0x87, 0xfc, 0x80, 0x5b, 0x30, 0xaa, 0x3e, 0x34, 0x85, 0x0d, 0x0f, 0xb8, 0x05, 0x7b, - 0xce, 0x4e, 0x8a, 0x7a, 0xc8, 0x9e, 0x73, 0x47, 0xf4, 0xc5, 0x83, 0x88, 0xcb, 0x42, 0x75, 0x25, - 0xf9, 0x0e, 0x0b, 0xb3, 0x4d, 0x8d, 0xa2, 0x6e, 0x9d, 0xe5, 0x45, 0x30, 0xb6, 0x8f, 0xe2, 0xd8, - 0x5b, 0xdb, 0x05, 0xb7, 0x40, 0x7e, 0xc1, 0xbc, 0x96, 0x28, 0x4a, 0x81, 0x22, 0x0d, 0xd6, 0x41, - 0xbe, 0xdc, 0x7c, 0x65, 0xd6, 0x8e, 0xdd, 0x38, 0xfd, 0xaa, 0xc1, 0xee, 0xc4, 0xdf, 0x7e, 0xcb, - 0xfe, 0x41, 0x3c, 0x5a, 0x22, 0x9f, 0x21, 0xb8, 0x97, 0x27, 0x77, 0xff, 0xe6, 0xf3, 0xe3, 0xac, - 0xbf, 0xfe, 0x1f, 0x6f, 0xf3, 0xe4, 0x41, 0xf8, 0xdf, 0x34, 0x4c, 0x7e, 0x40, 0x64, 0xab, 0x24, - 0x09, 0x1b, 0x95, 0x9c, 0xad, 0xd8, 0xb8, 0x63, 0x3a, 0x21, 0x39, 0x84, 0x43, 0x79, 0x24, 0x66, - 0xef, 0x5b, 0xcd, 0x12, 0x36, 0xea, 0x94, 0x4e, 0xc8, 0x1a, 0xa6, 0x5b, 0x55, 0x69, 0xb2, 0x64, - 0x97, 0x8b, 0xce, 0x66, 0xee, 0x4c, 0x74, 0xf2, 0xd3, 0xdb, 0x45, 0xc3, 0xdb, 0xfa, 0xfd, 0x1a, - 0x00, 0x00, 0xff, 0xff, 0xea, 0x2d, 0x15, 0xdb, 0x6a, 0x02, 0x00, 0x00, +func init() { + proto.RegisterFile("github.com/micro/go-micro/debug/proto/debug.proto", fileDescriptor_7cb19b1a05a6e0a9) +} + +var fileDescriptor_7cb19b1a05a6e0a9 = []byte{ + // 400 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xcd, 0x8a, 0x13, 0x41, + 0x10, 0xc7, 0x33, 0x99, 0x24, 0xbb, 0xa9, 0x35, 0x51, 0x1a, 0x95, 0x21, 0x78, 0x08, 0x7d, 0x1a, + 0x11, 0x3b, 0xee, 0x7a, 0x11, 0xbd, 0x2a, 0x78, 0x58, 0x2f, 0xed, 0x13, 0x74, 0x7a, 0x8a, 0xc9, + 0xe8, 0x76, 0x3a, 0x76, 0xd7, 0x2c, 0xe4, 0x26, 0xf8, 0x3a, 0x3e, 0xa4, 0xf4, 0x47, 0x5c, 0x07, + 0x84, 0xdc, 0xea, 0xf7, 0xef, 0x7f, 0xd7, 0x07, 0x55, 0x70, 0xdd, 0x76, 0xb4, 0xeb, 0xb7, 0x42, + 0x5b, 0xb3, 0x31, 0x9d, 0x76, 0x76, 0xd3, 0xda, 0xd7, 0x29, 0x68, 0x70, 0xdb, 0xb7, 0x9b, 0x83, + 0xb3, 0x94, 0x63, 0x11, 0x63, 0xfe, 0x12, 0x16, 0x9f, 0x51, 0xdd, 0xd1, 0x4e, 0xe2, 0x8f, 0x1e, + 0x3d, 0xb1, 0x0a, 0x2e, 0x3c, 0xba, 0xfb, 0x4e, 0x63, 0x55, 0xac, 0x8b, 0x7a, 0x2e, 0x4f, 0xc8, + 0x6b, 0x58, 0x9e, 0xac, 0xfe, 0x60, 0xf7, 0x1e, 0xd9, 0x73, 0x98, 0x79, 0x52, 0xd4, 0xfb, 0x6c, + 0xcd, 0xc4, 0x6b, 0x78, 0xf4, 0x95, 0x14, 0xf9, 0xf3, 0x39, 0x7f, 0x15, 0xb0, 0xc8, 0xd6, 0x9c, + 0x33, 0x78, 0x49, 0x39, 0xc2, 0x26, 0x7a, 0x27, 0xf2, 0x84, 0xa1, 0x5a, 0x7f, 0xa0, 0xce, 0x60, + 0x35, 0x8e, 0x0f, 0x99, 0x82, 0x6e, 0xd0, 0x58, 0x77, 0xac, 0xca, 0xa4, 0x27, 0x0a, 0x99, 0x68, + 0xe7, 0x50, 0x35, 0xbe, 0x9a, 0xa4, 0x4c, 0x19, 0xd9, 0x12, 0xc6, 0xad, 0xae, 0xa6, 0x51, 0x1c, + 0xb7, 0x9a, 0x7f, 0x03, 0xb8, 0xb5, 0xed, 0xd9, 0x6e, 0xd3, 0xbc, 0x0e, 0x95, 0x89, 0x1d, 0x5c, + 0xca, 0x4c, 0xec, 0x29, 0x4c, 0xb5, 0xed, 0xf7, 0x14, 0x1b, 0x28, 0x65, 0x82, 0xa0, 0xfa, 0x6e, + 0xaf, 0x31, 0x56, 0x2f, 0x65, 0x02, 0xfe, 0xbb, 0x80, 0x99, 0x44, 0x6d, 0x5d, 0xc3, 0x5e, 0xc0, + 0x3c, 0x0c, 0xe0, 0x49, 0x99, 0x43, 0x2c, 0x55, 0xca, 0x07, 0x21, 0x7c, 0xbf, 0x57, 0x77, 0x7d, + 0x9a, 0x76, 0x2e, 0x13, 0xb0, 0x6b, 0xb8, 0x34, 0x48, 0xaa, 0x51, 0xa4, 0xaa, 0x72, 0x5d, 0xd6, + 0x57, 0x37, 0xcf, 0x44, 0x4a, 0x27, 0xbe, 0x64, 0xfd, 0xd3, 0x9e, 0xdc, 0x51, 0xfe, 0xb5, 0xad, + 0x3e, 0xc0, 0x62, 0xf0, 0xc4, 0x9e, 0x40, 0xf9, 0x1d, 0x8f, 0x79, 0xb8, 0x10, 0xfe, 0xbf, 0xd6, + 0xfb, 0xf1, 0xbb, 0xe2, 0xe6, 0x67, 0x01, 0xd3, 0x8f, 0xe1, 0x5e, 0xd8, 0x2b, 0x98, 0xa5, 0xf5, + 0xb3, 0xa5, 0x18, 0x9c, 0xcc, 0xea, 0xb1, 0x18, 0xde, 0x05, 0x1f, 0xb1, 0x1a, 0xa6, 0x71, 0xad, + 0x6c, 0x21, 0xfe, 0xbd, 0x84, 0xd5, 0x52, 0x0c, 0xb6, 0xcd, 0x47, 0x6c, 0x0d, 0x93, 0x5b, 0xdb, + 0x7a, 0x76, 0x25, 0x1e, 0x56, 0xb0, 0xba, 0xc8, 0x33, 0xf1, 0xd1, 0x9b, 0x62, 0x3b, 0x8b, 0x97, + 0xfa, 0xf6, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x35, 0x1e, 0x9c, 0xa7, 0xde, 0x02, 0x00, 0x00, } diff --git a/debug/proto/debug.pb.micro.go b/debug/proto/debug.pb.micro.go index 3381c2af..6f3ffb48 100644 --- a/debug/proto/debug.pb.micro.go +++ b/debug/proto/debug.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: debug.proto +// source: github.com/micro/go-micro/debug/proto/debug.proto package debug diff --git a/debug/proto/debug.proto b/debug/proto/debug.proto index a666068a..54a6fb63 100644 --- a/debug/proto/debug.proto +++ b/debug/proto/debug.proto @@ -6,14 +6,20 @@ service Debug { rpc Logs(LogRequest) returns (stream Record) {}; } -message HealthRequest {} +message HealthRequest { + // optional service name + string service = 1; +} message HealthResponse { // default: ok string status = 1; } -message StatsRequest {} +message StatsRequest { + // optional service name + string service = 1; +} message StatsResponse { // unix timestamp @@ -30,14 +36,16 @@ message StatsResponse { // LogRequest requests service logs message LogRequest { + // service to request logs for + string service = 1; + // stream records continuously + bool stream = 2; // count of records to request - int64 count = 1; + int64 count = 3; // relative time in seconds // before the current time // from which to show logs - int64 since = 2; - // stream records continuously - bool stream = 3; + int64 since = 4; } // Record is service log record From 24efbe6a412c166dcfc745af5edf82d60af9dbbc Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 4 Dec 2019 12:27:30 +0000 Subject: [PATCH 306/344] Move debug handler to service dir --- debug/{ => service}/handler/debug.go | 2 +- debug/{ => service}/proto/debug.pb.go | 0 debug/{ => service}/proto/debug.pb.micro.go | 0 debug/{ => service}/proto/debug.proto | 0 debug/service/service.go | 2 +- function_test.go | 2 +- monitor/default.go | 2 +- service.go | 2 +- service_test.go | 2 +- util/mux/mux.go | 2 +- 10 files changed, 7 insertions(+), 7 deletions(-) rename debug/{ => service}/handler/debug.go (97%) rename debug/{ => service}/proto/debug.pb.go (100%) rename debug/{ => service}/proto/debug.pb.micro.go (100%) rename debug/{ => service}/proto/debug.proto (100%) diff --git a/debug/handler/debug.go b/debug/service/handler/debug.go similarity index 97% rename from debug/handler/debug.go rename to debug/service/handler/debug.go index 002dccba..27938d76 100644 --- a/debug/handler/debug.go +++ b/debug/service/handler/debug.go @@ -7,7 +7,7 @@ import ( "time" "github.com/micro/go-micro/debug/log" - proto "github.com/micro/go-micro/debug/proto" + proto "github.com/micro/go-micro/debug/service/proto" "github.com/micro/go-micro/server" ) diff --git a/debug/proto/debug.pb.go b/debug/service/proto/debug.pb.go similarity index 100% rename from debug/proto/debug.pb.go rename to debug/service/proto/debug.pb.go diff --git a/debug/proto/debug.pb.micro.go b/debug/service/proto/debug.pb.micro.go similarity index 100% rename from debug/proto/debug.pb.micro.go rename to debug/service/proto/debug.pb.micro.go diff --git a/debug/proto/debug.proto b/debug/service/proto/debug.proto similarity index 100% rename from debug/proto/debug.proto rename to debug/service/proto/debug.proto diff --git a/debug/service/service.go b/debug/service/service.go index a30d2836..ab2a26c1 100644 --- a/debug/service/service.go +++ b/debug/service/service.go @@ -8,7 +8,7 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/debug/log" - pb "github.com/micro/go-micro/debug/proto" + pb "github.com/micro/go-micro/debug/service/proto" ) // Debug provides debug service client diff --git a/function_test.go b/function_test.go index c53e9cdc..51d80fc9 100644 --- a/function_test.go +++ b/function_test.go @@ -5,7 +5,7 @@ import ( "sync" "testing" - proto "github.com/micro/go-micro/debug/proto" + proto "github.com/micro/go-micro/debug/service/proto" "github.com/micro/go-micro/registry/memory" "github.com/micro/go-micro/util/test" ) diff --git a/monitor/default.go b/monitor/default.go index 4aec0d47..557ca234 100644 --- a/monitor/default.go +++ b/monitor/default.go @@ -7,7 +7,7 @@ import ( "time" "github.com/micro/go-micro/client" - pb "github.com/micro/go-micro/debug/proto" + pb "github.com/micro/go-micro/debug/service/proto" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/cache" ) diff --git a/service.go b/service.go index 3058a3b2..915e6512 100644 --- a/service.go +++ b/service.go @@ -9,7 +9,7 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/config/cmd" - "github.com/micro/go-micro/debug/handler" + "github.com/micro/go-micro/debug/service/handler" "github.com/micro/go-micro/debug/profile" "github.com/micro/go-micro/debug/profile/pprof" "github.com/micro/go-micro/plugin" diff --git a/service_test.go b/service_test.go index f7abb15f..79b4872c 100644 --- a/service_test.go +++ b/service_test.go @@ -8,7 +8,7 @@ import ( glog "github.com/go-log/log" "github.com/micro/go-micro/client" - proto "github.com/micro/go-micro/debug/proto" + proto "github.com/micro/go-micro/debug/service/proto" "github.com/micro/go-micro/registry/memory" "github.com/micro/go-micro/util/log" "github.com/micro/go-micro/util/test" diff --git a/util/mux/mux.go b/util/mux/mux.go index 741dafcd..e10368ec 100644 --- a/util/mux/mux.go +++ b/util/mux/mux.go @@ -5,7 +5,7 @@ import ( "context" "sync" - "github.com/micro/go-micro/debug/handler" + "github.com/micro/go-micro/debug/service/handler" "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/server" ) From 898848795bcdac138c3e5388324685babede3bb7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 4 Dec 2019 12:28:16 +0000 Subject: [PATCH 307/344] tab indent --- debug/service/proto/debug.proto | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/debug/service/proto/debug.proto b/debug/service/proto/debug.proto index 54a6fb63..fc08850d 100644 --- a/debug/service/proto/debug.proto +++ b/debug/service/proto/debug.proto @@ -38,14 +38,14 @@ message StatsResponse { message LogRequest { // service to request logs for string service = 1; - // stream records continuously - bool stream = 2; - // count of records to request - int64 count = 3; - // relative time in seconds - // before the current time - // from which to show logs - int64 since = 4; + // stream records continuously + bool stream = 2; + // count of records to request + int64 count = 3; + // relative time in seconds + // before the current time + // from which to show logs + int64 since = 4; } // Record is service log record From 78647c7027ffce5b95fc4e4c4e19235a944e2e02 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 4 Dec 2019 23:51:07 +0000 Subject: [PATCH 308/344] add timestamp to stats --- debug/service/handler/debug.go | 1 + debug/service/proto/debug.pb.go | 89 +++++++++++++++------------ debug/service/proto/debug.pb.micro.go | 2 +- debug/service/proto/debug.proto | 12 ++-- debug/stats/stats.go | 8 ++- 5 files changed, 63 insertions(+), 49 deletions(-) diff --git a/debug/service/handler/debug.go b/debug/service/handler/debug.go index 27938d76..757db1cc 100644 --- a/debug/service/handler/debug.go +++ b/debug/service/handler/debug.go @@ -38,6 +38,7 @@ func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.S var mstat runtime.MemStats runtime.ReadMemStats(&mstat) + rsp.Timestamp = uint64(time.Now().Unix()) rsp.Started = uint64(d.started) rsp.Uptime = uint64(time.Now().Unix() - d.started) rsp.Memory = mstat.Alloc diff --git a/debug/service/proto/debug.pb.go b/debug/service/proto/debug.pb.go index 0ee2536f..7d4dfd42 100644 --- a/debug/service/proto/debug.pb.go +++ b/debug/service/proto/debug.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/micro/go-micro/debug/proto/debug.proto +// source: micro/go-micro/debug/service/proto/debug.proto package debug @@ -32,7 +32,7 @@ func (m *HealthRequest) Reset() { *m = HealthRequest{} } func (m *HealthRequest) String() string { return proto.CompactTextString(m) } func (*HealthRequest) ProtoMessage() {} func (*HealthRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{0} + return fileDescriptor_dea322649cde1ef2, []int{0} } func (m *HealthRequest) XXX_Unmarshal(b []byte) error { @@ -72,7 +72,7 @@ func (m *HealthResponse) Reset() { *m = HealthResponse{} } func (m *HealthResponse) String() string { return proto.CompactTextString(m) } func (*HealthResponse) ProtoMessage() {} func (*HealthResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{1} + return fileDescriptor_dea322649cde1ef2, []int{1} } func (m *HealthResponse) XXX_Unmarshal(b []byte) error { @@ -112,7 +112,7 @@ func (m *StatsRequest) Reset() { *m = StatsRequest{} } func (m *StatsRequest) String() string { return proto.CompactTextString(m) } func (*StatsRequest) ProtoMessage() {} func (*StatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{2} + return fileDescriptor_dea322649cde1ef2, []int{2} } func (m *StatsRequest) XXX_Unmarshal(b []byte) error { @@ -141,16 +141,18 @@ func (m *StatsRequest) GetService() string { } type StatsResponse struct { + // timestamp of recording + Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // unix timestamp - Started uint64 `protobuf:"varint,1,opt,name=started,proto3" json:"started,omitempty"` + Started uint64 `protobuf:"varint,2,opt,name=started,proto3" json:"started,omitempty"` // in seconds - Uptime uint64 `protobuf:"varint,2,opt,name=uptime,proto3" json:"uptime,omitempty"` + Uptime uint64 `protobuf:"varint,3,opt,name=uptime,proto3" json:"uptime,omitempty"` // in bytes - Memory uint64 `protobuf:"varint,3,opt,name=memory,proto3" json:"memory,omitempty"` + Memory uint64 `protobuf:"varint,4,opt,name=memory,proto3" json:"memory,omitempty"` // num threads - Threads uint64 `protobuf:"varint,4,opt,name=threads,proto3" json:"threads,omitempty"` + Threads uint64 `protobuf:"varint,5,opt,name=threads,proto3" json:"threads,omitempty"` // total gc in nanoseconds - Gc uint64 `protobuf:"varint,5,opt,name=gc,proto3" json:"gc,omitempty"` + Gc uint64 `protobuf:"varint,6,opt,name=gc,proto3" json:"gc,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -160,7 +162,7 @@ func (m *StatsResponse) Reset() { *m = StatsResponse{} } func (m *StatsResponse) String() string { return proto.CompactTextString(m) } func (*StatsResponse) ProtoMessage() {} func (*StatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{3} + return fileDescriptor_dea322649cde1ef2, []int{3} } func (m *StatsResponse) XXX_Unmarshal(b []byte) error { @@ -181,6 +183,13 @@ func (m *StatsResponse) XXX_DiscardUnknown() { var xxx_messageInfo_StatsResponse proto.InternalMessageInfo +func (m *StatsResponse) GetTimestamp() uint64 { + if m != nil { + return m.Timestamp + } + return 0 +} + func (m *StatsResponse) GetStarted() uint64 { if m != nil { return m.Started @@ -237,7 +246,7 @@ func (m *LogRequest) Reset() { *m = LogRequest{} } func (m *LogRequest) String() string { return proto.CompactTextString(m) } func (*LogRequest) ProtoMessage() {} func (*LogRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{4} + return fileDescriptor_dea322649cde1ef2, []int{4} } func (m *LogRequest) XXX_Unmarshal(b []byte) error { @@ -303,7 +312,7 @@ func (m *Record) Reset() { *m = Record{} } func (m *Record) String() string { return proto.CompactTextString(m) } func (*Record) ProtoMessage() {} func (*Record) Descriptor() ([]byte, []int) { - return fileDescriptor_7cb19b1a05a6e0a9, []int{5} + return fileDescriptor_dea322649cde1ef2, []int{5} } func (m *Record) XXX_Unmarshal(b []byte) error { @@ -356,34 +365,34 @@ func init() { } func init() { - proto.RegisterFile("github.com/micro/go-micro/debug/proto/debug.proto", fileDescriptor_7cb19b1a05a6e0a9) + proto.RegisterFile("micro/go-micro/debug/service/proto/debug.proto", fileDescriptor_dea322649cde1ef2) } -var fileDescriptor_7cb19b1a05a6e0a9 = []byte{ - // 400 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xcd, 0x8a, 0x13, 0x41, - 0x10, 0xc7, 0x33, 0x99, 0x24, 0xbb, 0xa9, 0x35, 0x51, 0x1a, 0x95, 0x21, 0x78, 0x08, 0x7d, 0x1a, - 0x11, 0x3b, 0xee, 0x7a, 0x11, 0xbd, 0x2a, 0x78, 0x58, 0x2f, 0xed, 0x13, 0x74, 0x7a, 0x8a, 0xc9, - 0xe8, 0x76, 0x3a, 0x76, 0xd7, 0x2c, 0xe4, 0x26, 0xf8, 0x3a, 0x3e, 0xa4, 0xf4, 0x47, 0x5c, 0x07, - 0x84, 0xdc, 0xea, 0xf7, 0xef, 0x7f, 0xd7, 0x07, 0x55, 0x70, 0xdd, 0x76, 0xb4, 0xeb, 0xb7, 0x42, - 0x5b, 0xb3, 0x31, 0x9d, 0x76, 0x76, 0xd3, 0xda, 0xd7, 0x29, 0x68, 0x70, 0xdb, 0xb7, 0x9b, 0x83, - 0xb3, 0x94, 0x63, 0x11, 0x63, 0xfe, 0x12, 0x16, 0x9f, 0x51, 0xdd, 0xd1, 0x4e, 0xe2, 0x8f, 0x1e, - 0x3d, 0xb1, 0x0a, 0x2e, 0x3c, 0xba, 0xfb, 0x4e, 0x63, 0x55, 0xac, 0x8b, 0x7a, 0x2e, 0x4f, 0xc8, - 0x6b, 0x58, 0x9e, 0xac, 0xfe, 0x60, 0xf7, 0x1e, 0xd9, 0x73, 0x98, 0x79, 0x52, 0xd4, 0xfb, 0x6c, - 0xcd, 0xc4, 0x6b, 0x78, 0xf4, 0x95, 0x14, 0xf9, 0xf3, 0x39, 0x7f, 0x15, 0xb0, 0xc8, 0xd6, 0x9c, - 0x33, 0x78, 0x49, 0x39, 0xc2, 0x26, 0x7a, 0x27, 0xf2, 0x84, 0xa1, 0x5a, 0x7f, 0xa0, 0xce, 0x60, - 0x35, 0x8e, 0x0f, 0x99, 0x82, 0x6e, 0xd0, 0x58, 0x77, 0xac, 0xca, 0xa4, 0x27, 0x0a, 0x99, 0x68, - 0xe7, 0x50, 0x35, 0xbe, 0x9a, 0xa4, 0x4c, 0x19, 0xd9, 0x12, 0xc6, 0xad, 0xae, 0xa6, 0x51, 0x1c, - 0xb7, 0x9a, 0x7f, 0x03, 0xb8, 0xb5, 0xed, 0xd9, 0x6e, 0xd3, 0xbc, 0x0e, 0x95, 0x89, 0x1d, 0x5c, - 0xca, 0x4c, 0xec, 0x29, 0x4c, 0xb5, 0xed, 0xf7, 0x14, 0x1b, 0x28, 0x65, 0x82, 0xa0, 0xfa, 0x6e, - 0xaf, 0x31, 0x56, 0x2f, 0x65, 0x02, 0xfe, 0xbb, 0x80, 0x99, 0x44, 0x6d, 0x5d, 0xc3, 0x5e, 0xc0, - 0x3c, 0x0c, 0xe0, 0x49, 0x99, 0x43, 0x2c, 0x55, 0xca, 0x07, 0x21, 0x7c, 0xbf, 0x57, 0x77, 0x7d, - 0x9a, 0x76, 0x2e, 0x13, 0xb0, 0x6b, 0xb8, 0x34, 0x48, 0xaa, 0x51, 0xa4, 0xaa, 0x72, 0x5d, 0xd6, - 0x57, 0x37, 0xcf, 0x44, 0x4a, 0x27, 0xbe, 0x64, 0xfd, 0xd3, 0x9e, 0xdc, 0x51, 0xfe, 0xb5, 0xad, - 0x3e, 0xc0, 0x62, 0xf0, 0xc4, 0x9e, 0x40, 0xf9, 0x1d, 0x8f, 0x79, 0xb8, 0x10, 0xfe, 0xbf, 0xd6, - 0xfb, 0xf1, 0xbb, 0xe2, 0xe6, 0x67, 0x01, 0xd3, 0x8f, 0xe1, 0x5e, 0xd8, 0x2b, 0x98, 0xa5, 0xf5, - 0xb3, 0xa5, 0x18, 0x9c, 0xcc, 0xea, 0xb1, 0x18, 0xde, 0x05, 0x1f, 0xb1, 0x1a, 0xa6, 0x71, 0xad, - 0x6c, 0x21, 0xfe, 0xbd, 0x84, 0xd5, 0x52, 0x0c, 0xb6, 0xcd, 0x47, 0x6c, 0x0d, 0x93, 0x5b, 0xdb, - 0x7a, 0x76, 0x25, 0x1e, 0x56, 0xb0, 0xba, 0xc8, 0x33, 0xf1, 0xd1, 0x9b, 0x62, 0x3b, 0x8b, 0x97, - 0xfa, 0xf6, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x35, 0x1e, 0x9c, 0xa7, 0xde, 0x02, 0x00, 0x00, +var fileDescriptor_dea322649cde1ef2 = []byte{ + // 399 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0xc1, 0x6e, 0xd4, 0x30, + 0x10, 0xdd, 0x6c, 0x36, 0x69, 0x77, 0xca, 0x2e, 0xc8, 0x2a, 0xc8, 0x8a, 0x38, 0xac, 0x7c, 0x0a, + 0x42, 0x78, 0xa1, 0x5c, 0x10, 0x5c, 0x41, 0xe2, 0x50, 0x2e, 0xe6, 0x0b, 0xdc, 0x64, 0x94, 0x06, + 0x9a, 0x38, 0xd8, 0x93, 0x4a, 0x7b, 0xe3, 0x57, 0xb8, 0xf3, 0x91, 0x28, 0xb6, 0x97, 0x36, 0x02, + 0xa9, 0xb7, 0x79, 0x6f, 0x9e, 0x9e, 0x67, 0xc6, 0x0f, 0x64, 0xd7, 0x56, 0xd6, 0xec, 0x1b, 0xf3, + 0x2a, 0x14, 0x35, 0x5e, 0x8d, 0xcd, 0xde, 0xa1, 0xbd, 0x6d, 0x2b, 0xdc, 0x0f, 0xd6, 0x50, 0xe4, + 0xa4, 0xaf, 0xc5, 0x0b, 0xd8, 0x7c, 0x46, 0x7d, 0x43, 0xd7, 0x0a, 0x7f, 0x8c, 0xe8, 0x88, 0x71, + 0x38, 0x89, 0x6a, 0x9e, 0xec, 0x92, 0x72, 0xad, 0x8e, 0x50, 0x94, 0xb0, 0x3d, 0x4a, 0xdd, 0x60, + 0x7a, 0x87, 0xec, 0x19, 0xe4, 0x8e, 0x34, 0x8d, 0x2e, 0x4a, 0x23, 0x12, 0x25, 0x3c, 0xfa, 0x4a, + 0x9a, 0xdc, 0xc3, 0x9e, 0xbf, 0x12, 0xd8, 0x44, 0x69, 0xf4, 0x7c, 0x0e, 0x6b, 0x6a, 0x3b, 0x74, + 0xa4, 0xbb, 0xc1, 0xab, 0x57, 0xea, 0x8e, 0xf0, 0x4e, 0xa4, 0x2d, 0x61, 0xcd, 0x97, 0xbe, 0x77, + 0x84, 0xd3, 0x2c, 0xe3, 0x30, 0x09, 0x79, 0xea, 0x1b, 0x11, 0x4d, 0x7c, 0x87, 0x9d, 0xb1, 0x07, + 0xbe, 0x0a, 0x7c, 0x40, 0x93, 0x13, 0x5d, 0x5b, 0xd4, 0xb5, 0xe3, 0x59, 0x70, 0x8a, 0x90, 0x6d, + 0x61, 0xd9, 0x54, 0x3c, 0xf7, 0xe4, 0xb2, 0xa9, 0xc4, 0x37, 0x80, 0x4b, 0xd3, 0x3c, 0xb8, 0x4b, + 0xb8, 0x86, 0x45, 0xdd, 0xf9, 0xd1, 0x4e, 0x55, 0x44, 0xec, 0x1c, 0xb2, 0xca, 0x8c, 0x3d, 0xf9, + 0xc1, 0x52, 0x15, 0xc0, 0xc4, 0xba, 0xb6, 0xaf, 0xd0, 0x8f, 0x95, 0xaa, 0x00, 0xc4, 0xef, 0x04, + 0x72, 0x85, 0x95, 0xb1, 0xf5, 0xbf, 0x87, 0x48, 0xef, 0x1f, 0xe2, 0x1c, 0xb2, 0x5b, 0x7d, 0x33, + 0xa2, 0x7f, 0x6b, 0xad, 0x02, 0x60, 0x6f, 0xe0, 0xb4, 0x43, 0xd2, 0xb5, 0x26, 0xcd, 0xd3, 0x5d, + 0x5a, 0x9e, 0x5d, 0x3c, 0x95, 0xc1, 0x4e, 0x7e, 0x89, 0xfc, 0xa7, 0x9e, 0xec, 0x41, 0xfd, 0x95, + 0x15, 0x1f, 0x60, 0x33, 0x6b, 0xb1, 0x27, 0x90, 0x7e, 0xc7, 0x43, 0x5c, 0x6e, 0x2a, 0xff, 0xff, + 0xd6, 0xfb, 0xe5, 0xbb, 0xe4, 0xe2, 0x67, 0x02, 0xd9, 0xc7, 0x29, 0x4d, 0xec, 0x25, 0xe4, 0x21, + 0x1c, 0x6c, 0x2b, 0x67, 0x81, 0x2a, 0x1e, 0xcb, 0x79, 0x6a, 0xc4, 0x82, 0x95, 0x90, 0xf9, 0x4f, + 0x67, 0x1b, 0x79, 0x3f, 0x27, 0xc5, 0x56, 0xce, 0xb2, 0x20, 0x16, 0x6c, 0x07, 0xab, 0x4b, 0xd3, + 0x38, 0x76, 0x26, 0xef, 0xbe, 0xa0, 0x38, 0x89, 0x3b, 0x89, 0xc5, 0xeb, 0xe4, 0x2a, 0xf7, 0x39, + 0x7e, 0xfb, 0x27, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xac, 0xb1, 0x40, 0xf9, 0x02, 0x00, 0x00, } diff --git a/debug/service/proto/debug.pb.micro.go b/debug/service/proto/debug.pb.micro.go index 6f3ffb48..f1789b8d 100644 --- a/debug/service/proto/debug.pb.micro.go +++ b/debug/service/proto/debug.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: github.com/micro/go-micro/debug/proto/debug.proto +// source: micro/go-micro/debug/service/proto/debug.proto package debug diff --git a/debug/service/proto/debug.proto b/debug/service/proto/debug.proto index fc08850d..a6cba776 100644 --- a/debug/service/proto/debug.proto +++ b/debug/service/proto/debug.proto @@ -22,16 +22,18 @@ message StatsRequest { } message StatsResponse { + // timestamp of recording + uint64 timestamp = 1; // unix timestamp - uint64 started = 1; + uint64 started = 2; // in seconds - uint64 uptime = 2; + uint64 uptime = 3; // in bytes - uint64 memory = 3; + uint64 memory = 4; // num threads - uint64 threads = 4; + uint64 threads = 5; // total gc in nanoseconds - uint64 gc = 5; + uint64 gc = 6; } // LogRequest requests service logs diff --git a/debug/stats/stats.go b/debug/stats/stats.go index 16e9faf3..c24bfc42 100644 --- a/debug/stats/stats.go +++ b/debug/stats/stats.go @@ -3,17 +3,19 @@ package stats // Stats provides stats interface type Stats interface { - // Read a stat snapshot - Read() (*Stat, error) + // Read stat snapshot + Read() ([]*Stat, error) // Write a stat snapshot Write(*Stat) error } // A runtime stat type Stat struct { + // Timestamp of recording + Timestamp int64 // Start time as unix timestamp Started int64 - // Uptime in nanoseconds + // Uptime in seconds Uptime int64 // Memory usage in bytes Memory uint64 From fe46e7a9e9c3414ce34e975891508022cf25aed3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 4 Dec 2019 23:58:29 +0000 Subject: [PATCH 309/344] Logs to Log --- debug/service/handler/debug.go | 2 +- debug/service/proto/debug.pb.go | 48 +++++++++++++-------------- debug/service/proto/debug.pb.micro.go | 40 +++++++++++----------- debug/service/proto/debug.proto | 2 +- debug/service/service.go | 4 +-- 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/debug/service/handler/debug.go b/debug/service/handler/debug.go index 757db1cc..ee24b27a 100644 --- a/debug/service/handler/debug.go +++ b/debug/service/handler/debug.go @@ -47,7 +47,7 @@ func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.S return nil } -func (d *Debug) Logs(ctx context.Context, stream server.Stream) error { +func (d *Debug) Log(ctx context.Context, stream server.Stream) error { req := new(proto.LogRequest) if err := stream.Recv(req); err != nil { return err diff --git a/debug/service/proto/debug.pb.go b/debug/service/proto/debug.pb.go index 7d4dfd42..f76bbba3 100644 --- a/debug/service/proto/debug.pb.go +++ b/debug/service/proto/debug.pb.go @@ -371,28 +371,28 @@ func init() { var fileDescriptor_dea322649cde1ef2 = []byte{ // 399 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0xc1, 0x6e, 0xd4, 0x30, - 0x10, 0xdd, 0x6c, 0x36, 0x69, 0x77, 0xca, 0x2e, 0xc8, 0x2a, 0xc8, 0x8a, 0x38, 0xac, 0x7c, 0x0a, - 0x42, 0x78, 0xa1, 0x5c, 0x10, 0x5c, 0x41, 0xe2, 0x50, 0x2e, 0xe6, 0x0b, 0xdc, 0x64, 0x94, 0x06, - 0x9a, 0x38, 0xd8, 0x93, 0x4a, 0x7b, 0xe3, 0x57, 0xb8, 0xf3, 0x91, 0x28, 0xb6, 0x97, 0x36, 0x02, - 0xa9, 0xb7, 0x79, 0x6f, 0x9e, 0x9e, 0x67, 0xc6, 0x0f, 0x64, 0xd7, 0x56, 0xd6, 0xec, 0x1b, 0xf3, - 0x2a, 0x14, 0x35, 0x5e, 0x8d, 0xcd, 0xde, 0xa1, 0xbd, 0x6d, 0x2b, 0xdc, 0x0f, 0xd6, 0x50, 0xe4, - 0xa4, 0xaf, 0xc5, 0x0b, 0xd8, 0x7c, 0x46, 0x7d, 0x43, 0xd7, 0x0a, 0x7f, 0x8c, 0xe8, 0x88, 0x71, - 0x38, 0x89, 0x6a, 0x9e, 0xec, 0x92, 0x72, 0xad, 0x8e, 0x50, 0x94, 0xb0, 0x3d, 0x4a, 0xdd, 0x60, - 0x7a, 0x87, 0xec, 0x19, 0xe4, 0x8e, 0x34, 0x8d, 0x2e, 0x4a, 0x23, 0x12, 0x25, 0x3c, 0xfa, 0x4a, - 0x9a, 0xdc, 0xc3, 0x9e, 0xbf, 0x12, 0xd8, 0x44, 0x69, 0xf4, 0x7c, 0x0e, 0x6b, 0x6a, 0x3b, 0x74, - 0xa4, 0xbb, 0xc1, 0xab, 0x57, 0xea, 0x8e, 0xf0, 0x4e, 0xa4, 0x2d, 0x61, 0xcd, 0x97, 0xbe, 0x77, - 0x84, 0xd3, 0x2c, 0xe3, 0x30, 0x09, 0x79, 0xea, 0x1b, 0x11, 0x4d, 0x7c, 0x87, 0x9d, 0xb1, 0x07, - 0xbe, 0x0a, 0x7c, 0x40, 0x93, 0x13, 0x5d, 0x5b, 0xd4, 0xb5, 0xe3, 0x59, 0x70, 0x8a, 0x90, 0x6d, - 0x61, 0xd9, 0x54, 0x3c, 0xf7, 0xe4, 0xb2, 0xa9, 0xc4, 0x37, 0x80, 0x4b, 0xd3, 0x3c, 0xb8, 0x4b, - 0xb8, 0x86, 0x45, 0xdd, 0xf9, 0xd1, 0x4e, 0x55, 0x44, 0xec, 0x1c, 0xb2, 0xca, 0x8c, 0x3d, 0xf9, - 0xc1, 0x52, 0x15, 0xc0, 0xc4, 0xba, 0xb6, 0xaf, 0xd0, 0x8f, 0x95, 0xaa, 0x00, 0xc4, 0xef, 0x04, - 0x72, 0x85, 0x95, 0xb1, 0xf5, 0xbf, 0x87, 0x48, 0xef, 0x1f, 0xe2, 0x1c, 0xb2, 0x5b, 0x7d, 0x33, - 0xa2, 0x7f, 0x6b, 0xad, 0x02, 0x60, 0x6f, 0xe0, 0xb4, 0x43, 0xd2, 0xb5, 0x26, 0xcd, 0xd3, 0x5d, - 0x5a, 0x9e, 0x5d, 0x3c, 0x95, 0xc1, 0x4e, 0x7e, 0x89, 0xfc, 0xa7, 0x9e, 0xec, 0x41, 0xfd, 0x95, - 0x15, 0x1f, 0x60, 0x33, 0x6b, 0xb1, 0x27, 0x90, 0x7e, 0xc7, 0x43, 0x5c, 0x6e, 0x2a, 0xff, 0xff, - 0xd6, 0xfb, 0xe5, 0xbb, 0xe4, 0xe2, 0x67, 0x02, 0xd9, 0xc7, 0x29, 0x4d, 0xec, 0x25, 0xe4, 0x21, - 0x1c, 0x6c, 0x2b, 0x67, 0x81, 0x2a, 0x1e, 0xcb, 0x79, 0x6a, 0xc4, 0x82, 0x95, 0x90, 0xf9, 0x4f, - 0x67, 0x1b, 0x79, 0x3f, 0x27, 0xc5, 0x56, 0xce, 0xb2, 0x20, 0x16, 0x6c, 0x07, 0xab, 0x4b, 0xd3, - 0x38, 0x76, 0x26, 0xef, 0xbe, 0xa0, 0x38, 0x89, 0x3b, 0x89, 0xc5, 0xeb, 0xe4, 0x2a, 0xf7, 0x39, - 0x7e, 0xfb, 0x27, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xac, 0xb1, 0x40, 0xf9, 0x02, 0x00, 0x00, + 0x10, 0xdd, 0xac, 0x9b, 0xb4, 0x3b, 0x65, 0x17, 0x64, 0x15, 0x64, 0xad, 0x90, 0xa8, 0x7c, 0x0a, + 0x42, 0x78, 0xa1, 0x5c, 0x10, 0x5c, 0x41, 0xe2, 0x50, 0x2e, 0xe6, 0x0b, 0xdc, 0x64, 0x94, 0x2e, + 0x34, 0x71, 0xb0, 0x27, 0x95, 0xf6, 0xc4, 0xb7, 0x70, 0xe7, 0x23, 0x51, 0x6c, 0x2f, 0x6d, 0x44, + 0xa5, 0xbd, 0xcd, 0x7b, 0xf3, 0xf4, 0x3c, 0x33, 0x7e, 0xa0, 0xda, 0x6d, 0xe5, 0xec, 0xa6, 0xb1, + 0xaf, 0x63, 0x51, 0xe3, 0xd5, 0xd0, 0x6c, 0x3c, 0xba, 0xdb, 0x6d, 0x85, 0x9b, 0xde, 0x59, 0x4a, + 0x9c, 0x0a, 0xb5, 0x7c, 0x09, 0xcb, 0x2f, 0x68, 0x6e, 0xe8, 0x5a, 0xe3, 0xcf, 0x01, 0x3d, 0x71, + 0x01, 0xc7, 0x49, 0x2d, 0xb2, 0xf3, 0xac, 0x5c, 0xe8, 0x3d, 0x94, 0x25, 0xac, 0xf6, 0x52, 0xdf, + 0xdb, 0xce, 0x23, 0x7f, 0x06, 0x85, 0x27, 0x43, 0x83, 0x4f, 0xd2, 0x84, 0x64, 0x09, 0x8f, 0xbe, + 0x91, 0x21, 0x7f, 0xd8, 0xf3, 0x77, 0x06, 0xcb, 0x24, 0x4d, 0x9e, 0xcf, 0x61, 0x41, 0xdb, 0x16, + 0x3d, 0x99, 0xb6, 0x0f, 0xea, 0x23, 0x7d, 0x47, 0x04, 0x27, 0x32, 0x8e, 0xb0, 0x16, 0xf3, 0xd0, + 0xdb, 0xc3, 0x71, 0x96, 0xa1, 0x1f, 0x85, 0x82, 0x85, 0x46, 0x42, 0x23, 0xdf, 0x62, 0x6b, 0xdd, + 0x4e, 0x1c, 0x45, 0x3e, 0xa2, 0xd1, 0x89, 0xae, 0x1d, 0x9a, 0xda, 0x8b, 0x3c, 0x3a, 0x25, 0xc8, + 0x57, 0x30, 0x6f, 0x2a, 0x51, 0x04, 0x72, 0xde, 0x54, 0xf2, 0x3b, 0xc0, 0xa5, 0x6d, 0x0e, 0xee, + 0x12, 0xaf, 0xe1, 0xd0, 0xb4, 0x61, 0xb4, 0x13, 0x9d, 0x10, 0x3f, 0x83, 0xbc, 0xb2, 0x43, 0x47, + 0x61, 0x30, 0xa6, 0x23, 0x18, 0x59, 0xbf, 0xed, 0x2a, 0x0c, 0x63, 0x31, 0x1d, 0x81, 0xfc, 0x93, + 0x41, 0xa1, 0xb1, 0xb2, 0xae, 0xfe, 0xff, 0x10, 0xec, 0xfe, 0x21, 0xce, 0x20, 0xbf, 0x35, 0x37, + 0x03, 0x86, 0xb7, 0x16, 0x3a, 0x02, 0xfe, 0x16, 0x4e, 0x5a, 0x24, 0x53, 0x1b, 0x32, 0x82, 0x9d, + 0xb3, 0xf2, 0xf4, 0xe2, 0xa9, 0x8a, 0x76, 0xea, 0x6b, 0xe2, 0x3f, 0x77, 0xe4, 0x76, 0xfa, 0x9f, + 0x6c, 0xfd, 0x11, 0x96, 0x93, 0x16, 0x7f, 0x02, 0xec, 0x07, 0xee, 0xd2, 0x72, 0x63, 0xf9, 0xf0, + 0x5b, 0x1f, 0xe6, 0xef, 0xb3, 0x8b, 0x5f, 0x90, 0x7f, 0x1a, 0xc3, 0xc4, 0x5f, 0x41, 0x11, 0xb3, + 0xc1, 0x57, 0x6a, 0x92, 0xa7, 0xf5, 0x63, 0x35, 0x0d, 0x8d, 0x9c, 0xf1, 0x12, 0xf2, 0xf0, 0xe7, + 0x7c, 0xa9, 0xee, 0xc7, 0x64, 0xbd, 0x52, 0x93, 0x28, 0xc8, 0x19, 0x7f, 0x01, 0xec, 0xd2, 0x36, + 0xfc, 0x54, 0xdd, 0x7d, 0xc0, 0xfa, 0x38, 0x6d, 0x24, 0x67, 0x6f, 0xb2, 0xab, 0x22, 0xa4, 0xf8, + 0xdd, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xea, 0xdf, 0xa5, 0x1d, 0xf7, 0x02, 0x00, 0x00, } diff --git a/debug/service/proto/debug.pb.micro.go b/debug/service/proto/debug.pb.micro.go index f1789b8d..45a26bac 100644 --- a/debug/service/proto/debug.pb.micro.go +++ b/debug/service/proto/debug.pb.micro.go @@ -36,7 +36,7 @@ var _ server.Option type DebugService interface { Health(ctx context.Context, in *HealthRequest, opts ...client.CallOption) (*HealthResponse, error) Stats(ctx context.Context, in *StatsRequest, opts ...client.CallOption) (*StatsResponse, error) - Logs(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogsService, error) + Log(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogService, error) } type debugService struct { @@ -77,8 +77,8 @@ func (c *debugService) Stats(ctx context.Context, in *StatsRequest, opts ...clie return out, nil } -func (c *debugService) Logs(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogsService, error) { - req := c.c.NewRequest(c.name, "Debug.Logs", &LogRequest{}) +func (c *debugService) Log(ctx context.Context, in *LogRequest, opts ...client.CallOption) (Debug_LogService, error) { + req := c.c.NewRequest(c.name, "Debug.Log", &LogRequest{}) stream, err := c.c.Stream(ctx, req, opts...) if err != nil { return nil, err @@ -86,33 +86,33 @@ func (c *debugService) Logs(ctx context.Context, in *LogRequest, opts ...client. if err := stream.Send(in); err != nil { return nil, err } - return &debugServiceLogs{stream}, nil + return &debugServiceLog{stream}, nil } -type Debug_LogsService interface { +type Debug_LogService interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error Recv() (*Record, error) } -type debugServiceLogs struct { +type debugServiceLog struct { stream client.Stream } -func (x *debugServiceLogs) Close() error { +func (x *debugServiceLog) Close() error { return x.stream.Close() } -func (x *debugServiceLogs) SendMsg(m interface{}) error { +func (x *debugServiceLog) SendMsg(m interface{}) error { return x.stream.Send(m) } -func (x *debugServiceLogs) RecvMsg(m interface{}) error { +func (x *debugServiceLog) RecvMsg(m interface{}) error { return x.stream.Recv(m) } -func (x *debugServiceLogs) Recv() (*Record, error) { +func (x *debugServiceLog) Recv() (*Record, error) { m := new(Record) err := x.stream.Recv(m) if err != nil { @@ -126,14 +126,14 @@ func (x *debugServiceLogs) Recv() (*Record, error) { type DebugHandler interface { Health(context.Context, *HealthRequest, *HealthResponse) error Stats(context.Context, *StatsRequest, *StatsResponse) error - Logs(context.Context, *LogRequest, Debug_LogsStream) error + Log(context.Context, *LogRequest, Debug_LogStream) error } func RegisterDebugHandler(s server.Server, hdlr DebugHandler, opts ...server.HandlerOption) error { type debug interface { Health(ctx context.Context, in *HealthRequest, out *HealthResponse) error Stats(ctx context.Context, in *StatsRequest, out *StatsResponse) error - Logs(ctx context.Context, stream server.Stream) error + Log(ctx context.Context, stream server.Stream) error } type Debug struct { debug @@ -154,37 +154,37 @@ func (h *debugHandler) Stats(ctx context.Context, in *StatsRequest, out *StatsRe return h.DebugHandler.Stats(ctx, in, out) } -func (h *debugHandler) Logs(ctx context.Context, stream server.Stream) error { +func (h *debugHandler) Log(ctx context.Context, stream server.Stream) error { m := new(LogRequest) if err := stream.Recv(m); err != nil { return err } - return h.DebugHandler.Logs(ctx, m, &debugLogsStream{stream}) + return h.DebugHandler.Log(ctx, m, &debugLogStream{stream}) } -type Debug_LogsStream interface { +type Debug_LogStream interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error Send(*Record) error } -type debugLogsStream struct { +type debugLogStream struct { stream server.Stream } -func (x *debugLogsStream) Close() error { +func (x *debugLogStream) Close() error { return x.stream.Close() } -func (x *debugLogsStream) SendMsg(m interface{}) error { +func (x *debugLogStream) SendMsg(m interface{}) error { return x.stream.Send(m) } -func (x *debugLogsStream) RecvMsg(m interface{}) error { +func (x *debugLogStream) RecvMsg(m interface{}) error { return x.stream.Recv(m) } -func (x *debugLogsStream) Send(m *Record) error { +func (x *debugLogStream) Send(m *Record) error { return x.stream.Send(m) } diff --git a/debug/service/proto/debug.proto b/debug/service/proto/debug.proto index a6cba776..4f639245 100644 --- a/debug/service/proto/debug.proto +++ b/debug/service/proto/debug.proto @@ -3,7 +3,7 @@ syntax = "proto3"; service Debug { rpc Health(HealthRequest) returns (HealthResponse) {}; rpc Stats(StatsRequest) returns (StatsResponse) {}; - rpc Logs(LogRequest) returns (stream Record) {}; + rpc Log(LogRequest) returns (stream Record) {}; } message HealthRequest { diff --git a/debug/service/service.go b/debug/service/service.go index ab2a26c1..8728b556 100644 --- a/debug/service/service.go +++ b/debug/service/service.go @@ -46,7 +46,7 @@ func (d *Debug) Logs(opts ...log.ReadOption) (<-chan log.Record, error) { req.Stream = options.Stream // get the log stream - stream, err := d.dbg.Logs(context.Background(), req) + stream, err := d.dbg.Log(context.Background(), req) if err != nil { return nil, fmt.Errorf("failed getting log stream: %s", err) } @@ -59,7 +59,7 @@ func (d *Debug) Logs(opts ...log.ReadOption) (<-chan log.Record, error) { return logChan, nil } -func (d *Debug) streamLogs(logChan chan log.Record, stream pb.Debug_LogsService) { +func (d *Debug) streamLogs(logChan chan log.Record, stream pb.Debug_LogService) { defer stream.Close() for { From 40c09eed1cf786518c4a07652d45a09de7f21bd9 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 5 Dec 2019 00:01:17 +0000 Subject: [PATCH 310/344] Logs to Log --- debug/service/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debug/service/service.go b/debug/service/service.go index 8728b556..d48b0a3d 100644 --- a/debug/service/service.go +++ b/debug/service/service.go @@ -27,7 +27,7 @@ func NewDebug(name string) *Debug { } // Logs queries the service logs and returns a channel to read the logs from -func (d *Debug) Logs(opts ...log.ReadOption) (<-chan log.Record, error) { +func (d *Debug) Log(opts ...log.ReadOption) (<-chan log.Record, error) { options := log.ReadOptions{} // initialize the read options for _, o := range opts { From af3d4e595f1cfde3c69694b68d31da2f2ca00beb Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 5 Dec 2019 00:08:46 +0000 Subject: [PATCH 311/344] in memory stats buffer --- debug/stats/default.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 debug/stats/default.go diff --git a/debug/stats/default.go b/debug/stats/default.go new file mode 100644 index 00000000..b2d78fce --- /dev/null +++ b/debug/stats/default.go @@ -0,0 +1,38 @@ +package stats + +import ( + "github.com/micro/go-micro/debug/buffer" +) + +type stats struct { + buffer *buffer.Buffer +} + +func (s *stats) Read() ([]*Stat, error) { + // TODO adjustable size and optional read values + buf := s.buffer.Get(1) + var stats []*Stat + + for _, b := range buf { + stat, ok := b.Value.(*Stat) + if !ok { + continue + } + stats = append(stats, stat) + } + + return stats, nil +} + +func (s *stats) Write(stat *Stat) error { + s.buffer.Put(stat) + return nil +} + +// NewStats returns a new in memory stats buffer +// TODO add options +func NewStats() Stats { + return &stats{ + buffer: buffer.New(1024), + } +} From 30aec5b872d1a07b1f179386611b86762152e8df Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Thu, 5 Dec 2019 10:56:45 +0100 Subject: [PATCH 312/344] No newlines at end of log messages Log messages should not end with a new line, this should be entirely handled by the underlying log library. Signed-off-by: Thomas Boerger --- web/service.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/service.go b/web/service.go index 97c5255a..49850d9e 100644 --- a/web/service.go +++ b/web/service.go @@ -216,7 +216,7 @@ func (s *service) start() error { ch <- l.Close() }() - log.Logf("Listening on %v\n", l.Addr().String()) + log.Logf("Listening on %v", l.Addr().String()) return nil } @@ -381,7 +381,7 @@ func (s *service) Run() error { select { // wait on kill signal case sig := <-ch: - log.Logf("Received signal %s\n", sig) + log.Logf("Received signal %s", sig) // wait on context cancel case <-s.opts.Context.Done(): log.Logf("Received context shutdown") From b55b7d6b20a6c9895170bf819c3c934ea11728b4 Mon Sep 17 00:00:00 2001 From: Allenxuxu <120582243@qq.com> Date: Thu, 5 Dec 2019 19:29:48 +0800 Subject: [PATCH 313/344] replace map with list --- config/loader/memory/memory.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/config/loader/memory/memory.go b/config/loader/memory/memory.go index 21141c5b..60af473a 100644 --- a/config/loader/memory/memory.go +++ b/config/loader/memory/memory.go @@ -2,6 +2,7 @@ package memory import ( "bytes" + "container/list" "errors" "fmt" "strings" @@ -28,8 +29,7 @@ type memory struct { // all the sources sources []source.Source - idx int - watchers map[int]*watcher + watchers *list.List } type watcher struct { @@ -153,11 +153,11 @@ func (m *memory) reload() error { } func (m *memory) update() { - watchers := make([]*watcher, 0, len(m.watchers)) + watchers := make([]*watcher, 0, m.watchers.Len()) m.RLock() - for _, w := range m.watchers { - watchers = append(watchers, w) + for e := m.watchers.Front(); e != nil; e = e.Next() { + watchers = append(watchers, e.Value.(*watcher)) } m.RUnlock() @@ -336,16 +336,14 @@ func (m *memory) Watch(path ...string) (loader.Watcher, error) { updates: make(chan reader.Value, 1), } - id := m.idx - m.watchers[id] = w - m.idx++ + e := m.watchers.PushBack(w) m.Unlock() go func() { <-w.exit m.Lock() - delete(m.watchers, id) + m.watchers.Remove(e) m.Unlock() }() @@ -404,7 +402,7 @@ func NewLoader(opts ...loader.Option) loader.Loader { m := &memory{ exit: make(chan bool), opts: options, - watchers: make(map[int]*watcher), + watchers: list.New(), sources: options.Source, } From 5db7514a914cd3c01e18fbae833e8f4428065818 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 5 Dec 2019 15:50:32 +0000 Subject: [PATCH 314/344] This PR fixes various tunnel race conditions --- tunnel/default.go | 20 ++++++------ tunnel/link.go | 6 ++++ tunnel/tunnel.go | 13 ++++---- tunnel/tunnel_reconnect_test.go | 55 +++++++++++++++++++++++++++++++++ tunnel/tunnel_test.go | 46 --------------------------- 5 files changed, 78 insertions(+), 62 deletions(-) create mode 100644 tunnel/tunnel_reconnect_test.go diff --git a/tunnel/default.go b/tunnel/default.go index da96540c..1cb0dbfc 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -854,16 +854,6 @@ func (t *tun) connect() error { } }() - // setup links - t.setupLinks() - - // process outbound messages to be sent - // process sends to all links - go t.process() - - // monitor links - go t.monitor() - return nil } @@ -889,6 +879,16 @@ func (t *tun) Connect() error { // create new close channel t.closed = make(chan bool) + // setup links + t.setupLinks() + + // process outbound messages to be sent + // process sends to all links + go t.process() + + // monitor links + go t.monitor() + return nil } diff --git a/tunnel/link.go b/tunnel/link.go index 25083138..042f1cb9 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -229,7 +229,10 @@ func (l *link) manage() { // check the type of message switch { case bytes.Equal(p.message.Body, linkRequest): + l.RLock() log.Tracef("Link %s received link request %v", l.id, p.message.Body) + l.RUnlock() + // send response if err := send(linkResponse); err != nil { l.Lock() @@ -239,7 +242,10 @@ func (l *link) manage() { case bytes.Equal(p.message.Body, linkResponse): // set round trip time d := time.Since(now) + l.RLock() log.Tracef("Link %s received link response in %v", p.message.Body, d) + l.RUnlock() + // set the RTT l.setRTT(d) } case <-t.C: diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 212e07e4..56928d8d 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -36,26 +36,27 @@ type Mode uint8 // and Micro-Tunnel-Session header. The tunnel id is a hash of // the address being requested. type Tunnel interface { + // Init initializes tunnel with options Init(opts ...Option) error - // Address the tunnel is listening on + // Address returns the address the tunnel is listening on Address() string // Connect connects the tunnel Connect() error // Close closes the tunnel Close() error - // All the links the tunnel is connected to + // Links returns all the links the tunnel is connected to Links() []Link - // Connect to a channel + // Dial allows a client to connect to a channel Dial(channel string, opts ...DialOption) (Session, error) - // Accept connections on a channel + // Listen allows to accept connections on a channel Listen(channel string, opts ...ListenOption) (Listener, error) - // Name of the tunnel implementation + // String returns the name of the tunnel implementation String() string } // Link represents internal links to the tunnel type Link interface { - // The id of the link + // Id returns the link unique Id Id() string // Delay is the current load on the link (lower is better) Delay() int64 diff --git a/tunnel/tunnel_reconnect_test.go b/tunnel/tunnel_reconnect_test.go new file mode 100644 index 00000000..2c78b8b2 --- /dev/null +++ b/tunnel/tunnel_reconnect_test.go @@ -0,0 +1,55 @@ +// +build !race + +package tunnel + +import ( + "sync" + "testing" + "time" +) + +func TestReconnectTunnel(t *testing.T) { + // create a new tunnel client + tunA := NewTunnel( + Address("127.0.0.1:9096"), + Nodes("127.0.0.1:9097"), + ) + + // create a new tunnel server + tunB := NewTunnel( + Address("127.0.0.1:9097"), + ) + + // start tunnel + err := tunB.Connect() + if err != nil { + t.Fatal(err) + } + defer tunB.Close() + + // we manually override the tunnel.ReconnectTime value here + // this is so that we make the reconnects faster than the default 5s + ReconnectTime = 200 * time.Millisecond + + // start tunnel + err = tunA.Connect() + if err != nil { + t.Fatal(err) + } + defer tunA.Close() + + wait := make(chan bool) + + var wg sync.WaitGroup + + wg.Add(1) + // start tunnel listener + go testBrokenTunAccept(t, tunB, wait, &wg) + + wg.Add(1) + // start tunnel sender + go testBrokenTunSend(t, tunA, wait, &wg) + + // wait until done + wg.Wait() +} diff --git a/tunnel/tunnel_test.go b/tunnel/tunnel_test.go index e884e692..8c3119da 100644 --- a/tunnel/tunnel_test.go +++ b/tunnel/tunnel_test.go @@ -247,52 +247,6 @@ func testBrokenTunSend(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGr <-wait } -func TestReconnectTunnel(t *testing.T) { - // create a new tunnel client - tunA := NewTunnel( - Address("127.0.0.1:9096"), - Nodes("127.0.0.1:9097"), - ) - - // create a new tunnel server - tunB := NewTunnel( - Address("127.0.0.1:9097"), - ) - - // start tunnel - err := tunB.Connect() - if err != nil { - t.Fatal(err) - } - defer tunB.Close() - - // we manually override the tunnel.ReconnectTime value here - // this is so that we make the reconnects faster than the default 5s - ReconnectTime = 200 * time.Millisecond - - // start tunnel - err = tunA.Connect() - if err != nil { - t.Fatal(err) - } - defer tunA.Close() - - wait := make(chan bool) - - var wg sync.WaitGroup - - wg.Add(1) - // start tunnel listener - go testBrokenTunAccept(t, tunB, wait, &wg) - - wg.Add(1) - // start tunnel sender - go testBrokenTunSend(t, tunA, wait, &wg) - - // wait until done - wg.Wait() -} - func TestTunnelRTTRate(t *testing.T) { // create a new tunnel client tunA := NewTunnel( From 5865e89beda21aa82fb902afc3f3344dd7860456 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 5 Dec 2019 16:10:49 +0000 Subject: [PATCH 315/344] Fixing dead code and go vet moaning --- client/grpc/codec.go | 2 +- codec/jsonrpc/jsonrpc.go | 1 - monitor/default.go | 2 -- proxy/grpc/grpc.go | 2 -- proxy/http/http.go | 2 -- proxy/mucp/mucp.go | 4 +--- registry/mdns_registry.go | 2 +- registry/service/handler/handler.go | 2 -- router/handler/router.go | 2 -- server/grpc/codec.go | 2 +- server/rpc_server.go | 2 +- util/socket/socket.go | 1 - 12 files changed, 5 insertions(+), 19 deletions(-) diff --git a/client/grpc/codec.go b/client/grpc/codec.go index 2f32a0b1..44f16d54 100644 --- a/client/grpc/codec.go +++ b/client/grpc/codec.go @@ -172,7 +172,7 @@ func (g *grpcCodec) Write(m *codec.Message, v interface{}) error { return g.s.SendMsg(v) } // write the body using the framing codec - return g.s.SendMsg(&bytes.Frame{m.Body}) + return g.s.SendMsg(&bytes.Frame{Data: m.Body}) } func (g *grpcCodec) Close() error { diff --git a/codec/jsonrpc/jsonrpc.go b/codec/jsonrpc/jsonrpc.go index f98b2842..d7e0e1c9 100644 --- a/codec/jsonrpc/jsonrpc.go +++ b/codec/jsonrpc/jsonrpc.go @@ -60,7 +60,6 @@ func (j *jsonCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error { default: return fmt.Errorf("Unrecognised message type: %v", mt) } - return nil } func (j *jsonCodec) ReadBody(b interface{}) error { diff --git a/monitor/default.go b/monitor/default.go index 557ca234..b37b5658 100644 --- a/monitor/default.go +++ b/monitor/default.go @@ -307,8 +307,6 @@ func (m *monitor) Stop() error { m.running = false return nil } - - return nil } func newMonitor(opts ...Option) Monitor { diff --git a/proxy/grpc/grpc.go b/proxy/grpc/grpc.go index 91333662..571822ea 100644 --- a/proxy/grpc/grpc.go +++ b/proxy/grpc/grpc.go @@ -135,8 +135,6 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server return err } } - - return nil } // NewProxy returns a new grpc proxy server diff --git a/proxy/http/http.go b/proxy/http/http.go index 9bcf01db..64b4384b 100644 --- a/proxy/http/http.go +++ b/proxy/http/http.go @@ -187,8 +187,6 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server return errors.InternalServerError(req.Service(), err.Error()) } } - - return nil } // NewSingleHostProxy returns a router which sends requests to a single http backend diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index a202fe3d..0e04c7d6 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -437,7 +437,7 @@ func (p *Proxy) serveRequest(ctx context.Context, link client.Client, service, e } // create new request with raw bytes body - creq := link.NewRequest(service, endpoint, &bytes.Frame{body}, client.WithContentType(req.ContentType())) + creq := link.NewRequest(service, endpoint, &bytes.Frame{Data: body}, client.WithContentType(req.ContentType())) // not a stream so make a client.Call request if !req.Stream() { @@ -493,8 +493,6 @@ func (p *Proxy) serveRequest(ctx context.Context, link client.Client, service, e return err } } - - return nil } // NewSingleHostProxy returns a proxy which sends requests to a single backend diff --git a/registry/mdns_registry.go b/registry/mdns_registry.go index 48782f76..fe952d22 100644 --- a/registry/mdns_registry.go +++ b/registry/mdns_registry.go @@ -105,7 +105,7 @@ func (m *mdnsRegistry) Register(service *Service, opts ...RegisterOption) error return err } - srv, err := mdns.NewServer(&mdns.Config{Zone: &mdns.DNSSDService{s}}) + srv, err := mdns.NewServer(&mdns.Config{Zone: &mdns.DNSSDService{MDNSService: s}}) if err != nil { return err } diff --git a/registry/service/handler/handler.go b/registry/service/handler/handler.go index 2c33153a..e2042e5e 100644 --- a/registry/service/handler/handler.go +++ b/registry/service/handler/handler.go @@ -79,6 +79,4 @@ func (r *Registry) Watch(ctx context.Context, req *pb.WatchRequest, rsp pb.Regis return errors.InternalServerError("go.micro.registry", err.Error()) } } - - return nil } diff --git a/router/handler/router.go b/router/handler/router.go index 90039871..971e2336 100644 --- a/router/handler/router.go +++ b/router/handler/router.go @@ -187,6 +187,4 @@ func (r *Router) Watch(ctx context.Context, req *pb.WatchRequest, stream pb.Rout return err } } - - return nil } diff --git a/server/grpc/codec.go b/server/grpc/codec.go index 53de36c3..356f8e81 100644 --- a/server/grpc/codec.go +++ b/server/grpc/codec.go @@ -169,7 +169,7 @@ func (g *grpcCodec) Write(m *codec.Message, v interface{}) error { m.Body = b } // write the body using the framing codec - return g.s.SendMsg(&bytes.Frame{m.Body}) + return g.s.SendMsg(&bytes.Frame{Data: m.Body}) } func (g *grpcCodec) Close() error { diff --git a/server/rpc_server.go b/server/rpc_server.go index a22f13b6..191bf1e8 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -100,7 +100,7 @@ func (s *rpcServer) HandleEvent(e broker.Event) error { rpcMsg := &rpcMessage{ topic: msg.Header["Micro-Topic"], contentType: ct, - payload: &raw.Frame{msg.Body}, + payload: &raw.Frame{Data: msg.Body}, codec: cf, header: msg.Header, body: msg.Body, diff --git a/util/socket/socket.go b/util/socket/socket.go index f536ad7d..e68df694 100644 --- a/util/socket/socket.go +++ b/util/socket/socket.go @@ -38,7 +38,6 @@ func (s *Socket) Accept(m *transport.Message) error { case <-s.closed: return io.EOF } - return nil } // Process takes the next message off the send queue created by a call to Send From bca12a7003c4b2693eefaef2c49381f67a516bec Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Thu, 5 Dec 2019 17:11:17 +0000 Subject: [PATCH 316/344] =?UTF-8?q?Changed=20a=20few=20router=20knobs=20to?= =?UTF-8?q?=20avoid=20storms=20=E2=9B=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router/default.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/router/default.go b/router/default.go index e4305436..cd35db86 100644 --- a/router/default.go +++ b/router/default.go @@ -15,9 +15,9 @@ import ( var ( // AdvertiseEventsTick is time interval in which the router advertises route updates - AdvertiseEventsTick = 5 * time.Second + AdvertiseEventsTick = 10 * time.Second // AdvertiseTableTick is time interval in which router advertises all routes found in routing table - AdvertiseTableTick = 1 * time.Minute + AdvertiseTableTick = 2 * time.Minute // DefaultAdvertTTL is default advertisement TTL DefaultAdvertTTL = 1 * time.Minute // AdvertSuppress is advert suppression threshold @@ -29,7 +29,7 @@ var ( // PenaltyHalfLife is the time the advert penalty decays to half its value PenaltyHalfLife = 30.0 // MaxSuppressTime defines time after which the suppressed advert is deleted - MaxSuppressTime = time.Second * 30 + MaxSuppressTime = 90 * time.Second // PenaltyDecay is a coefficient which controls the speed the advert penalty decays PenaltyDecay = math.Log(2) / PenaltyHalfLife ) From ac9001ac747788c418655c9caa13a74df6a4de6b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 5 Dec 2019 17:50:32 +0000 Subject: [PATCH 317/344] advert ttl inline with router table tick --- router/default.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/default.go b/router/default.go index cd35db86..b0739ebf 100644 --- a/router/default.go +++ b/router/default.go @@ -19,7 +19,7 @@ var ( // AdvertiseTableTick is time interval in which router advertises all routes found in routing table AdvertiseTableTick = 2 * time.Minute // DefaultAdvertTTL is default advertisement TTL - DefaultAdvertTTL = 1 * time.Minute + DefaultAdvertTTL = 2 * time.Minute // AdvertSuppress is advert suppression threshold AdvertSuppress = 200.0 // AdvertRecover is advert recovery threshold From 219efd27e9b03f93c3cd05b3dc385dd21854430b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 5 Dec 2019 23:11:42 +0000 Subject: [PATCH 318/344] Optimise the multicast to use one session in the tunnel --- tunnel/default.go | 63 ++++---- tunnel/listener.go | 48 ++++-- ...el_reconnect_test.go => reconnect_test.go} | 0 tunnel/session.go | 147 ++++++++---------- 4 files changed, 137 insertions(+), 121 deletions(-) rename tunnel/{tunnel_reconnect_test.go => reconnect_test.go} (100%) diff --git a/tunnel/default.go b/tunnel/default.go index 1cb0dbfc..e64359a6 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -127,7 +127,6 @@ func (t *tun) newSession(channel, sessionId string) (*session, bool) { closed: make(chan bool), recv: make(chan *message, 128), send: t.send, - wait: make(chan bool), errChan: make(chan error, 1), } @@ -470,6 +469,9 @@ func (t *tun) listen(link *link) { return } + // this state machine block handles the only message types + // that we know or care about; connect, close, open, accept, + // discover, announce, session, keepalive switch mtype { case "connect": log.Debugf("Tunnel link %s received connect message", link.Remote()) @@ -500,9 +502,6 @@ func (t *tun) listen(link *link) { // nothing more to do continue case "close": - // TODO: handle the close message - // maybe report io.EOF or kill the link - // if there is no channel then we close the link // as its a signal from the other side to close the connection if len(channel) == 0 { @@ -521,6 +520,8 @@ func (t *tun) listen(link *link) { // try get the dialing socket s, exists := t.getSession(channel, sessionId) if exists && !loopback { + // only delete the session if its unicast + // otherwise ignore close on the multicast if s.mode == Unicast { // only delete this if its unicast // but not if its a loopback conn @@ -541,14 +542,16 @@ func (t *tun) listen(link *link) { // an accept returned by the listener case "accept": s, exists := t.getSession(channel, sessionId) - // we don't need this + // just set accepted on anything not unicast if exists && s.mode > Unicast { s.accepted = true continue } + // if its already accepted move on if exists && s.accepted { continue } + // otherwise we're going to process to accept // a continued session case "session": // process message @@ -562,7 +565,10 @@ func (t *tun) listen(link *link) { link.setChannel(channels...) // this was an announcement not intended for anything - if sessionId == "listener" || sessionId == "" { + // if the dialing side sent "discover" then a session + // id would be present. We skip in case of multicast. + switch sessionId { + case "listener", "multicast", "": continue } @@ -574,14 +580,19 @@ func (t *tun) listen(link *link) { continue } - // send the announce back to the caller - s.recv <- &message{ + msg := &message{ typ: "announce", tunnel: id, channel: channel, session: sessionId, link: link.id, } + + // send the announce back to the caller + select { + case <-s.closed: + case s.recv <- msg: + } } continue case "discover": @@ -651,22 +662,10 @@ func (t *tun) listen(link *link) { delete(t.sessions, channel) continue default: - // process + // otherwise process } - log.Debugf("Tunnel using channel %s session %s", s.channel, s.session) - - // is the session new? - select { - // if its new the session is actually blocked waiting - // for a connection. so we check if its waiting. - case <-s.wait: - // if its waiting e.g its new then we close it - default: - // set remote address of the session - s.remote = msg.Header["Remote"] - close(s.wait) - } + log.Debugf("Tunnel using channel %s session %s type %s", s.channel, s.session, mtype) // construct a new transport message tmsg := &transport.Message{ @@ -1052,7 +1051,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { t.RUnlock() - // link not found + // link not found and one was specified so error out if len(links) == 0 && len(options.Link) > 0 { // delete session and return error t.delSession(c.channel, c.session) @@ -1061,15 +1060,14 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { } // discovered so set the link if not multicast - // TODO: pick the link efficiently based - // on link status and saturation. if c.discovered && c.mode == Unicast { // pickLink will pick the best link link := t.pickLink(links) + // set the link c.link = link.id } - // shit fuck + // if its not already discovered we need to attempt to do so if !c.discovered { // piggy back roundtrip nowRTT := time.Now() @@ -1098,7 +1096,15 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { } } - // a unicast session so we call "open" and wait for an "accept" + // return early if its not unicast + // we will not call "open" for multicast + if c.mode != Unicast { + return c, nil + } + + // Note: we go no further for multicast or broadcast. + // This is a unicast session so we call "open" and wait + // for an "accept" // reset now in case we use it now := time.Now() @@ -1115,7 +1121,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { d := time.Since(now) // if we haven't measured the roundtrip do it now - if !measured && c.mode == Unicast { + if !measured { // set the link time t.RLock() link, ok := t.links[c.link] @@ -1145,6 +1151,7 @@ func (t *tun) Listen(channel string, opts ...ListenOption) (Listener, error) { return nil, errors.New("already listening on " + channel) } + // delete function removes the session when closed delFunc := func() { t.delSession(channel, "listener") } diff --git a/tunnel/listener.go b/tunnel/listener.go index 7ba6074e..36d70e96 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -24,7 +24,7 @@ type tunListener struct { delFunc func() } -// periodically announce self +// periodically announce self the channel being listened on func (t *tunListener) announce() { tick := time.NewTicker(time.Second * 30) defer tick.Stop() @@ -48,9 +48,12 @@ func (t *tunListener) process() { defer func() { // close the sessions - for _, conn := range conns { + for id, conn := range conns { conn.Close() + delete(conns, id) } + // unassign + conns = nil }() for { @@ -62,9 +65,22 @@ func (t *tunListener) process() { return // receive a new message case m := <-t.session.recv: + var sessionId string + + // get the session id + switch m.mode { + case Multicast, Broadcast: + // use channel name if multicast/broadcast + sessionId = m.channel + log.Tracef("Tunnel listener using session %s for real session %s", sessionId, m.session) + default: + // use session id if unicast + sessionId = m.session + } + // get a session - sess, ok := conns[m.session] - log.Debugf("Tunnel listener received channel %s session %s exists: %t", m.channel, m.session, ok) + sess, ok := conns[sessionId] + log.Debugf("Tunnel listener received channel %s session %s type %s exists: %t", m.channel, sessionId, m.typ, ok) if !ok { // we only process open and session types switch m.typ { @@ -80,7 +96,7 @@ func (t *tunListener) process() { // the channel channel: m.channel, // the session id - session: m.session, + session: sessionId, // tunnel token token: t.token, // is loopback conn @@ -95,14 +111,12 @@ func (t *tunListener) process() { recv: make(chan *message, 128), // use the internal send buffer send: t.session.send, - // wait - wait: make(chan bool), // error channel errChan: make(chan error, 1), } // save the session - conns[m.session] = sess + conns[sessionId] = sess select { case <-t.closed: @@ -114,17 +128,21 @@ func (t *tunListener) process() { // an existing session was found - // received a close message switch m.typ { case "close": + // received a close message select { + // check if the session is closed case <-sess.closed: // no op - delete(conns, m.session) + delete(conns, sessionId) default: - // close and delete session - close(sess.closed) - delete(conns, m.session) + if sess.mode == Unicast { + // only close if unicast session + // close and delete session + close(sess.closed) + delete(conns, sessionId) + } } // continue @@ -139,9 +157,9 @@ func (t *tunListener) process() { // send this to the accept chan select { case <-sess.closed: - delete(conns, m.session) + delete(conns, sessionId) case sess.recv <- m: - log.Debugf("Tunnel listener sent to recv chan channel %s session %s", m.channel, m.session) + log.Debugf("Tunnel listener sent to recv chan channel %s session %s type %s", m.channel, sessionId, m.typ) } } } diff --git a/tunnel/tunnel_reconnect_test.go b/tunnel/reconnect_test.go similarity index 100% rename from tunnel/tunnel_reconnect_test.go rename to tunnel/reconnect_test.go diff --git a/tunnel/session.go b/tunnel/session.go index b5b724b0..6c4ad69a 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -30,8 +30,6 @@ type session struct { send chan *message // recv chan recv chan *message - // wait until we have a connection - wait chan bool // if the discovery worked discovered bool // if the session was accepted @@ -109,6 +107,29 @@ func (s *session) newMessage(typ string) *message { } } +func (s *session) sendMsg(msg *message) error { + select { + case <-s.closed: + return io.EOF + case s.send <- msg: + return nil + } +} + +func (s *session) wait(msg *message) error { + // wait for an error response + select { + case err := <-msg.errChan: + if err != nil { + return err + } + case <-s.closed: + return io.EOF + } + + return nil +} + // waitFor waits for the message type required until the timeout specified func (s *session) waitFor(msgType string, timeout time.Duration) (*message, error) { now := time.Now() @@ -144,20 +165,32 @@ func (s *session) waitFor(msgType string, timeout time.Duration) (*message, erro } } -// Discover attempts to discover the link for a specific channel +// Discover attempts to discover the link for a specific channel. +// This is only used by the tunnel.Dial when first connecting. func (s *session) Discover() error { // create a new discovery message for this channel msg := s.newMessage("discover") + // broadcast the message to all links msg.mode = Broadcast + // its an outbound connection since we're dialling msg.outbound = true + // don't set the link since we don't know where it is msg.link = "" - // send the discovery message - s.send <- msg + // if multicast then set that as session + if s.mode == Multicast { + msg.session = "multicast" + } + + // send discover message + if err := s.sendMsg(msg); err != nil { + return err + } // set time now now := time.Now() + // after strips down the dial timeout after := func() time.Duration { d := time.Since(now) // dial timeout minus time since @@ -168,6 +201,7 @@ func (s *session) Discover() error { return wait } + // the discover message is sent out, now // wait to hear back about the sent message select { case <-time.After(after()): @@ -178,27 +212,16 @@ func (s *session) Discover() error { } } - var err error - - // set a new dialTimeout - dialTimeout := after() - - // set a shorter delay for multicast - if s.mode != Unicast { - // shorten this - dialTimeout = time.Millisecond * 500 - } - - // wait for announce - _, err = s.waitFor("announce", dialTimeout) - - // if its multicast just go ahead because this is best effort + // bail early if its not unicast + // we don't need to wait for the announce if s.mode != Unicast { s.discovered = true s.accepted = true return nil } + // wait for announce + _, err := s.waitFor("announce", after()) if err != nil { return err } @@ -210,30 +233,22 @@ func (s *session) Discover() error { } // Open will fire the open message for the session. This is called by the dialler. +// This is to indicate that we want to create a new session. func (s *session) Open() error { // create a new message msg := s.newMessage("open") // send open message - s.send <- msg + if err := s.sendMsg(msg); err != nil { + return err + } // wait for an error response for send - select { - case err := <-msg.errChan: - if err != nil { - return err - } - case <-s.closed: - return io.EOF + if err := s.wait(msg); err != nil { + return err } - // don't wait on multicast/broadcast - if s.mode == Multicast { - s.accepted = true - return nil - } - - // now wait for the accept + // now wait for the accept message to be returned msg, err := s.waitFor("accept", s.timeout) if err != nil { return err @@ -252,32 +267,16 @@ func (s *session) Accept() error { msg := s.newMessage("accept") // send the accept message - select { - case <-s.closed: - return io.EOF - case s.send <- msg: - // no op here - } - - // don't wait on multicast/broadcast - if s.mode == Multicast { - return nil + if err := s.sendMsg(msg); err != nil { + return err } // wait for send response - select { - case err := <-s.errChan: - if err != nil { - return err - } - case <-s.closed: - return io.EOF - } - - return nil + return s.wait(msg) } -// Announce sends an announcement to notify that this session exists. This is primarily used by the listener. +// Announce sends an announcement to notify that this session exists. +// This is primarily used by the listener. func (s *session) Announce() error { msg := s.newMessage("announce") // we don't need an error back @@ -287,23 +286,12 @@ func (s *session) Announce() error { // we don't need the link msg.link = "" - select { - case s.send <- msg: - return nil - case <-s.closed: - return io.EOF - } + // send announce message + return s.sendMsg(msg) } // Send is used to send a message func (s *session) Send(m *transport.Message) error { - select { - case <-s.closed: - return io.EOF - default: - // no op - } - // encrypt the transport message payload body, err := Encrypt(m.Body, s.token+s.channel+s.session) if err != nil { @@ -335,21 +323,19 @@ func (s *session) Send(m *transport.Message) error { msg.data = data // if multicast don't set the link - if s.mode == Multicast { + if s.mode != Unicast { msg.link = "" } log.Tracef("Appending %+v to send backlog", msg) + // send the actual message - s.send <- msg + if err := s.sendMsg(msg); err != nil { + return err + } // wait for an error response - select { - case err := <-msg.errChan: - return err - case <-s.closed: - return io.EOF - } + return s.wait(msg) } // Recv is used to receive a message @@ -413,6 +399,11 @@ func (s *session) Close() error { default: close(s.closed) + // don't send close on multicast + if s.mode != Unicast { + return nil + } + // append to backlog msg := s.newMessage("close") // no error response on close @@ -421,7 +412,7 @@ func (s *session) Close() error { // send the close message select { case s.send <- msg: - default: + case <-time.After(time.Millisecond * 10): } } From 1d8c66780e25ecb5b8e5e2bdb013937d71ec1755 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 6 Dec 2019 00:18:40 +0000 Subject: [PATCH 319/344] save working solution --- network/default.go | 82 ++++++++++++++++++++++++++++++++-------------- tunnel/default.go | 6 ++-- tunnel/listener.go | 6 +++- tunnel/session.go | 10 +++--- 4 files changed, 71 insertions(+), 33 deletions(-) diff --git a/network/default.go b/network/default.go index ef859d51..4e5d96d7 100644 --- a/network/default.go +++ b/network/default.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "hash/fnv" + "io" "math" "sync" "time" @@ -70,6 +71,9 @@ type network struct { connected bool // closed closes the network closed chan bool + // whether we've announced the first connect successfully + // and received back some sort of peer message + announced chan bool } // newNetwork returns a new network node @@ -267,10 +271,11 @@ func (n *network) handleNetConn(s tunnel.Session, msg chan *message) { m := new(transport.Message) if err := s.Recv(m); err != nil { log.Debugf("Network tunnel [%s] receive error: %v", NetworkChannel, err) - if sessionErr := s.Close(); sessionErr != nil { - log.Debugf("Network tunnel [%s] closing connection error: %v", NetworkChannel, sessionErr) + if err == io.EOF { + s.Close() + return } - return + continue } select { @@ -452,6 +457,14 @@ func (n *network) processNetChan(listener tunnel.Listener) { if err := n.node.UpdatePeer(peer); err != nil { log.Debugf("Network failed to update peers: %v", err) } + + // check if we announced and were discovered + select { + case <-n.announced: + // we've sent the connect and received this response + default: + close(n.announced) + } case "close": pbNetClose := &pbNet.Close{} if err := proto.Unmarshal(m.msg.Body, pbNetClose); err != nil { @@ -622,10 +635,11 @@ func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { m := new(transport.Message) if err := s.Recv(m); err != nil { log.Debugf("Network tunnel [%s] receive error: %v", ControlChannel, err) - if sessionErr := s.Close(); sessionErr != nil { - log.Debugf("Network tunnel [%s] closing connection error: %v", ControlChannel, sessionErr) + if err == io.EOF { + s.Close() + return } - return + continue } select { @@ -930,6 +944,40 @@ func (n *network) sendConnect() { } } +// connect will wait for a link to be established +func (n *network) connect() { + // wait for connected state + var connected bool + + for { + // check the links + for _, link := range n.tunnel.Links() { + if link.State() == "connected" { + connected = true + break + } + } + + // if we're not conencted wait + if !connected { + time.Sleep(time.Second) + continue + } + + // send the connect message + n.sendConnect() + + // check the announce channel + select { + case <-n.announced: + return + default: + time.Sleep(time.Second) + // we have to go again + } + } +} + // Connect connects the network func (n *network) Connect() error { n.Lock() @@ -1000,6 +1048,8 @@ func (n *network) Connect() error { // create closed channel n.closed = make(chan bool) + // create new announced channel + n.announced = make(chan bool) // start the router if err := n.options.Router.Start(); err != nil { @@ -1022,25 +1072,7 @@ func (n *network) Connect() error { n.Unlock() // send connect after there's a link established - go func() { - // wait for 30 ticks e.g 30 seconds - for i := 0; i < 30; i++ { - // get the current links - links := n.tunnel.Links() - - // if there are no links wait until we have one - if len(links) == 0 { - time.Sleep(time.Second) - continue - } - - // send the connect message - n.sendConnect() - // most importantly - break - } - }() - + go n.connect() // go resolving network nodes go n.resolve() // broadcast peers diff --git a/tunnel/default.go b/tunnel/default.go index e64359a6..6b1b9151 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -629,7 +629,7 @@ func (t *tun) listen(link *link) { s, exists = t.getSession(channel, "listener") // only return accept to the session case mtype == "accept": - log.Debugf("Received accept message for %s %s", channel, sessionId) + log.Debugf("Received accept message for channel: %s session: %s", channel, sessionId) s, exists = t.getSession(channel, sessionId) if exists && s.accepted { continue @@ -649,7 +649,7 @@ func (t *tun) listen(link *link) { // bail if no session or listener has been found if !exists { - log.Debugf("Tunnel skipping no session %s %s exists", channel, sessionId) + log.Debugf("Tunnel skipping no channel: %s session: %s exists", channel, sessionId) // drop it, we don't care about // messages we don't know about continue @@ -665,7 +665,7 @@ func (t *tun) listen(link *link) { // otherwise process } - log.Debugf("Tunnel using channel %s session %s type %s", s.channel, s.session, mtype) + log.Debugf("Tunnel using channel: %s session: %s type: %s", s.channel, s.session, mtype) // construct a new transport message tmsg := &transport.Message{ diff --git a/tunnel/listener.go b/tunnel/listener.go index 36d70e96..ec435b03 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -71,7 +71,7 @@ func (t *tunListener) process() { switch m.mode { case Multicast, Broadcast: // use channel name if multicast/broadcast - sessionId = m.channel + sessionId = "multicast" log.Tracef("Tunnel listener using session %s for real session %s", sessionId, m.session) default: // use session id if unicast @@ -198,6 +198,10 @@ func (t *tunListener) Accept() (Session, error) { if !ok { return nil, io.EOF } + // return without accept + if c.mode != Unicast { + return c, nil + } // send back the accept if err := c.Accept(); err != nil { return nil, err diff --git a/tunnel/session.go b/tunnel/session.go index 6c4ad69a..3cb37c61 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -2,7 +2,6 @@ package tunnel import ( "encoding/hex" - "errors" "io" "time" @@ -344,7 +343,7 @@ func (s *session) Recv(m *transport.Message) error { select { case <-s.closed: - return errors.New("session is closed") + return io.EOF // recv from backlog case msg = <-s.recv: } @@ -360,7 +359,10 @@ func (s *session) Recv(m *transport.Message) error { log.Debugf("Received %+v from recv backlog", msg) // decrypt the received payload using the token - body, err := Decrypt(msg.data.Body, s.token+s.channel+s.session) + // we have to used msg.session because multicast has a shared + // session id of "multicast" in this session struct on + // the listener side + body, err := Decrypt(msg.data.Body, s.token+s.channel+msg.session) if err != nil { log.Debugf("failed to decrypt message body: %v", err) return err @@ -376,7 +378,7 @@ func (s *session) Recv(m *transport.Message) error { return err } // encrypt the transport message payload - val, err := Decrypt([]byte(h), s.token+s.channel+s.session) + val, err := Decrypt([]byte(h), s.token+s.channel+msg.session) if err != nil { log.Debugf("failed to decrypt message header %s: %v", k, err) return err From c445aed6b1ffbd41809066e8f0585967a11bad34 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 7 Dec 2019 19:54:29 +0000 Subject: [PATCH 320/344] Cleanup and speedup network convergence along with direct messaging for connect and solicit --- client/rpc_client.go | 40 +++- client/rpc_codec.go | 27 +-- network/default.go | 426 +++++++++++++++++++++++++++++++------------ network/network.go | 8 - network/node.go | 2 +- network/node_test.go | 2 +- proxy/mucp/mucp.go | 55 ++++-- router/default.go | 8 +- router/router.go | 4 + server/rpc_codec.go | 21 +-- server/rpc_server.go | 13 +- service.go | 2 +- tunnel/default.go | 17 +- tunnel/link.go | 56 +++++- tunnel/listener.go | 4 +- tunnel/session.go | 4 +- tunnel/tunnel.go | 4 +- 17 files changed, 494 insertions(+), 199 deletions(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index 75ce75ac..4da6df45 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -316,6 +316,22 @@ func (r *rpcClient) Options() Options { return r.opts } +// hasProxy checks if we have proxy set in the environment +func (r *rpcClient) hasProxy() bool { + // get proxy + if prx := os.Getenv("MICRO_PROXY"); len(prx) > 0 { + return true + } + + // get proxy address + if prx := os.Getenv("MICRO_PROXY_ADDRESS"); len(prx) > 0 { + return true + } + + return false +} + +// next returns an iterator for the next nodes to call func (r *rpcClient) next(request Request, opts CallOptions) (selector.Next, error) { service := request.Service() @@ -431,10 +447,18 @@ func (r *rpcClient) Call(ctx context.Context, request Request, response interfac return err } - ch := make(chan error, callOpts.Retries+1) + // get the retries + retries := callOpts.Retries + + // disable retries when using a proxy + if r.hasProxy() { + retries = 0 + } + + ch := make(chan error, retries+1) var gerr error - for i := 0; i <= callOpts.Retries; i++ { + for i := 0; i <= retries; i++ { go func(i int) { ch <- call(i) }(i) @@ -514,10 +538,18 @@ func (r *rpcClient) Stream(ctx context.Context, request Request, opts ...CallOpt err error } - ch := make(chan response, callOpts.Retries+1) + // get the retries + retries := callOpts.Retries + + // disable retries when using a proxy + if r.hasProxy() { + retries = 0 + } + + ch := make(chan response, retries+1) var grr error - for i := 0; i <= callOpts.Retries; i++ { + for i := 0; i <= retries; i++ { go func(i int) { s, err := call(i) ch <- response{s, err} diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 60dc02b5..a71f6a11 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -88,32 +88,24 @@ func (rwc *readWriteCloser) Close() error { } func getHeaders(m *codec.Message) { - get := func(hdr string) string { - if hd := m.Header[hdr]; len(hd) > 0 { - return hd + set := func(v, hdr string) string { + if len(v) > 0 { + return v } - // old - return m.Header["X-"+hdr] + return m.Header[hdr] } // check error in header - if len(m.Error) == 0 { - m.Error = get("Micro-Error") - } + m.Error = set(m.Error, "Micro-Error") // check endpoint in header - if len(m.Endpoint) == 0 { - m.Endpoint = get("Micro-Endpoint") - } + m.Endpoint = set(m.Endpoint, "Micro-Endpoint") // check method in header - if len(m.Method) == 0 { - m.Method = get("Micro-Method") - } + m.Method = set(m.Method, "Micro-Method") - if len(m.Id) == 0 { - m.Id = get("Micro-Id") - } + // set the request id + m.Id = set(m.Id, "Micro-Id") } func setHeaders(m *codec.Message, stream string) { @@ -122,7 +114,6 @@ func setHeaders(m *codec.Message, stream string) { return } m.Header[hdr] = v - m.Header["X-"+hdr] = v } set("Micro-Id", m.Id) diff --git a/network/default.go b/network/default.go index 4e5d96d7..26789436 100644 --- a/network/default.go +++ b/network/default.go @@ -71,9 +71,18 @@ type network struct { connected bool // closed closes the network closed chan bool - // whether we've announced the first connect successfully - // and received back some sort of peer message - announced chan bool + // whether we've discovered by the network + discovered chan bool + // solicted checks whether routes were solicited by one node + solicited chan string +} + +// message is network message +type message struct { + // msg is transport message + msg *transport.Message + // session is tunnel session + session tunnel.Session } // newNetwork returns a new network node @@ -149,14 +158,16 @@ func newNetwork(opts ...Option) Network { address: peerAddress, peers: make(map[string]*node), }, - options: options, - router: options.Router, - proxy: options.Proxy, - tunnel: options.Tunnel, - server: server, - client: client, - tunClient: make(map[string]transport.Client), - peerLinks: make(map[string]tunnel.Link), + options: options, + router: options.Router, + proxy: options.Proxy, + tunnel: options.Tunnel, + server: server, + client: client, + tunClient: make(map[string]transport.Client), + peerLinks: make(map[string]tunnel.Link), + discovered: make(chan bool, 1), + solicited: make(chan string, 1), } network.node.network = network @@ -278,6 +289,14 @@ func (n *network) handleNetConn(s tunnel.Session, msg chan *message) { continue } + // check if peer is set + peer := m.Header["Micro-Peer"] + + // check who the message is intended for + if len(peer) > 0 && peer != n.options.Id { + continue + } + select { case msg <- &message{ msg: m, @@ -367,26 +386,33 @@ func (n *network) processNetChan(listener tunnel.Listener) { // mark the time the message has been received now := time.Now() pbNetConnect := &pbNet.Connect{} + if err := proto.Unmarshal(m.msg.Body, pbNetConnect); err != nil { log.Debugf("Network tunnel [%s] connect unmarshal error: %v", NetworkChannel, err) continue } + // don't process your own messages if pbNetConnect.Node.Id == n.options.Id { continue } + log.Debugf("Network received connect message from: %s", pbNetConnect.Node.Id) + peer := &node{ id: pbNetConnect.Node.Id, address: pbNetConnect.Node.Address, peers: make(map[string]*node), lastSeen: now, } + // update peer links log.Tracef("Network updating peer link %s for peer: %s", m.session.Link(), pbNetConnect.Node.Address) + if err := n.updatePeerLinks(pbNetConnect.Node.Address, m.session.Link()); err != nil { log.Debugf("Network failed updating peer links: %s", err) } + // add peer to the list of node peers if err := n.node.AddPeer(peer); err == ErrPeerExists { log.Debugf("Network peer exists, refreshing: %s", peer.id) @@ -394,50 +420,76 @@ func (n *network) processNetChan(listener tunnel.Listener) { if err := n.RefreshPeer(peer.id, now); err != nil { log.Debugf("Network failed refreshing peer %s: %v", peer.id, err) } - continue } + + // we send the peer message because someone has sent connect + // and wants to know what's on the network. The faster we + // respond the faster we start to converge + // get node peers down to MaxDepth encoded in protobuf msg := PeersToProto(n.node, MaxDepth) + node := pbNetConnect.Node.Id + // advertise yourself to the network - if err := n.sendMsg("peer", msg, NetworkChannel); err != nil { + if err := n.sendTo("peer", NetworkChannel, node, msg); err != nil { log.Debugf("Network failed to advertise peers: %v", err) } + // advertise all the routes when a new node has connected if err := n.router.Solicit(); err != nil { log.Debugf("Network failed to solicit routes: %s", err) } + + // specify that we're soliciting + select { + case n.solicited <- node: + default: + // don't block + } case "peer": // mark the time the message has been received now := time.Now() pbNetPeer := &pbNet.Peer{} + if err := proto.Unmarshal(m.msg.Body, pbNetPeer); err != nil { log.Debugf("Network tunnel [%s] peer unmarshal error: %v", NetworkChannel, err) continue } + // don't process your own messages if pbNetPeer.Node.Id == n.options.Id { continue } + log.Debugf("Network received peer message from: %s %s", pbNetPeer.Node.Id, pbNetPeer.Node.Address) + peer := &node{ id: pbNetPeer.Node.Id, address: pbNetPeer.Node.Address, peers: make(map[string]*node), lastSeen: now, } + // update peer links log.Tracef("Network updating peer link %s for peer: %s", m.session.Link(), pbNetPeer.Node.Address) + if err := n.updatePeerLinks(pbNetPeer.Node.Address, m.session.Link()); err != nil { log.Debugf("Network failed updating peer links: %s", err) } + if err := n.node.AddPeer(peer); err == nil { // send a solicit message when discovering new peer msg := &pbRtr.Solicit{ Id: n.options.Id, } - if err := n.sendMsg("solicit", msg, ControlChannel); err != nil { + + node := pbNetPeer.Node.Id + + // only solicit this peer + if err := n.sendTo("solicit", ControlChannel, node, msg); err != nil { log.Debugf("Network failed to send solicit message: %s", err) } + continue // we're expecting any error to be ErrPeerExists } else if err != ErrPeerExists { @@ -446,6 +498,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { } log.Debugf("Network peer exists, refreshing: %s", pbNetPeer.Node.Id) + // update lastSeen time for the peer if err := n.RefreshPeer(pbNetPeer.Node.Id, now); err != nil { log.Debugf("Network failed refreshing peer %s: %v", pbNetPeer.Node.Id, err) @@ -458,12 +511,12 @@ func (n *network) processNetChan(listener tunnel.Listener) { log.Debugf("Network failed to update peers: %v", err) } - // check if we announced and were discovered + // tell the connect loop that we've been discovered + // so it stops sending connect messages out select { - case <-n.announced: - // we've sent the connect and received this response + case n.discovered <- true: default: - close(n.announced) + // don't block here } case "close": pbNetClose := &pbNet.Close{} @@ -471,22 +524,28 @@ func (n *network) processNetChan(listener tunnel.Listener) { log.Debugf("Network tunnel [%s] close unmarshal error: %v", NetworkChannel, err) continue } + // don't process your own messages if pbNetClose.Node.Id == n.options.Id { continue } + log.Debugf("Network received close message from: %s", pbNetClose.Node.Id) + peer := &node{ id: pbNetClose.Node.Id, address: pbNetClose.Node.Address, } + if err := n.DeletePeerNode(peer.id); err != nil { log.Debugf("Network failed to delete node %s routes: %v", peer.id, err) } + if err := n.prunePeerRoutes(peer); err != nil { log.Debugf("Network failed pruning peer %s routes: %v", peer.id, err) } - // deelete peer from the peerLinks + + // delete peer from the peerLinks n.Lock() delete(n.peerLinks, pbNetClose.Node.Address) n.Unlock() @@ -497,57 +556,6 @@ func (n *network) processNetChan(listener tunnel.Listener) { } } -// sendMsg sends a message to the tunnel channel -func (n *network) sendMsg(method string, msg proto.Message, channel string) error { - body, err := proto.Marshal(msg) - if err != nil { - return err - } - // create transport message and chuck it down the pipe - m := transport.Message{ - Header: map[string]string{ - "Micro-Method": method, - }, - Body: body, - } - - // check if the channel client is initialized - n.RLock() - client, ok := n.tunClient[channel] - if !ok || client == nil { - n.RUnlock() - return ErrClientNotFound - } - n.RUnlock() - - log.Debugf("Network sending %s message from: %s", method, n.options.Id) - if err := client.Send(&m); err != nil { - return err - } - - return nil -} - -// announce announces node peers to the network -func (n *network) announce(client transport.Client) { - announce := time.NewTicker(AnnounceTime) - defer announce.Stop() - - for { - select { - case <-n.closed: - return - case <-announce.C: - msg := PeersToProto(n.node, MaxDepth) - // advertise yourself to the network - if err := n.sendMsg("peer", msg, NetworkChannel); err != nil { - log.Debugf("Network failed to advertise peers: %v", err) - continue - } - } - } -} - // pruneRoutes prunes routes return by given query func (n *network) pruneRoutes(q ...router.QueryOption) error { routes, err := n.router.Table().Query(q...) @@ -585,9 +593,12 @@ func (n *network) prunePeerRoutes(peer *node) error { return nil } -// prune deltes node peers that have not been seen for longer than PruneTime seconds -// prune also removes all the routes either originated by or routable by the stale nodes -func (n *network) prune() { +// manage the process of announcing to peers and prune any peer nodes that have not been +// seen for a period of time. Also removes all the routes either originated by or routable +//by the stale nodes +func (n *network) manage() { + announce := time.NewTicker(AnnounceTime) + defer announce.Stop() prune := time.NewTicker(PruneTime) defer prune.Stop() @@ -595,8 +606,14 @@ func (n *network) prune() { select { case <-n.closed: return + case <-announce.C: + msg := PeersToProto(n.node, MaxDepth) + // advertise yourself to the network + if err := n.sendMsg("peer", NetworkChannel, msg); err != nil { + log.Debugf("Network failed to advertise peers: %v", err) + } case <-prune.C: - pruned := n.PruneStalePeerNodes(PruneTime) + pruned := n.PruneStalePeers(PruneTime) for id, peer := range pruned { log.Debugf("Network peer exceeded prune time: %s", id) n.Lock() @@ -606,29 +623,90 @@ func (n *network) prune() { log.Debugf("Network failed pruning peer %s routes: %v", id, err) } } + // get a list of all routes routes, err := n.options.Router.Table().List() if err != nil { log.Debugf("Network failed listing routes when pruning peers: %v", err) continue } + // collect all the router IDs in the routing table routers := make(map[string]bool) + for _, route := range routes { - if _, ok := routers[route.Router]; !ok { - routers[route.Router] = true - // if the router is NOT in our peer graph, delete all routes originated by it - if peerNode := n.node.GetPeerNode(route.Router); peerNode == nil { - if err := n.pruneRoutes(router.QueryRouter(route.Router)); err != nil { - log.Debugf("Network failed deleting routes by %s: %v", route.Router, err) - } - } + // check if its been processed + if _, ok := routers[route.Router]; ok { + continue + } + + // mark as processed + routers[route.Router] = true + + // if the router is NOT in our peer graph, delete all routes originated by it + if peer := n.node.GetPeerNode(route.Router); peer != nil { + continue + } + + if err := n.pruneRoutes(router.QueryRouter(route.Router)); err != nil { + log.Debugf("Network failed deleting routes by %s: %v", route.Router, err) } } } } } +// sendTo sends a message to a specific node as a one off. +// we need this because when links die, we have no discovery info, +// and sending to an existing multicast link doesn't immediately work +func (n *network) sendTo(method, channel, peer string, msg proto.Message) error { + body, err := proto.Marshal(msg) + if err != nil { + return err + } + c, err := n.tunnel.Dial(channel, tunnel.DialMode(tunnel.Multicast)) + if err != nil { + return err + } + defer c.Close() + + log.Debugf("Network sending %s message from: %s to %s", method, n.options.Id, peer) + + return c.Send(&transport.Message{ + Header: map[string]string{ + "Micro-Method": method, + "Micro-Peer": peer, + }, + Body: body, + }) +} + +// sendMsg sends a message to the tunnel channel +func (n *network) sendMsg(method, channel string, msg proto.Message) error { + body, err := proto.Marshal(msg) + if err != nil { + return err + } + + // check if the channel client is initialized + n.RLock() + client, ok := n.tunClient[channel] + if !ok || client == nil { + n.RUnlock() + return ErrClientNotFound + } + n.RUnlock() + + log.Debugf("Network sending %s message from: %s", method, n.options.Id) + + return client.Send(&transport.Message{ + Header: map[string]string{ + "Micro-Method": method, + }, + Body: body, + }) +} + // handleCtrlConn handles ControlChannel connections func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { for { @@ -642,6 +720,14 @@ func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { continue } + // check if peer is set + peer := m.Header["Micro-Peer"] + + // check who the message is intended for + if len(peer) > 0 && peer != n.options.Id { + continue + } + select { case msg <- &message{ msg: m, @@ -770,15 +856,19 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { switch m.msg.Header["Micro-Method"] { case "advert": pbRtrAdvert := &pbRtr.Advert{} + if err := proto.Unmarshal(m.msg.Body, pbRtrAdvert); err != nil { log.Debugf("Network fail to unmarshal advert message: %v", err) continue } + // don't process your own messages if pbRtrAdvert.Id == n.options.Id { continue } + log.Debugf("Network received advert message from: %s", pbRtrAdvert.Id) + // loookup advertising node in our peer topology advertNode := n.node.GetPeerNode(pbRtrAdvert.Id) if advertNode == nil { @@ -788,6 +878,7 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { } var events []*router.Event + for _, event := range pbRtrAdvert.Events { // we know the advertising node is not the origin of the route if pbRtrAdvert.Id != event.Route.Router { @@ -798,6 +889,7 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { continue } } + route := router.Route{ Service: event.Route.Service, Address: event.Route.Address, @@ -807,6 +899,7 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { Link: event.Route.Link, Metric: event.Route.Metric, } + // calculate route metric and add to the advertised metric // we need to make sure we do not overflow math.MaxInt64 metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link) @@ -829,11 +922,13 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { } events = append(events, e) } + // if no events are eligible for processing continue if len(events) == 0 { log.Tracef("Network no events to be processed by router: %s", n.options.Id) continue } + // create an advert and process it advert := &router.Advert{ Id: pbRtrAdvert.Id, @@ -853,16 +948,27 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { log.Debugf("Network fail to unmarshal solicit message: %v", err) continue } + log.Debugf("Network received solicit message from: %s", pbRtrSolicit.Id) + // ignore solicitation when requested by you if pbRtrSolicit.Id == n.options.Id { continue } + log.Debugf("Network router flushing routes for: %s", pbRtrSolicit.Id) + // advertise all the routes when a new node has connected if err := n.router.Solicit(); err != nil { log.Debugf("Network failed to solicit routes: %s", err) } + + // specify that someone solicited the route + select { + case n.solicited <- pbRtrSolicit.Id: + default: + // don't block + } } case <-n.closed: return @@ -879,6 +985,7 @@ func (n *network) advertise(advertChan <-chan *router.Advert) { case advert := <-advertChan: // create a proto advert var events []*pbRtr.Event + for _, event := range advert.Events { // the routes service address address := event.Route.Address @@ -912,16 +1019,33 @@ func (n *network) advertise(advertChan <-chan *router.Advert) { } events = append(events, e) } + msg := &pbRtr.Advert{ Id: advert.Id, Type: pbRtr.AdvertType(advert.Type), Timestamp: advert.Timestamp.UnixNano(), Events: events, } - if err := n.sendMsg("advert", msg, ControlChannel); err != nil { - log.Debugf("Network failed to advertise routes: %v", err) + + // send the advert to all on the control channel + // since its not a solicitation + if advert.Type != router.Solicitation { + if err := n.sendMsg("advert", ControlChannel, msg); err != nil { + log.Debugf("Network failed to advertise routes: %v", err) + } continue } + + // it's a solication, someone asked for it + // so we're going to pick off the node and send it + select { + case node := <-n.solicited: + // someone requested the route + n.sendTo("advert", ControlChannel, node, msg) + default: + // send to all since we can't get anything + n.sendMsg("advert", ControlChannel, msg) + } case <-n.closed: return } @@ -939,41 +1063,87 @@ func (n *network) sendConnect() { Address: n.node.address, }, } - if err := n.sendMsg("connect", msg, NetworkChannel); err != nil { + + if err := n.sendMsg("connect", NetworkChannel, msg); err != nil { log.Debugf("Network failed to send connect message: %s", err) } } -// connect will wait for a link to be established +// connect will wait for a link to be established and send the connect +// message. We're trying to ensure convergence pretty quickly. So we want +// to hear back. In the case we become completely disconnected we'll +// connect again once a new link is established func (n *network) connect() { - // wait for connected state - var connected bool + // discovered lets us know what we received a peer message back + var discovered bool + var attempts int + + // our advertise address + loopback := n.server.Options().Advertise + // actual address + address := n.tunnel.Address() for { - // check the links + // connected is used to define if the link is connected + var connected bool + + // check the links state for _, link := range n.tunnel.Links() { + // skip loopback + if link.Loopback() { + continue + } + + // if remote is ourselves + switch link.Remote() { + case loopback, address: + continue + } + if link.State() == "connected" { connected = true break } } - // if we're not conencted wait + // if we're not connected wait if !connected { + // reset discovered + discovered = false + // sleep for a second time.Sleep(time.Second) + // now try again continue } - // send the connect message - n.sendConnect() + // we're connected but are we discovered? + if !discovered { + // recreate the clients because all the tunnel links are gone + // so we haven't send discovery beneath + if err := n.createClients(); err != nil { + log.Debugf("Failed to recreate network/control clients: %v", err) + continue + } - // check the announce channel + // send the connect message + n.sendConnect() + } + + // check if we've been discovered select { - case <-n.announced: + case <-n.discovered: + discovered = true + attempts = 0 + case <-n.closed: return - default: - time.Sleep(time.Second) - // we have to go again + case <-time.After(time.Second + backoff.Do(attempts)): + // we have to try again + attempts++ + + // reset attempts 5 == ~2mins + if attempts > 5 { + attempts = 0 + } } } } @@ -982,18 +1152,18 @@ func (n *network) connect() { func (n *network) Connect() error { n.Lock() - // try to resolve network nodes - nodes, err := n.resolveNodes() - if err != nil { - log.Debugf("Network failed to resolve nodes: %v", err) - } - // connect network tunnel if err := n.tunnel.Connect(); err != nil { n.Unlock() return err } + // try to resolve network nodes + nodes, err := n.resolveNodes() + if err != nil { + log.Debugf("Network failed to resolve nodes: %v", err) + } + // initialize the tunnel to resolved nodes n.tunnel.Init( tunnel.Nodes(nodes...), @@ -1048,8 +1218,6 @@ func (n *network) Connect() error { // create closed channel n.closed = make(chan bool) - // create new announced channel - n.announced = make(chan bool) // start the router if err := n.options.Router.Start(); err != nil { @@ -1073,16 +1241,14 @@ func (n *network) Connect() error { // send connect after there's a link established go n.connect() - // go resolving network nodes + // resolve network nodes and re-init the tunnel go n.resolve() - // broadcast peers - go n.announce(netClient) - // prune stale nodes - go n.prune() - // listen to network messages - go n.processNetChan(netListener) + // broadcast announcements and prune stale nodes + go n.manage() // advertise service routes go n.advertise(advertChan) + // listen to network messages + go n.processNetChan(netListener) // accept and process routes go n.processCtrlChan(ctrlListener) @@ -1112,6 +1278,40 @@ func (n *network) close() error { return nil } +// createClients is used to create new clients in the event we lose all the tunnels +func (n *network) createClients() error { + // dial into ControlChannel to send route adverts + ctrlClient, err := n.tunnel.Dial(ControlChannel, tunnel.DialMode(tunnel.Multicast)) + if err != nil { + return err + } + + // dial into NetworkChannel to send network messages + netClient, err := n.tunnel.Dial(NetworkChannel, tunnel.DialMode(tunnel.Multicast)) + if err != nil { + return err + } + + n.Lock() + defer n.Unlock() + + // set the control client + c, ok := n.tunClient[ControlChannel] + if ok { + c.Close() + } + n.tunClient[ControlChannel] = ctrlClient + + // set the network client + c, ok = n.tunClient[NetworkChannel] + if ok { + c.Close() + } + n.tunClient[NetworkChannel] = netClient + + return nil +} + // Close closes network connection func (n *network) Close() error { n.Lock() @@ -1140,7 +1340,7 @@ func (n *network) Close() error { Address: n.node.address, }, } - if err := n.sendMsg("close", msg, NetworkChannel); err != nil { + if err := n.sendMsg("close", NetworkChannel, msg); err != nil { log.Debugf("Network failed to send close message: %s", err) } } diff --git a/network/network.go b/network/network.go index 08a45665..8f71709c 100644 --- a/network/network.go +++ b/network/network.go @@ -56,14 +56,6 @@ type Network interface { Server() server.Server } -// message is network message -type message struct { - // msg is transport message - msg *transport.Message - // session is tunnel session - session tunnel.Session -} - // NewNetwork returns a new network interface func NewNetwork(opts ...Option) Network { return newNetwork(opts...) diff --git a/network/node.go b/network/node.go index f0d3809c..f1a51b7d 100644 --- a/network/node.go +++ b/network/node.go @@ -216,7 +216,7 @@ func (n *node) DeletePeerNode(id string) error { // PruneStalePeerNodes prune the peers that have not been seen for longer than given time // It returns a map of the the nodes that got pruned -func (n *node) PruneStalePeerNodes(pruneTime time.Duration) map[string]*node { +func (n *node) PruneStalePeers(pruneTime time.Duration) map[string]*node { n.Lock() defer n.Unlock() diff --git a/network/node_test.go b/network/node_test.go index 80a41c70..71b21a19 100644 --- a/network/node_test.go +++ b/network/node_test.go @@ -225,7 +225,7 @@ func TestPruneStalePeerNodes(t *testing.T) { time.Sleep(pruneTime) // should delete all nodes besides node - pruned := node.PruneStalePeerNodes(pruneTime) + pruned := node.PruneStalePeers(pruneTime) if len(pruned) != len(nodes)-1 { t.Errorf("Expected pruned node count: %d, got: %d", len(nodes)-1, len(pruned)) diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index 0e04c7d6..a7cf5bd6 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -83,7 +83,8 @@ func readLoop(r server.Request, s client.Stream) error { // toNodes returns a list of node addresses from given routes func toNodes(routes []router.Route) []string { - nodes := make([]string, len(routes)) + nodes := make([]string, 0, len(routes)) + for _, node := range routes { address := node.Address if len(node.Gateway) > 0 { @@ -91,11 +92,13 @@ func toNodes(routes []router.Route) []string { } nodes = append(nodes, address) } + return nodes } func toSlice(r map[uint64]router.Route) []router.Route { routes := make([]router.Route, 0, len(r)) + for _, v := range r { routes = append(routes, v) } @@ -161,6 +164,8 @@ func (p *Proxy) filterRoutes(ctx context.Context, routes []router.Route) []route filteredRoutes = append(filteredRoutes, route) } + log.Tracef("Proxy filtered routes %+v vs %+v\n", routes, filteredRoutes) + return filteredRoutes } @@ -225,13 +230,15 @@ func (p *Proxy) cacheRoutes(service string) ([]router.Route, error) { // refreshMetrics will refresh any metrics for our local cached routes. // we may not receive new watch events for these as they change. func (p *Proxy) refreshMetrics() { - services := make([]string, 0, len(p.Routes)) - // get a list of services to update p.RLock() + + services := make([]string, 0, len(p.Routes)) + for service := range p.Routes { services = append(services, service) } + p.RUnlock() // get and cache the routes for the service @@ -246,6 +253,8 @@ func (p *Proxy) manageRoutes(route router.Route, action string) error { p.Lock() defer p.Unlock() + log.Tracef("Proxy taking route action %v %+v\n", action, route) + switch action { case "create", "update": if _, ok := p.Routes[route.Service]; !ok { @@ -253,7 +262,12 @@ func (p *Proxy) manageRoutes(route router.Route, action string) error { } p.Routes[route.Service][route.Hash()] = route case "delete": + // delete that specific route delete(p.Routes[route.Service], route.Hash()) + // clean up the cache entirely + if len(p.Routes[route.Service]) == 0 { + delete(p.Routes, route.Service) + } default: return fmt.Errorf("unknown action: %s", action) } @@ -288,7 +302,7 @@ func (p *Proxy) ProcessMessage(ctx context.Context, msg server.Message) error { // TODO: check that we're not broadcast storming by sending to the same topic // that we're actually subscribed to - log.Tracef("Received message for %s", msg.Topic()) + log.Tracef("Proxy received message for %s", msg.Topic()) var errors []string @@ -329,7 +343,7 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server return errors.BadRequest("go.micro.proxy", "service name is blank") } - log.Tracef("Received request for %s", service) + log.Tracef("Proxy received request for %s", service) // are we network routing or local routing if len(p.Links) == 0 { @@ -363,15 +377,17 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server } //nolint:prealloc - var opts []client.CallOption - - // set strategy to round robin - opts = append(opts, client.WithSelectOption(selector.WithStrategy(selector.RoundRobin))) + opts := []client.CallOption{ + // set strategy to round robin + client.WithSelectOption(selector.WithStrategy(selector.RoundRobin)), + } // if the address is already set just serve it // TODO: figure it out if we should know to pick a link if len(addresses) > 0 { - opts = append(opts, client.WithAddress(addresses...)) + opts = append(opts, + client.WithAddress(addresses...), + ) // serve the normal way return p.serveRequest(ctx, p.Client, service, endpoint, req, rsp, opts...) @@ -387,10 +403,16 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server opts = append(opts, client.WithAddress(addresses...)) } + log.Tracef("Proxy calling %+v\n", addresses) // serve the normal way return p.serveRequest(ctx, p.Client, service, endpoint, req, rsp, opts...) } + // we're assuming we need routes to operate on + if len(routes) == 0 { + return errors.InternalServerError("go.micro.proxy", "route not found") + } + var gerr error // we're routing globally with multiple links @@ -404,11 +426,16 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server continue } - log.Debugf("Proxy using route %+v\n", route) + log.Tracef("Proxy using route %+v\n", route) // set the address to call addresses := toNodes([]router.Route{route}) - opts = append(opts, client.WithAddress(addresses...)) + // set the address in the options + // disable retries since its one route processing + opts = append(opts, + client.WithAddress(addresses...), + client.WithRetries(0), + ) // do the request with the link gerr = p.serveRequest(ctx, link, service, endpoint, req, rsp, opts...) @@ -558,7 +585,9 @@ func NewProxy(opts ...options.Option) proxy.Proxy { }() go func() { - t := time.NewTicker(time.Minute) + // TODO: speed up refreshing of metrics + // without this ticking effort e.g stream + t := time.NewTicker(time.Second * 10) defer t.Stop() // we must refresh route metrics since they do not trigger new events diff --git a/router/default.go b/router/default.go index b0739ebf..02ceac1b 100644 --- a/router/default.go +++ b/router/default.go @@ -799,7 +799,8 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { // build a list of events to advertise events := make([]*Event, len(bestRoutes)) - i := 0 + var i int + for _, route := range bestRoutes { event := &Event{ Type: evType, @@ -823,9 +824,10 @@ func (r *router) Solicit() error { // advertise the routes r.advertWg.Add(1) + go func() { - defer r.advertWg.Done() - r.publishAdvert(RouteUpdate, events) + r.publishAdvert(Solicitation, events) + r.advertWg.Done() }() return nil diff --git a/router/router.go b/router/router.go index e6018766..7758817c 100644 --- a/router/router.go +++ b/router/router.go @@ -111,6 +111,8 @@ const ( Announce AdvertType = iota // RouteUpdate advertises route updates RouteUpdate + // Solicitation indicates routes were solicited + Solicitation ) // String returns human readable advertisement type @@ -120,6 +122,8 @@ func (t AdvertType) String() string { return "announce" case RouteUpdate: return "update" + case Solicitation: + return "solicitation" default: return "unknown" } diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 342110aa..53d552f4 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -86,24 +86,18 @@ func getHeader(hdr string, md map[string]string) string { } func getHeaders(m *codec.Message) { - get := func(hdr, v string) string { + set := func(v, hdr string) string { if len(v) > 0 { return v } - - if hd := m.Header[hdr]; len(hd) > 0 { - return hd - } - - // old - return m.Header["X-"+hdr] + return m.Header[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) + m.Id = set(m.Id, "Micro-Id") + m.Error = set(m.Error, "Micro-Error") + m.Endpoint = set(m.Endpoint, "Micro-Endpoint") + m.Method = set(m.Method, "Micro-Method") + m.Target = set(m.Target, "Micro-Service") // TODO: remove this cruft if len(m.Endpoint) == 0 { @@ -321,7 +315,6 @@ 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 { diff --git a/server/rpc_server.go b/server/rpc_server.go index 191bf1e8..d23401c8 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -549,6 +549,7 @@ func (s *rpcServer) Register() error { node.Metadata["protocol"] = "mucp" s.RLock() + // Maps are ordered randomly, sort the keys for consistency var handlerList []string for n, e := range s.handlers { @@ -557,6 +558,7 @@ func (s *rpcServer) Register() error { handlerList = append(handlerList, n) } } + sort.Strings(handlerList) var subscriberList []Subscriber @@ -566,18 +568,20 @@ func (s *rpcServer) Register() error { subscriberList = append(subscriberList, e) } } + sort.Slice(subscriberList, func(i, j int) bool { return subscriberList[i].Topic() > subscriberList[j].Topic() }) endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList)) + for _, n := range handlerList { endpoints = append(endpoints, s.handlers[n].Endpoints()...) } + for _, e := range subscriberList { endpoints = append(endpoints, e.Endpoints()...) } - s.RUnlock() service := ®istry.Service{ Name: config.Name, @@ -586,9 +590,10 @@ func (s *rpcServer) Register() error { Endpoints: endpoints, } - s.Lock() + // get registered value registered := s.registered - s.Unlock() + + s.RUnlock() if !registered { log.Logf("Registry [%s] Registering node: %s", config.Registry.String(), node.Id) @@ -610,6 +615,8 @@ func (s *rpcServer) Register() error { defer s.Unlock() s.registered = true + // set what we're advertising + s.opts.Advertise = addr // subscribe to the topic with own name sub, err := s.opts.Broker.Subscribe(config.Name, s.HandleEvent) diff --git a/service.go b/service.go index 915e6512..efddd0a4 100644 --- a/service.go +++ b/service.go @@ -9,9 +9,9 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/config/cmd" - "github.com/micro/go-micro/debug/service/handler" "github.com/micro/go-micro/debug/profile" "github.com/micro/go-micro/debug/profile/pprof" + "github.com/micro/go-micro/debug/service/handler" "github.com/micro/go-micro/plugin" "github.com/micro/go-micro/server" "github.com/micro/go-micro/util/log" diff --git a/tunnel/default.go b/tunnel/default.go index 6b1b9151..5943757f 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -327,6 +327,7 @@ func (t *tun) process() { // and the message is being sent outbound via // a dialled connection don't use this link if loopback && msg.outbound { + log.Tracef("Link for node %s is loopback", node) err = errors.New("link is loopback") continue } @@ -334,6 +335,7 @@ func (t *tun) process() { // if the message was being returned by the loopback listener // send it back up the loopback link only if msg.loopback && !loopback { + log.Tracef("Link for message %s is loopback", node) err = errors.New("link is not loopback") continue } @@ -363,7 +365,7 @@ func (t *tun) process() { // send the message for _, link := range sendTo { // send the message via the current link - log.Tracef("Sending %+v to %s", newMsg.Header, link.Remote()) + log.Tracef("Tunnel sending %+v to %s", newMsg.Header, link.Remote()) if errr := link.Send(newMsg); errr != nil { log.Debugf("Tunnel error sending %+v to %s: %v", newMsg.Header, link.Remote(), errr) @@ -502,6 +504,7 @@ func (t *tun) listen(link *link) { // nothing more to do continue case "close": + log.Debugf("Tunnel link %s received close message", link.Remote()) // if there is no channel then we close the link // as its a signal from the other side to close the connection if len(channel) == 0 { @@ -555,9 +558,11 @@ func (t *tun) listen(link *link) { // a continued session case "session": // process message - log.Tracef("Received %+v from %s", msg.Header, link.Remote()) + log.Tracef("Tunnel received %+v from %s", msg.Header, link.Remote()) // an announcement of a channel listener case "announce": + log.Tracef("Tunnel received %+v from %s", msg.Header, link.Remote()) + // process the announcement channels := strings.Split(channel, ",") @@ -629,7 +634,7 @@ func (t *tun) listen(link *link) { s, exists = t.getSession(channel, "listener") // only return accept to the session case mtype == "accept": - log.Debugf("Received accept message for channel: %s session: %s", channel, sessionId) + log.Debugf("Tunnel received accept message for channel: %s session: %s", channel, sessionId) s, exists = t.getSession(channel, sessionId) if exists && s.accepted { continue @@ -649,7 +654,7 @@ func (t *tun) listen(link *link) { // bail if no session or listener has been found if !exists { - log.Debugf("Tunnel skipping no channel: %s session: %s exists", channel, sessionId) + log.Tracef("Tunnel skipping no channel: %s session: %s exists", channel, sessionId) // drop it, we don't care about // messages we don't know about continue @@ -665,7 +670,7 @@ func (t *tun) listen(link *link) { // otherwise process } - log.Debugf("Tunnel using channel: %s session: %s type: %s", s.channel, s.session, mtype) + log.Tracef("Tunnel using channel: %s session: %s type: %s", s.channel, s.session, mtype) // construct a new transport message tmsg := &transport.Message{ @@ -740,7 +745,7 @@ func (t *tun) keepalive(link *link) { "Micro-Tunnel-Id": t.id, }, }); err != nil { - log.Debugf("Error sending keepalive to link %v: %v", link.Remote(), err) + log.Debugf("Tunnel error sending keepalive to link %v: %v", link.Remote(), err) t.delLink(link.Remote()) return } diff --git a/tunnel/link.go b/tunnel/link.go index 042f1cb9..a7367812 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -2,6 +2,7 @@ package tunnel import ( "bytes" + "errors" "io" "sync" "time" @@ -14,7 +15,11 @@ import ( type link struct { transport.Socket + // transport to use for connections + transport transport.Transport + sync.RWMutex + // stops the link closed chan bool // link state channel for testing link @@ -65,6 +70,8 @@ var ( linkRequest = []byte{0, 0, 0, 0} // the 4 byte 1 filled packet sent to determine link state linkResponse = []byte{1, 1, 1, 1} + + ErrLinkConnectTimeout = errors.New("link connect timeout") ) func newLink(s transport.Socket) *link { @@ -72,8 +79,8 @@ func newLink(s transport.Socket) *link { Socket: s, id: uuid.New().String(), lastKeepAlive: time.Now(), - channels: make(map[string]time.Time), closed: make(chan bool), + channels: make(map[string]time.Time), state: make(chan *packet, 64), sendQueue: make(chan *packet, 128), recvQueue: make(chan *packet, 128), @@ -87,6 +94,32 @@ func newLink(s transport.Socket) *link { return l } +func (l *link) connect(addr string) error { + c, err := l.transport.Dial(addr) + if err != nil { + return err + } + + l.Lock() + l.Socket = c + l.Unlock() + + return nil +} + +func (l *link) accept(sock transport.Socket) error { + l.Lock() + l.Socket = sock + l.Unlock() + return nil +} + +func (l *link) setLoopback(v bool) { + l.Lock() + l.loopback = v + l.Unlock() +} + // setRate sets the bits per second rate as a float64 func (l *link) setRate(bits int64, delta time.Duration) { // rate of send in bits per nanosecond @@ -201,11 +234,15 @@ func (l *link) manage() { t := time.NewTicker(time.Minute) defer t.Stop() + // get link id + linkId := l.Id() + // used to send link state packets send := func(b []byte) error { return l.Send(&transport.Message{ Header: map[string]string{ - "Micro-Method": "link", + "Micro-Method": "link", + "Micro-Link-Id": linkId, }, Body: b, }) } @@ -229,9 +266,7 @@ func (l *link) manage() { // check the type of message switch { case bytes.Equal(p.message.Body, linkRequest): - l.RLock() - log.Tracef("Link %s received link request %v", l.id, p.message.Body) - l.RUnlock() + log.Tracef("Link %s received link request", linkId) // send response if err := send(linkResponse); err != nil { @@ -242,9 +277,7 @@ func (l *link) manage() { case bytes.Equal(p.message.Body, linkResponse): // set round trip time d := time.Since(now) - l.RLock() - log.Tracef("Link %s received link response in %v", p.message.Body, d) - l.RUnlock() + log.Tracef("Link %s received link response in %v", linkId, d) // set the RTT l.setRTT(d) } @@ -309,6 +342,12 @@ func (l *link) Rate() float64 { return l.rate } +func (l *link) Loopback() bool { + l.RLock() + defer l.RUnlock() + return l.loopback +} + // Length returns the roundtrip time as nanoseconds (lower is better). // Returns 0 where no measurement has been taken. func (l *link) Length() int64 { @@ -320,7 +359,6 @@ func (l *link) Length() int64 { func (l *link) Id() string { l.RLock() defer l.RUnlock() - return l.id } diff --git a/tunnel/listener.go b/tunnel/listener.go index ec435b03..288b7dac 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -80,7 +80,7 @@ func (t *tunListener) process() { // get a session sess, ok := conns[sessionId] - log.Debugf("Tunnel listener received channel %s session %s type %s exists: %t", m.channel, sessionId, m.typ, ok) + log.Tracef("Tunnel listener received channel %s session %s type %s exists: %t", m.channel, sessionId, m.typ, ok) if !ok { // we only process open and session types switch m.typ { @@ -159,7 +159,7 @@ func (t *tunListener) process() { case <-sess.closed: delete(conns, sessionId) case sess.recv <- m: - log.Debugf("Tunnel listener sent to recv chan channel %s session %s type %s", m.channel, sessionId, m.typ) + log.Tracef("Tunnel listener sent to recv chan channel %s session %s type %s", m.channel, sessionId, m.typ) } } } diff --git a/tunnel/session.go b/tunnel/session.go index 3cb37c61..e545d316 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -356,11 +356,11 @@ func (s *session) Recv(m *transport.Message) error { } //log.Tracef("Received %+v from recv backlog", msg) - log.Debugf("Received %+v from recv backlog", msg) + log.Tracef("Received %+v from recv backlog", msg) // decrypt the received payload using the token // we have to used msg.session because multicast has a shared - // session id of "multicast" in this session struct on + // session id of "multicast" in this session struct on // the listener side body, err := Decrypt(msg.data.Body, s.token+s.channel+msg.session) if err != nil { diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 56928d8d..abd61cb4 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -64,7 +64,9 @@ type Link interface { Length() int64 // Current transfer rate as bits per second (lower is better) Rate() float64 - // State of the link e.g connected/closed + // Is this a loopback link + Loopback() bool + // State of the link: connected/closed/error State() string // honours transport socket transport.Socket From 9bd0fb91255ac3634704897e040de34689dd534f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 7 Dec 2019 23:28:39 +0000 Subject: [PATCH 321/344] save changes --- network/default.go | 119 ++++++++++--------- network/network.go | 2 - network/options.go | 10 +- network/resolver/dns/dns.go | 21 +++- network/service/handler/handler.go | 4 +- tunnel/default.go | 181 +++++++++++++++-------------- tunnel/listener.go | 26 ++--- tunnel/options.go | 29 +++-- tunnel/session.go | 41 ++++--- tunnel/tunnel.go | 2 + 10 files changed, 239 insertions(+), 196 deletions(-) diff --git a/network/default.go b/network/default.go index 26789436..83557592 100644 --- a/network/default.go +++ b/network/default.go @@ -234,7 +234,7 @@ func (n *network) resolveNodes() ([]string, error) { dns := &dns.Resolver{} // append seed nodes if we have them - for _, node := range n.options.Peers { + for _, node := range n.options.Nodes { // resolve anything that looks like a host name records, err := dns.Resolve(node) if err != nil { @@ -282,7 +282,8 @@ func (n *network) handleNetConn(s tunnel.Session, msg chan *message) { m := new(transport.Message) if err := s.Recv(m); err != nil { log.Debugf("Network tunnel [%s] receive error: %v", NetworkChannel, err) - if err == io.EOF { + switch err { + case io.EOF, tunnel.ErrReadTimeout: s.Close() return } @@ -338,39 +339,10 @@ func (n *network) acceptNetConn(l tunnel.Listener, recv chan *message) { } } -// updatePeerLinks updates link for a given peer -func (n *network) updatePeerLinks(peerAddr string, linkId string) error { - n.Lock() - defer n.Unlock() - log.Tracef("Network looking up link %s in the peer links", linkId) - // lookup the peer link - var peerLink tunnel.Link - for _, link := range n.tunnel.Links() { - if link.Id() == linkId { - peerLink = link - break - } - } - if peerLink == nil { - return ErrPeerLinkNotFound - } - // if the peerLink is found in the returned links update peerLinks - log.Tracef("Network updating peer links for peer %s", peerAddr) - // add peerLink to the peerLinks map - if link, ok := n.peerLinks[peerAddr]; ok { - // if the existing has better Length then the new, replace it - if link.Length() < peerLink.Length() { - n.peerLinks[peerAddr] = peerLink - } - } else { - n.peerLinks[peerAddr] = peerLink - } - - return nil -} - // processNetChan processes messages received on NetworkChannel func (n *network) processNetChan(listener tunnel.Listener) { + defer listener.Close() + // receive network message queue recv := make(chan *message, 128) @@ -707,13 +679,51 @@ func (n *network) sendMsg(method, channel string, msg proto.Message) error { }) } +// updatePeerLinks updates link for a given peer +func (n *network) updatePeerLinks(peerAddr string, linkId string) error { + n.Lock() + defer n.Unlock() + + log.Tracef("Network looking up link %s in the peer links", linkId) + + // lookup the peer link + var peerLink tunnel.Link + + for _, link := range n.tunnel.Links() { + if link.Id() == linkId { + peerLink = link + break + } + } + + if peerLink == nil { + return ErrPeerLinkNotFound + } + + // if the peerLink is found in the returned links update peerLinks + log.Tracef("Network updating peer links for peer %s", peerAddr) + + // add peerLink to the peerLinks map + if link, ok := n.peerLinks[peerAddr]; ok { + // if the existing has better Length then the new, replace it + if link.Length() < peerLink.Length() { + n.peerLinks[peerAddr] = peerLink + } + } else { + n.peerLinks[peerAddr] = peerLink + } + + return nil +} + // handleCtrlConn handles ControlChannel connections func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { for { m := new(transport.Message) if err := s.Recv(m); err != nil { log.Debugf("Network tunnel [%s] receive error: %v", ControlChannel, err) - if err == io.EOF { + switch err { + case io.EOF, tunnel.ErrReadTimeout: s.Close() return } @@ -843,6 +853,8 @@ func (n *network) getRouteMetric(router string, gateway string, link string) int // processCtrlChan processes messages received on ControlChannel func (n *network) processCtrlChan(listener tunnel.Listener) { + defer listener.Close() + // receive control message queue recv := make(chan *message, 128) @@ -1151,12 +1163,7 @@ func (n *network) connect() { // Connect connects the network func (n *network) Connect() error { n.Lock() - - // connect network tunnel - if err := n.tunnel.Connect(); err != nil { - n.Unlock() - return err - } + defer n.Unlock() // try to resolve network nodes nodes, err := n.resolveNodes() @@ -1169,10 +1176,14 @@ func (n *network) Connect() error { tunnel.Nodes(nodes...), ) + // connect network tunnel + if err := n.tunnel.Connect(); err != nil { + n.Unlock() + return err + } + // return if already connected if n.connected { - // unlock first - n.Unlock() // send the connect message n.sendConnect() return nil @@ -1187,32 +1198,36 @@ func (n *network) Connect() error { // dial into ControlChannel to send route adverts ctrlClient, err := n.tunnel.Dial(ControlChannel, tunnel.DialMode(tunnel.Multicast)) if err != nil { - n.Unlock() return err } n.tunClient[ControlChannel] = ctrlClient // listen on ControlChannel - ctrlListener, err := n.tunnel.Listen(ControlChannel, tunnel.ListenMode(tunnel.Multicast)) + ctrlListener, err := n.tunnel.Listen( + ControlChannel, + tunnel.ListenMode(tunnel.Multicast), + tunnel.ListenTimeout(router.AdvertiseTableTick*2), + ) if err != nil { - n.Unlock() return err } // dial into NetworkChannel to send network messages netClient, err := n.tunnel.Dial(NetworkChannel, tunnel.DialMode(tunnel.Multicast)) if err != nil { - n.Unlock() return err } n.tunClient[NetworkChannel] = netClient // listen on NetworkChannel - netListener, err := n.tunnel.Listen(NetworkChannel, tunnel.ListenMode(tunnel.Multicast)) + netListener, err := n.tunnel.Listen( + NetworkChannel, + tunnel.ListenMode(tunnel.Multicast), + tunnel.ListenTimeout(AnnounceTime*2), + ) if err != nil { - n.Unlock() return err } @@ -1221,23 +1236,19 @@ func (n *network) Connect() error { // start the router if err := n.options.Router.Start(); err != nil { - n.Unlock() return err } // start advertising routes advertChan, err := n.options.Router.Advertise() if err != nil { - n.Unlock() return err } // start the server if err := n.server.Start(); err != nil { - n.Unlock() return err } - n.Unlock() // send connect after there's a link established go n.connect() @@ -1252,9 +1263,8 @@ func (n *network) Connect() error { // accept and process routes go n.processCtrlChan(ctrlListener) - n.Lock() + // we're now connected n.connected = true - n.Unlock() return nil } @@ -1340,6 +1350,7 @@ func (n *network) Close() error { Address: n.node.address, }, } + if err := n.sendMsg("close", NetworkChannel, msg); err != nil { log.Debugf("Network failed to send close message: %s", err) } diff --git a/network/network.go b/network/network.go index 8f71709c..e927241b 100644 --- a/network/network.go +++ b/network/network.go @@ -6,8 +6,6 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/server" - "github.com/micro/go-micro/transport" - "github.com/micro/go-micro/tunnel" ) var ( diff --git a/network/options.go b/network/options.go index 0a3c5b2b..63ff6fe7 100644 --- a/network/options.go +++ b/network/options.go @@ -22,8 +22,8 @@ type Options struct { Address string // Advertise sets the address to advertise Advertise string - // Peers is a list of peers to connect to - Peers []string + // Nodes is a list of nodes to connect to + Nodes []string // Tunnel is network tunnel Tunnel tunnel.Tunnel // Router is network router @@ -62,10 +62,10 @@ func Advertise(a string) Option { } } -// Peers is a list of peers to connect to -func Peers(n ...string) Option { +// Nodes is a list of nodes to connect to +func Nodes(n ...string) Option { return func(o *Options) { - o.Peers = n + o.Nodes = n } } diff --git a/network/resolver/dns/dns.go b/network/resolver/dns/dns.go index b4029f06..a8d27b06 100644 --- a/network/resolver/dns/dns.go +++ b/network/resolver/dns/dns.go @@ -31,6 +31,17 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { r.Address = "1.0.0.1:53" } + //nolint:prealloc + var records []*resolver.Record + + // parsed an actual ip + if v := net.ParseIP(host); v != nil { + records = append(records, &resolver.Record{ + Address: net.JoinHostPort(host, port), + }) + return records, nil + } + m := new(dns.Msg) m.SetQuestion(dns.Fqdn(host), dns.TypeA) rec, err := dns.ExchangeContext(context.Background(), m, r.Address) @@ -38,9 +49,6 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { return nil, err } - //nolint:prealloc - var records []*resolver.Record - for _, answer := range rec.Answer { h := answer.Header() // check record type matches @@ -59,5 +67,12 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { }) } + // no records returned so just best effort it + if len(records) == 0 { + records = append(records, &resolver.Record{ + Address: net.JoinHostPort(host, port), + }) + } + return records, nil } diff --git a/network/service/handler/handler.go b/network/service/handler/handler.go index 5a9f9379..d8538a7c 100644 --- a/network/service/handler/handler.go +++ b/network/service/handler/handler.go @@ -55,7 +55,7 @@ func (n *Network) Connect(ctx context.Context, req *pbNet.ConnectRequest, resp * } // get list of existing nodes - nodes := n.Network.Options().Peers + nodes := n.Network.Options().Nodes // generate a node map nodeMap := make(map[string]bool) @@ -84,7 +84,7 @@ func (n *Network) Connect(ctx context.Context, req *pbNet.ConnectRequest, resp * // reinitialise the peers n.Network.Init( - network.Peers(nodes...), + network.Nodes(nodes...), ) // call the connect method diff --git a/tunnel/default.go b/tunnel/default.go index 5943757f..15909654 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -197,73 +197,96 @@ func (t *tun) announce(channel, session string, link *link) { } } -// monitor monitors outbound links and attempts to reconnect to the failed ones -func (t *tun) monitor() { +// manage monitors outbound links and attempts to reconnect to the failed ones +func (t *tun) manage() { reconnect := time.NewTicker(ReconnectTime) defer reconnect.Stop() + // do it immediately + t.manageLinks() + for { select { case <-t.closed: return case <-reconnect.C: - t.RLock() - - var delLinks []string - // check the link status and purge dead links - for node, link := range t.links { - // check link status - switch link.State() { - case "closed": - delLinks = append(delLinks, node) - case "error": - delLinks = append(delLinks, node) - } - } - - t.RUnlock() - - // delete the dead links - if len(delLinks) > 0 { - t.Lock() - for _, node := range delLinks { - log.Debugf("Tunnel deleting dead link for %s", node) - if link, ok := t.links[node]; ok { - link.Close() - delete(t.links, node) - } - } - t.Unlock() - } - - // check current link status - var connect []string - - // build list of unknown nodes to connect to - t.RLock() - for _, node := range t.options.Nodes { - if _, ok := t.links[node]; !ok { - connect = append(connect, node) - } - } - t.RUnlock() - - for _, node := range connect { - // create new link - link, err := t.setupLink(node) - if err != nil { - log.Debugf("Tunnel failed to setup node link to %s: %v", node, err) - continue - } - // save the link - t.Lock() - t.links[node] = link - t.Unlock() - } + t.manageLinks() } } } +// manageLinks is a function that can be called to immediately to link setup +func (t *tun) manageLinks() { + var delLinks []string + + t.RLock() + + // check the link status and purge dead links + for node, link := range t.links { + // check link status + switch link.State() { + case "closed": + delLinks = append(delLinks, node) + case "error": + delLinks = append(delLinks, node) + } + } + + t.RUnlock() + + // delete the dead links + if len(delLinks) > 0 { + t.Lock() + for _, node := range delLinks { + log.Debugf("Tunnel deleting dead link for %s", node) + if link, ok := t.links[node]; ok { + link.Close() + delete(t.links, node) + } + } + t.Unlock() + } + + // check current link status + var connect []string + + // build list of unknown nodes to connect to + t.RLock() + + for _, node := range t.options.Nodes { + if _, ok := t.links[node]; !ok { + connect = append(connect, node) + } + } + + t.RUnlock() + + var wg sync.WaitGroup + + for _, node := range connect { + wg.Add(1) + + go func() { + defer wg.Done() + + // create new link + link, err := t.setupLink(node) + if err != nil { + log.Debugf("Tunnel failed to setup node link to %s: %v", node, err) + return + } + + // save the link + t.Lock() + t.links[node] = link + t.Unlock() + }() + } + + // wait for all threads to finish + wg.Wait() +} + // process outgoing messages sent by all local sessions func (t *tun) process() { // manage the send buffer @@ -757,11 +780,13 @@ func (t *tun) keepalive(link *link) { // It returns error if the link failed to be established func (t *tun) setupLink(node string) (*link, error) { log.Debugf("Tunnel setting up link: %s", node) + c, err := t.options.Transport.Dial(node) if err != nil { log.Debugf("Tunnel failed to connect to %s: %v", node, err) return nil, err } + log.Debugf("Tunnel connected to %s", node) // create a new link @@ -795,30 +820,6 @@ func (t *tun) setupLink(node string) (*link, error) { return link, nil } -func (t *tun) setupLinks() { - for _, node := range t.options.Nodes { - // skip zero length nodes - if len(node) == 0 { - continue - } - - // link already exists - if _, ok := t.links[node]; ok { - continue - } - - // connect to node and return link - link, err := t.setupLink(node) - if err != nil { - log.Debugf("Tunnel failed to establish node link to %s: %v", node, err) - continue - } - - // save the link - t.links[node] = link - } -} - // connect the tunnel to all the nodes and listen for incoming tunnel connections func (t *tun) connect() error { l, err := t.options.Transport.Listen(t.options.Address) @@ -869,11 +870,10 @@ func (t *tun) Connect() error { // already connected if t.connected { // setup links - t.setupLinks() return nil } - // send the connect message + // connect the tunnel: start the listener if err := t.connect(); err != nil { return err } @@ -883,16 +883,13 @@ func (t *tun) Connect() error { // create new close channel t.closed = make(chan bool) - // setup links - t.setupLinks() + // manage the links + go t.manage() // process outbound messages to be sent // process sends to all links go t.process() - // monitor links - go t.monitor() - return nil } @@ -1029,7 +1026,9 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { // set the multicast option c.mode = options.Mode // set the dial timeout - c.timeout = options.Timeout + c.dialTimeout = options.Timeout + // set read timeout set to never + c.readTimeout = time.Duration(-1) var links []*link // did we measure the rtt @@ -1145,7 +1144,11 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) { func (t *tun) Listen(channel string, opts ...ListenOption) (Listener, error) { log.Debugf("Tunnel listening on %s", channel) - var options ListenOptions + options := ListenOptions{ + // Read timeout defaults to never + Timeout: time.Duration(-1), + } + for _, o := range opts { o(&options) } @@ -1167,6 +1170,8 @@ func (t *tun) Listen(channel string, opts ...ListenOption) (Listener, error) { c.local = channel // set mode c.mode = options.Mode + // set the timeout + c.readTimeout = options.Timeout tl := &tunListener{ channel: channel, diff --git a/tunnel/listener.go b/tunnel/listener.go index 288b7dac..2417edd6 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -65,18 +65,8 @@ func (t *tunListener) process() { return // receive a new message case m := <-t.session.recv: - var sessionId string - - // get the session id - switch m.mode { - case Multicast, Broadcast: - // use channel name if multicast/broadcast - sessionId = "multicast" - log.Tracef("Tunnel listener using session %s for real session %s", sessionId, m.session) - default: - // use session id if unicast - sessionId = m.session - } + // session id + sessionId := m.session // get a session sess, ok := conns[sessionId] @@ -113,6 +103,8 @@ func (t *tunListener) process() { send: t.session.send, // error channel errChan: make(chan error, 1), + // set the read timeout + readTimeout: t.session.readTimeout, } // save the session @@ -137,12 +129,10 @@ func (t *tunListener) process() { // no op delete(conns, sessionId) default: - if sess.mode == Unicast { - // only close if unicast session - // close and delete session - close(sess.closed) - delete(conns, sessionId) - } + // only close if unicast session + // close and delete session + close(sess.closed) + delete(conns, sessionId) } // continue diff --git a/tunnel/options.go b/tunnel/options.go index 3a8f13db..145db19f 100644 --- a/tunnel/options.go +++ b/tunnel/options.go @@ -47,6 +47,8 @@ type ListenOption func(*ListenOptions) type ListenOptions struct { // specify mode of the session Mode Mode + // The read timeout + Timeout time.Duration } // The tunnel id @@ -84,16 +86,6 @@ func Transport(t transport.Transport) Option { } } -// DefaultOptions returns router default options -func DefaultOptions() Options { - return Options{ - Id: uuid.New().String(), - Address: DefaultAddress, - Token: DefaultToken, - Transport: quic.NewTransport(), - } -} - // Listen options func ListenMode(m Mode) ListenOption { return func(o *ListenOptions) { @@ -101,6 +93,13 @@ func ListenMode(m Mode) ListenOption { } } +// Timeout for reads and writes on the listener session +func ListenTimeout(t time.Duration) ListenOption { + return func(o *ListenOptions) { + o.Timeout = t + } +} + // Dial options // Dial multicast sets the multicast option to send only to those mapped @@ -124,3 +123,13 @@ func DialLink(id string) DialOption { o.Link = id } } + +// DefaultOptions returns router default options +func DefaultOptions() Options { + return Options{ + Id: uuid.New().String(), + Address: DefaultAddress, + Token: DefaultToken, + Transport: quic.NewTransport(), + } +} diff --git a/tunnel/session.go b/tunnel/session.go index e545d316..ebb179df 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -39,8 +39,10 @@ type session struct { loopback bool // mode of the connection mode Mode - // the timeout - timeout time.Duration + // the dial timeout + dialTimeout time.Duration + // the read timeout + readTimeout time.Duration // the link on which this message was received link string // the error response @@ -133,31 +135,43 @@ func (s *session) wait(msg *message) error { func (s *session) waitFor(msgType string, timeout time.Duration) (*message, error) { now := time.Now() - after := func(timeout time.Duration) time.Duration { + after := func(timeout time.Duration) <-chan time.Time { + if timeout < time.Duration(0) { + return nil + } + + // get the delta d := time.Since(now) + // dial timeout minus time since wait := timeout - d if wait < time.Duration(0) { - return time.Duration(0) + wait = time.Duration(0) } - return wait + return time.After(wait) } // wait for the message type for { select { case msg := <-s.recv: + // there may be no message type + if len(msgType) == 0 { + return msg, nil + } + // ignore what we don't want if msg.typ != msgType { log.Debugf("Tunnel received non %s message in waiting for %s", msg.typ, msgType) continue } + // got the message return msg, nil - case <-time.After(after(timeout)): - return nil, ErrDialTimeout + case <-after(timeout): + return nil, ErrReadTimeout case <-s.closed: return nil, io.EOF } @@ -193,7 +207,8 @@ func (s *session) Discover() error { after := func() time.Duration { d := time.Since(now) // dial timeout minus time since - wait := s.timeout - d + wait := s.dialTimeout - d + // make sure its always > 0 if wait < time.Duration(0) { return time.Duration(0) } @@ -248,7 +263,7 @@ func (s *session) Open() error { } // now wait for the accept message to be returned - msg, err := s.waitFor("accept", s.timeout) + msg, err := s.waitFor("accept", s.dialTimeout) if err != nil { return err } @@ -341,11 +356,9 @@ func (s *session) Send(m *transport.Message) error { func (s *session) Recv(m *transport.Message) error { var msg *message - select { - case <-s.closed: - return io.EOF - // recv from backlog - case msg = <-s.recv: + msg, err := s.waitFor("", s.readTimeout) + if err != nil { + return err } // check the error if one exists diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index abd61cb4..15ff6078 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -26,6 +26,8 @@ var ( ErrDiscoverChan = errors.New("failed to discover channel") // ErrLinkNotFound is returned when a link is specified at dial time and does not exist ErrLinkNotFound = errors.New("link not found") + // ErrReadTimeout is a timeout on session.Recv + ErrReadTimeout = errors.New("read timeout") ) // Mode of the session From 283c85d2568441a29da825c18fae7538c3cd3f51 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 8 Dec 2019 00:53:55 +0000 Subject: [PATCH 322/344] done --- network/default.go | 10 +++++----- tunnel/default.go | 5 +++-- tunnel/listener.go | 20 ++++++++++++++++---- tunnel/session.go | 6 ++++++ 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/network/default.go b/network/default.go index 83557592..b037e0aa 100644 --- a/network/default.go +++ b/network/default.go @@ -379,9 +379,8 @@ func (n *network) processNetChan(listener tunnel.Listener) { } // update peer links - log.Tracef("Network updating peer link %s for peer: %s", m.session.Link(), pbNetConnect.Node.Address) - if err := n.updatePeerLinks(pbNetConnect.Node.Address, m.session.Link()); err != nil { + if err := n.updatePeerLinks(pbNetConnect.Node.Address, m); err != nil { log.Debugf("Network failed updating peer links: %s", err) } @@ -443,9 +442,8 @@ func (n *network) processNetChan(listener tunnel.Listener) { } // update peer links - log.Tracef("Network updating peer link %s for peer: %s", m.session.Link(), pbNetPeer.Node.Address) - if err := n.updatePeerLinks(pbNetPeer.Node.Address, m.session.Link()); err != nil { + if err := n.updatePeerLinks(pbNetPeer.Node.Address, m); err != nil { log.Debugf("Network failed updating peer links: %s", err) } @@ -680,10 +678,12 @@ func (n *network) sendMsg(method, channel string, msg proto.Message) error { } // updatePeerLinks updates link for a given peer -func (n *network) updatePeerLinks(peerAddr string, linkId string) error { +func (n *network) updatePeerLinks(peerAddr string, m *message) error { n.Lock() defer n.Unlock() + linkId := m.msg.Header["Micro-Link"] + log.Tracef("Network looking up link %s in the peer links", linkId) // lookup the peer link diff --git a/tunnel/default.go b/tunnel/default.go index 15909654..985912d0 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -266,7 +266,7 @@ func (t *tun) manageLinks() { for _, node := range connect { wg.Add(1) - go func() { + go func(node string) { defer wg.Done() // create new link @@ -280,7 +280,7 @@ func (t *tun) manageLinks() { t.Lock() t.links[node] = link t.Unlock() - }() + }(node) } // wait for all threads to finish @@ -801,6 +801,7 @@ func (t *tun) setupLink(node string) (*link, error) { "Micro-Tunnel-Id": t.id, }, }); err != nil { + link.Close() return nil, err } diff --git a/tunnel/listener.go b/tunnel/listener.go index 2417edd6..6dbec5c8 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -65,12 +65,24 @@ func (t *tunListener) process() { return // receive a new message case m := <-t.session.recv: - // session id - sessionId := m.session + var sessionId string + var linkId string + + switch m.mode { + case Multicast: + sessionId = "multicast" + linkId = "multicast" + case Broadcast: + sessionId = "broadcast" + linkId = "broadcast" + default: + sessionId = m.session + linkId = m.link + } // get a session sess, ok := conns[sessionId] - log.Tracef("Tunnel listener received channel %s session %s type %s exists: %t", m.channel, sessionId, m.typ, ok) + log.Tracef("Tunnel listener received channel %s session %s type %s exists: %t", m.channel, m.session, m.typ, ok) if !ok { // we only process open and session types switch m.typ { @@ -92,7 +104,7 @@ func (t *tunListener) process() { // is loopback conn loopback: m.loopback, // the link the message was received on - link: m.link, + link: linkId, // set the connection mode mode: m.mode, // close chan diff --git a/tunnel/session.go b/tunnel/session.go index ebb179df..b43f3e75 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -400,6 +400,12 @@ func (s *session) Recv(m *transport.Message) error { msg.data.Header[k] = string(val) } + // set the link + // TODO: decruft, this is only for multicast + // since the session is now a single session + // likely provide as part of message.Link() + msg.data.Header["Micro-Link"] = msg.link + // set message *m = *msg.data // return nil From 6307d6ba51595ef28159af363ba3b9b6ac72c202 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 8 Dec 2019 12:12:20 +0000 Subject: [PATCH 323/344] further cleanup of tunnel/network --- network/default.go | 68 +++++++++------------ tunnel/default.go | 127 ++++++++++++++++++--------------------- tunnel/reconnect_test.go | 16 ++--- tunnel/session.go | 2 +- tunnel/tunnel_test.go | 4 +- 5 files changed, 98 insertions(+), 119 deletions(-) diff --git a/network/default.go b/network/default.go index b037e0aa..cd5d6967 100644 --- a/network/default.go +++ b/network/default.go @@ -202,6 +202,18 @@ func (n *network) Name() string { return n.options.Name } +func (n *network) initNodes() { + nodes, err := n.resolveNodes() + if err != nil { + log.Debugf("Network failed to resolve nodes: %v", err) + return + } + // initialize the tunnel + n.tunnel.Init( + tunnel.Nodes(nodes...), + ) +} + // resolveNodes resolves network nodes to addresses func (n *network) resolveNodes() ([]string, error) { // resolve the network address to network nodes @@ -253,29 +265,6 @@ func (n *network) resolveNodes() ([]string, error) { return nodes, err } -// resolve continuously resolves network nodes and initializes network tunnel with resolved addresses -func (n *network) resolve() { - resolve := time.NewTicker(ResolveTime) - defer resolve.Stop() - - for { - select { - case <-n.closed: - return - case <-resolve.C: - nodes, err := n.resolveNodes() - if err != nil { - log.Debugf("Network failed to resolve nodes: %v", err) - continue - } - // initialize the tunnel - n.tunnel.Init( - tunnel.Nodes(nodes...), - ) - } - } -} - // handleNetConn handles network announcement messages func (n *network) handleNetConn(s tunnel.Session, msg chan *message) { for { @@ -565,12 +554,14 @@ func (n *network) prunePeerRoutes(peer *node) error { // manage the process of announcing to peers and prune any peer nodes that have not been // seen for a period of time. Also removes all the routes either originated by or routable -//by the stale nodes +//by the stale nodes. it also resolves nodes periodically and adds them to the tunnel func (n *network) manage() { announce := time.NewTicker(AnnounceTime) defer announce.Stop() prune := time.NewTicker(PruneTime) defer prune.Stop() + resolve := time.NewTicker(ResolveTime) + defer resolve.Stop() for { select { @@ -584,11 +575,14 @@ func (n *network) manage() { } case <-prune.C: pruned := n.PruneStalePeers(PruneTime) + for id, peer := range pruned { log.Debugf("Network peer exceeded prune time: %s", id) + n.Lock() delete(n.peerLinks, peer.address) n.Unlock() + if err := n.prunePeerRoutes(peer); err != nil { log.Debugf("Network failed pruning peer %s routes: %v", id, err) } @@ -622,6 +616,8 @@ func (n *network) manage() { log.Debugf("Network failed deleting routes by %s: %v", route.Router, err) } } + case <-resolve.C: + n.initNodes() } } } @@ -1165,25 +1161,19 @@ func (n *network) Connect() error { n.Lock() defer n.Unlock() - // try to resolve network nodes - nodes, err := n.resolveNodes() - if err != nil { - log.Debugf("Network failed to resolve nodes: %v", err) - } - - // initialize the tunnel to resolved nodes - n.tunnel.Init( - tunnel.Nodes(nodes...), - ) - // connect network tunnel if err := n.tunnel.Connect(); err != nil { - n.Unlock() return err } + // initialise the nodes + n.initNodes() + // return if already connected if n.connected { + // immediately resolve + initNodes() + // send the connect message n.sendConnect() return nil @@ -1250,11 +1240,9 @@ func (n *network) Connect() error { return err } - // send connect after there's a link established + // manage connection once links are established go n.connect() - // resolve network nodes and re-init the tunnel - go n.resolve() - // broadcast announcements and prune stale nodes + // resolve nodes, broadcast announcements and prune stale nodes go n.manage() // advertise service routes go n.advertise(advertChan) diff --git a/tunnel/default.go b/tunnel/default.go index 985912d0..1fa2fd47 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -202,7 +202,7 @@ func (t *tun) manage() { reconnect := time.NewTicker(ReconnectTime) defer reconnect.Stop() - // do it immediately + // do immediately t.manageLinks() for { @@ -215,6 +215,47 @@ func (t *tun) manage() { } } +// manageLink sends channel discover requests periodically and +// keepalive messages to link +func (t *tun) manageLink(link *link) { + keepalive := time.NewTicker(KeepAliveTime) + defer keepalive.Stop() + discover := time.NewTicker(DiscoverTime) + defer discover.Stop() + + for { + select { + case <-t.closed: + return + case <-link.closed: + return + case <-discover.C: + // send a discovery message to all links + if err := link.Send(&transport.Message{ + Header: map[string]string{ + "Micro-Tunnel": "discover", + "Micro-Tunnel-Id": t.id, + }, + }); err != nil { + log.Debugf("Tunnel failed to send discover to link %s: %v", link.Remote(), err) + } + case <-keepalive.C: + // send keepalive message + log.Debugf("Tunnel sending keepalive to link: %v", link.Remote()) + if err := link.Send(&transport.Message{ + Header: map[string]string{ + "Micro-Tunnel": "keepalive", + "Micro-Tunnel-Id": t.id, + }, + }); err != nil { + log.Debugf("Tunnel error sending keepalive to link %v: %v", link.Remote(), err) + t.delLink(link.Remote()) + return + } + } + } +} + // manageLinks is a function that can be called to immediately to link setup func (t *tun) manageLinks() { var delLinks []string @@ -278,8 +319,15 @@ func (t *tun) manageLinks() { // save the link t.Lock() + defer t.Unlock() + + // just check nothing else was setup in the interim + if _, ok := t.links[node]; ok { + link.Close() + return + } + // save the link t.links[node] = link - t.Unlock() }(node) } @@ -723,59 +771,6 @@ func (t *tun) listen(link *link) { } } -// discover sends channel discover requests periodically -func (t *tun) discover(link *link) { - tick := time.NewTicker(DiscoverTime) - defer tick.Stop() - - for { - select { - case <-tick.C: - // send a discovery message to all links - if err := link.Send(&transport.Message{ - Header: map[string]string{ - "Micro-Tunnel": "discover", - "Micro-Tunnel-Id": t.id, - }, - }); err != nil { - log.Debugf("Tunnel failed to send discover to link %s: %v", link.Remote(), err) - } - case <-link.closed: - return - case <-t.closed: - return - } - } -} - -// keepalive periodically sends keepalive messages to link -func (t *tun) keepalive(link *link) { - keepalive := time.NewTicker(KeepAliveTime) - defer keepalive.Stop() - - for { - select { - case <-t.closed: - return - case <-link.closed: - return - case <-keepalive.C: - // send keepalive message - log.Debugf("Tunnel sending keepalive to link: %v", link.Remote()) - if err := link.Send(&transport.Message{ - Header: map[string]string{ - "Micro-Tunnel": "keepalive", - "Micro-Tunnel-Id": t.id, - }, - }); err != nil { - log.Debugf("Tunnel error sending keepalive to link %v: %v", link.Remote(), err) - t.delLink(link.Remote()) - return - } - } - } -} - // setupLink connects to node and returns link if successful // It returns error if the link failed to be established func (t *tun) setupLink(node string) (*link, error) { @@ -812,11 +807,8 @@ func (t *tun) setupLink(node string) (*link, error) { // process incoming messages go t.listen(link) - // start keepalive monitor - go t.keepalive(link) - - // discover things on the remote side - go t.discover(link) + // manage keepalives and discovery messages + go t.manageLink(link) return link, nil } @@ -839,11 +831,8 @@ func (t *tun) connect() error { // create a new link link := newLink(sock) - // start keepalive monitor - go t.keepalive(link) - - // discover things on the remote side - go t.discover(link) + // manage the link + go t.manageLink(link) // listen for inbound messages. // only save the link once connected. @@ -870,6 +859,8 @@ func (t *tun) Connect() error { // already connected if t.connected { + // do it immediately + t.manageLinks() // setup links return nil } @@ -884,13 +875,13 @@ func (t *tun) Connect() error { // create new close channel t.closed = make(chan bool) - // manage the links - go t.manage() - // process outbound messages to be sent // process sends to all links go t.process() + // manage the links + go t.manage() + return nil } diff --git a/tunnel/reconnect_test.go b/tunnel/reconnect_test.go index 2c78b8b2..3e9331c3 100644 --- a/tunnel/reconnect_test.go +++ b/tunnel/reconnect_test.go @@ -9,15 +9,19 @@ import ( ) func TestReconnectTunnel(t *testing.T) { + // we manually override the tunnel.ReconnectTime value here + // this is so that we make the reconnects faster than the default 5s + ReconnectTime = 100 * time.Millisecond + // create a new tunnel client tunA := NewTunnel( - Address("127.0.0.1:9096"), - Nodes("127.0.0.1:9097"), + Address("127.0.0.1:9098"), + Nodes("127.0.0.1:9099"), ) // create a new tunnel server tunB := NewTunnel( - Address("127.0.0.1:9097"), + Address("127.0.0.1:9099"), ) // start tunnel @@ -27,10 +31,6 @@ func TestReconnectTunnel(t *testing.T) { } defer tunB.Close() - // we manually override the tunnel.ReconnectTime value here - // this is so that we make the reconnects faster than the default 5s - ReconnectTime = 200 * time.Millisecond - // start tunnel err = tunA.Connect() if err != nil { @@ -48,7 +48,7 @@ func TestReconnectTunnel(t *testing.T) { wg.Add(1) // start tunnel sender - go testBrokenTunSend(t, tunA, wait, &wg) + go testBrokenTunSend(t, tunA, wait, &wg, ReconnectTime) // wait until done wg.Wait() diff --git a/tunnel/session.go b/tunnel/session.go index b43f3e75..84153541 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -420,7 +420,7 @@ func (s *session) Close() error { default: close(s.closed) - // don't send close on multicast + // don't send close on multicast or broadcast if s.mode != Unicast { return nil } diff --git a/tunnel/tunnel_test.go b/tunnel/tunnel_test.go index 8c3119da..839beeb1 100644 --- a/tunnel/tunnel_test.go +++ b/tunnel/tunnel_test.go @@ -206,7 +206,7 @@ func testBrokenTunAccept(t *testing.T, tun Tunnel, wait chan bool, wg *sync.Wait wait <- true } -func testBrokenTunSend(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGroup) { +func testBrokenTunSend(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGroup, reconnect time.Duration) { defer wg.Done() // wait for the listener to get ready @@ -234,7 +234,7 @@ func testBrokenTunSend(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGr <-wait // give it time to reconnect - time.Sleep(5 * ReconnectTime) + time.Sleep(10 * reconnect) // send the message if err := c.Send(&m); err != nil { From ce578800d08f1384cfa7ebf5bae090e62ca0a57b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 8 Dec 2019 12:17:31 +0000 Subject: [PATCH 324/344] n.initNodes --- network/default.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/default.go b/network/default.go index cd5d6967..a5331b45 100644 --- a/network/default.go +++ b/network/default.go @@ -1172,7 +1172,7 @@ func (n *network) Connect() error { // return if already connected if n.connected { // immediately resolve - initNodes() + n.initNodes() // send the connect message n.sendConnect() From 398acc67cada3349df5245d37e29452a6555b356 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 8 Dec 2019 13:45:24 +0000 Subject: [PATCH 325/344] fix broken test --- tunnel/default.go | 72 +++++++++----- tunnel/tunnel_test.go | 214 +++++++++++++++++++++++++----------------- 2 files changed, 179 insertions(+), 107 deletions(-) diff --git a/tunnel/default.go b/tunnel/default.go index 1fa2fd47..a6cb08c9 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -202,9 +202,6 @@ func (t *tun) manage() { reconnect := time.NewTicker(ReconnectTime) defer reconnect.Stop() - // do immediately - t.manageLinks() - for { select { case <-t.closed: @@ -231,23 +228,13 @@ func (t *tun) manageLink(link *link) { return case <-discover.C: // send a discovery message to all links - if err := link.Send(&transport.Message{ - Header: map[string]string{ - "Micro-Tunnel": "discover", - "Micro-Tunnel-Id": t.id, - }, - }); err != nil { + if err := t.sendMsg("discover", link); err != nil { log.Debugf("Tunnel failed to send discover to link %s: %v", link.Remote(), err) } case <-keepalive.C: // send keepalive message log.Debugf("Tunnel sending keepalive to link: %v", link.Remote()) - if err := link.Send(&transport.Message{ - Header: map[string]string{ - "Micro-Tunnel": "keepalive", - "Micro-Tunnel-Id": t.id, - }, - }); err != nil { + if err := t.sendMsg("keepalive", link); err != nil { log.Debugf("Tunnel error sending keepalive to link %v: %v", link.Remote(), err) t.delLink(link.Remote()) return @@ -570,8 +557,10 @@ func (t *tun) listen(link *link) { t.links[link.Remote()] = link t.Unlock() - // send back a discovery + // send back an announcement of our channels discovery go t.announce("", "", link) + // ask for the things on the other wise + go t.sendMsg("discover", link) // nothing more to do continue case "close": @@ -771,6 +760,15 @@ func (t *tun) listen(link *link) { } } +func (t *tun) sendMsg(method string, link *link) error { + return link.Send(&transport.Message{ + Header: map[string]string{ + "Micro-Tunnel": method, + "Micro-Tunnel-Id": t.id, + }, + }) +} + // setupLink connects to node and returns link if successful // It returns error if the link failed to be established func (t *tun) setupLink(node string) (*link, error) { @@ -790,12 +788,7 @@ func (t *tun) setupLink(node string) (*link, error) { link.id = c.Remote() // send the first connect message - if err := link.Send(&transport.Message{ - Header: map[string]string{ - "Micro-Tunnel": "connect", - "Micro-Tunnel-Id": t.id, - }, - }); err != nil { + if err := t.sendMsg("connect", link); err != nil { link.Close() return nil, err } @@ -813,6 +806,36 @@ func (t *tun) setupLink(node string) (*link, error) { return link, nil } +func (t *tun) setupLinks() { + var wg sync.WaitGroup + + for _, node := range t.options.Nodes { + wg.Add(1) + + go func(node string) { + defer wg.Done() + + // we're not trying to fix existing links + if _, ok := t.links[node]; ok { + return + } + + // create new link + link, err := t.setupLink(node) + if err != nil { + log.Debugf("Tunnel failed to setup node link to %s: %v", node, err) + return + } + + // save the link + t.links[node] = link + }(node) + } + + // wait for all threads to finish + wg.Wait() +} + // connect the tunnel to all the nodes and listen for incoming tunnel connections func (t *tun) connect() error { l, err := t.options.Transport.Listen(t.options.Address) @@ -860,7 +883,7 @@ func (t *tun) Connect() error { // already connected if t.connected { // do it immediately - t.manageLinks() + t.setupLinks() // setup links return nil } @@ -879,6 +902,9 @@ func (t *tun) Connect() error { // process sends to all links go t.process() + // call setup before managing them + t.setupLinks() + // manage the links go t.manage() diff --git a/tunnel/tunnel_test.go b/tunnel/tunnel_test.go index 839beeb1..9633e53d 100644 --- a/tunnel/tunnel_test.go +++ b/tunnel/tunnel_test.go @@ -8,6 +8,90 @@ import ( "github.com/micro/go-micro/transport" ) +func testBrokenTunAccept(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGroup) { + defer wg.Done() + + // listen on some virtual address + tl, err := tun.Listen("test-tunnel") + if err != nil { + t.Fatal(err) + } + + // receiver ready; notify sender + wait <- true + + // accept a connection + c, err := tl.Accept() + if err != nil { + t.Fatal(err) + } + + // accept the message and close the tunnel + // we do this to simulate loss of network connection + m := new(transport.Message) + if err := c.Recv(m); err != nil { + t.Fatal(err) + } + + // close all the links + for _, link := range tun.Links() { + link.Close() + } + + // receiver ready; notify sender + wait <- true + + // accept the message + m = new(transport.Message) + if err := c.Recv(m); err != nil { + t.Fatal(err) + } + + // notify the sender we have received + wait <- true +} + +func testBrokenTunSend(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGroup, reconnect time.Duration) { + defer wg.Done() + + // wait for the listener to get ready + <-wait + + // dial a new session + c, err := tun.Dial("test-tunnel") + if err != nil { + t.Fatal(err) + } + defer c.Close() + + m := transport.Message{ + Header: map[string]string{ + "test": "send", + }, + } + + // send the message + if err := c.Send(&m); err != nil { + t.Fatal(err) + } + + // wait for the listener to get ready + <-wait + + // give it time to reconnect + time.Sleep(reconnect) + + // send the message + if err := c.Send(&m); err != nil { + t.Fatal(err) + } + + // wait for the listener to receive the message + // c.Send merely enqueues the message to the link send queue and returns + // in order to verify it was received we wait for the listener to tell us + <-wait +} + // testAccept will accept connections on the transport, create a new link and tunnel on top func testAccept(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGroup) { defer wg.Done() @@ -163,90 +247,6 @@ func TestLoopbackTunnel(t *testing.T) { wg.Wait() } -func testBrokenTunAccept(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGroup) { - defer wg.Done() - - // listen on some virtual address - tl, err := tun.Listen("test-tunnel") - if err != nil { - t.Fatal(err) - } - - // receiver ready; notify sender - wait <- true - - // accept a connection - c, err := tl.Accept() - if err != nil { - t.Fatal(err) - } - - // accept the message and close the tunnel - // we do this to simulate loss of network connection - m := new(transport.Message) - if err := c.Recv(m); err != nil { - t.Fatal(err) - } - - // close all the links - for _, link := range tun.Links() { - link.Close() - } - - // receiver ready; notify sender - wait <- true - - // accept the message - m = new(transport.Message) - if err := c.Recv(m); err != nil { - t.Fatal(err) - } - - // notify the sender we have received - wait <- true -} - -func testBrokenTunSend(t *testing.T, tun Tunnel, wait chan bool, wg *sync.WaitGroup, reconnect time.Duration) { - defer wg.Done() - - // wait for the listener to get ready - <-wait - - // dial a new session - c, err := tun.Dial("test-tunnel") - if err != nil { - t.Fatal(err) - } - defer c.Close() - - m := transport.Message{ - Header: map[string]string{ - "test": "send", - }, - } - - // send the message - if err := c.Send(&m); err != nil { - t.Fatal(err) - } - - // wait for the listener to get ready - <-wait - - // give it time to reconnect - time.Sleep(10 * reconnect) - - // send the message - if err := c.Send(&m); err != nil { - t.Fatal(err) - } - - // wait for the listener to receive the message - // c.Send merely enqueues the message to the link send queue and returns - // in order to verify it was received we wait for the listener to tell us - <-wait -} - func TestTunnelRTTRate(t *testing.T) { // create a new tunnel client tunA := NewTunnel( @@ -296,3 +296,49 @@ func TestTunnelRTTRate(t *testing.T) { t.Logf("Link %s length %v rate %v", link.Id(), link.Length(), link.Rate()) } } + +func TestReconnectTunnel(t *testing.T) { + // we manually override the tunnel.ReconnectTime value here + // this is so that we make the reconnects faster than the default 5s + ReconnectTime = 200 * time.Millisecond + + // create a new tunnel client + tunA := NewTunnel( + Address("127.0.0.1:9098"), + Nodes("127.0.0.1:9099"), + ) + + // create a new tunnel server + tunB := NewTunnel( + Address("127.0.0.1:9099"), + ) + + // start tunnel + err := tunB.Connect() + if err != nil { + t.Fatal(err) + } + defer tunB.Close() + + // start tunnel + err = tunA.Connect() + if err != nil { + t.Fatal(err) + } + defer tunA.Close() + + wait := make(chan bool) + + var wg sync.WaitGroup + + wg.Add(1) + // start tunnel listener + go testBrokenTunAccept(t, tunB, wait, &wg) + + wg.Add(1) + // start tunnel sender + go testBrokenTunSend(t, tunA, wait, &wg, ReconnectTime*5) + + // wait until done + wg.Wait() +} From d28a868e46beafd5410fea16a061edbf05c6d444 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 8 Dec 2019 14:37:17 +0000 Subject: [PATCH 326/344] Fix network startup connect --- network/default.go | 67 +++++++++++++++++++++++----------------- tunnel/reconnect_test.go | 55 --------------------------------- 2 files changed, 38 insertions(+), 84 deletions(-) delete mode 100644 tunnel/reconnect_test.go diff --git a/network/default.go b/network/default.go index a5331b45..3fde3fdb 100644 --- a/network/default.go +++ b/network/default.go @@ -202,13 +202,16 @@ func (n *network) Name() string { return n.options.Name } -func (n *network) initNodes() { +func (n *network) initNodes(startup bool) { nodes, err := n.resolveNodes() - if err != nil { + if err != nil && !startup { log.Debugf("Network failed to resolve nodes: %v", err) return } + // initialize the tunnel + log.Tracef("Network initialising nodes %+v\n", nodes) + n.tunnel.Init( tunnel.Nodes(nodes...), ) @@ -218,6 +221,11 @@ func (n *network) initNodes() { func (n *network) resolveNodes() ([]string, error) { // resolve the network address to network nodes records, err := n.options.Resolver.Resolve(n.options.Name) + if err != nil { + log.Debugf("Network failed to resolve nodes: %v", err) + } + + // keep processing nodeMap := make(map[string]bool) @@ -262,7 +270,7 @@ func (n *network) resolveNodes() ([]string, error) { } } - return nodes, err + return nodes, nil } // handleNetConn handles network announcement messages @@ -617,7 +625,7 @@ func (n *network) manage() { } } case <-resolve.C: - n.initNodes() + n.initNodes(false) } } } @@ -1137,6 +1145,8 @@ func (n *network) connect() { n.sendConnect() } + log.Tracef("connected %v discovered %v backoff %v\n", connected, discovered, backoff.Do(attempts)) + // check if we've been discovered select { case <-n.discovered: @@ -1166,33 +1176,34 @@ func (n *network) Connect() error { return err } - // initialise the nodes - n.initNodes() - // return if already connected if n.connected { - // immediately resolve - n.initNodes() - + // initialise the nodes + n.initNodes(false) // send the connect message - n.sendConnect() + go n.sendConnect() return nil } + // initialise the nodes + n.initNodes(true) + // set our internal node address // if advertise address is not set if len(n.options.Advertise) == 0 { n.server.Init(server.Advertise(n.tunnel.Address())) } - // dial into ControlChannel to send route adverts - ctrlClient, err := n.tunnel.Dial(ControlChannel, tunnel.DialMode(tunnel.Multicast)) + // listen on NetworkChannel + netListener, err := n.tunnel.Listen( + NetworkChannel, + tunnel.ListenMode(tunnel.Multicast), + tunnel.ListenTimeout(AnnounceTime*2), + ) if err != nil { return err } - n.tunClient[ControlChannel] = ctrlClient - // listen on ControlChannel ctrlListener, err := n.tunnel.Listen( ControlChannel, @@ -1203,6 +1214,14 @@ func (n *network) Connect() error { return err } + // dial into ControlChannel to send route adverts + ctrlClient, err := n.tunnel.Dial(ControlChannel, tunnel.DialMode(tunnel.Multicast)) + if err != nil { + return err + } + + n.tunClient[ControlChannel] = ctrlClient + // dial into NetworkChannel to send network messages netClient, err := n.tunnel.Dial(NetworkChannel, tunnel.DialMode(tunnel.Multicast)) if err != nil { @@ -1211,16 +1230,6 @@ func (n *network) Connect() error { n.tunClient[NetworkChannel] = netClient - // listen on NetworkChannel - netListener, err := n.tunnel.Listen( - NetworkChannel, - tunnel.ListenMode(tunnel.Multicast), - tunnel.ListenTimeout(AnnounceTime*2), - ) - if err != nil { - return err - } - // create closed channel n.closed = make(chan bool) @@ -1240,16 +1249,16 @@ func (n *network) Connect() error { return err } - // manage connection once links are established - go n.connect() - // resolve nodes, broadcast announcements and prune stale nodes - go n.manage() // advertise service routes go n.advertise(advertChan) // listen to network messages go n.processNetChan(netListener) // accept and process routes go n.processCtrlChan(ctrlListener) + // manage connection once links are established + go n.connect() + // resolve nodes, broadcast announcements and prune stale nodes + go n.manage() // we're now connected n.connected = true diff --git a/tunnel/reconnect_test.go b/tunnel/reconnect_test.go deleted file mode 100644 index 3e9331c3..00000000 --- a/tunnel/reconnect_test.go +++ /dev/null @@ -1,55 +0,0 @@ -// +build !race - -package tunnel - -import ( - "sync" - "testing" - "time" -) - -func TestReconnectTunnel(t *testing.T) { - // we manually override the tunnel.ReconnectTime value here - // this is so that we make the reconnects faster than the default 5s - ReconnectTime = 100 * time.Millisecond - - // create a new tunnel client - tunA := NewTunnel( - Address("127.0.0.1:9098"), - Nodes("127.0.0.1:9099"), - ) - - // create a new tunnel server - tunB := NewTunnel( - Address("127.0.0.1:9099"), - ) - - // start tunnel - err := tunB.Connect() - if err != nil { - t.Fatal(err) - } - defer tunB.Close() - - // start tunnel - err = tunA.Connect() - if err != nil { - t.Fatal(err) - } - defer tunA.Close() - - wait := make(chan bool) - - var wg sync.WaitGroup - - wg.Add(1) - // start tunnel listener - go testBrokenTunAccept(t, tunB, wait, &wg) - - wg.Add(1) - // start tunnel sender - go testBrokenTunSend(t, tunA, wait, &wg, ReconnectTime) - - // wait until done - wg.Wait() -} From 6064e1426c4a93658b91d55fd0e9547113cbcabb Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 8 Dec 2019 15:02:54 +0000 Subject: [PATCH 327/344] fix some potential go routine leaks --- network/default.go | 2 -- tunnel/link.go | 15 +++++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/network/default.go b/network/default.go index 3fde3fdb..9f29414d 100644 --- a/network/default.go +++ b/network/default.go @@ -1145,8 +1145,6 @@ func (n *network) connect() { n.sendConnect() } - log.Tracef("connected %v discovered %v backoff %v\n", connected, discovered, backoff.Do(attempts)) - // check if we've been discovered select { case <-n.discovered: diff --git a/tunnel/link.go b/tunnel/link.go index a7367812..a072a047 100644 --- a/tunnel/link.go +++ b/tunnel/link.go @@ -200,6 +200,8 @@ func (l *link) process() { // process link state message select { case l.state <- pk: + case <-l.closed: + return default: } continue @@ -221,7 +223,11 @@ func (l *link) process() { select { case pk := <-l.sendQueue: // send the message - pk.status <- l.send(pk.message) + select { + case pk.status <- l.send(pk.message): + case <-l.closed: + return + } case <-l.closed: return } @@ -388,13 +394,6 @@ func (l *link) Send(m *transport.Message) error { // get time now now := time.Now() - // check if its closed first - select { - case <-l.closed: - return io.EOF - default: - } - // queue the message select { case l.sendQueue <- p: From 679214e5980d327e1e7fa61f8ab4804a9643d375 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 8 Dec 2019 15:39:45 +0000 Subject: [PATCH 328/344] just return filtered routes --- proxy/mucp/mucp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index a7cf5bd6..d565d47a 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -164,7 +164,7 @@ func (p *Proxy) filterRoutes(ctx context.Context, routes []router.Route) []route filteredRoutes = append(filteredRoutes, route) } - log.Tracef("Proxy filtered routes %+v vs %+v\n", routes, filteredRoutes) + log.Tracef("Proxy filtered routes %+v\n", filteredRoutes) return filteredRoutes } From e2b2a30668310e7ee05aff2e0adddf08196240cc Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 8 Dec 2019 20:31:16 +0000 Subject: [PATCH 329/344] add net/http/pprof profiler --- debug/profile/http/http.go | 78 ++++++++++++++++++++++++++++++++++++ debug/profile/pprof/pprof.go | 4 ++ debug/profile/profile.go | 2 + service.go | 27 ++++++++++--- 4 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 debug/profile/http/http.go diff --git a/debug/profile/http/http.go b/debug/profile/http/http.go new file mode 100644 index 00000000..66cbf49c --- /dev/null +++ b/debug/profile/http/http.go @@ -0,0 +1,78 @@ +// Package http enables the http profiler +package http + +import ( + "context" + "net/http" + "net/http/pprof" + "sync" + + "github.com/micro/go-micro/debug/profile" +) + +type httpProfile struct { + sync.Mutex + running bool + server *http.Server +} + +var ( + DefaultAddress = ":6060" +) + +// Start the profiler +func (h *httpProfile) Start() error { + h.Lock() + defer h.Unlock() + + if h.running { + return nil + } + + go func() { + if err := h.server.ListenAndServe(); err != nil { + h.Lock() + h.running = false + h.Unlock() + } + }() + + h.running = true + + return nil +} + +// Stop the profiler +func (h *httpProfile) Stop() error { + h.Lock() + defer h.Unlock() + + if !h.running { + return nil + } + + h.running = false + + return h.server.Shutdown(context.TODO()) +} + +func (h *httpProfile) String() string { + return "http" +} + +func NewProfile(opts ...profile.Option) profile.Profile { + mux := http.NewServeMux() + + mux.HandleFunc("/debug/pprof/", pprof.Index) + mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) + mux.HandleFunc("/debug/pprof/profile", pprof.Profile) + mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + mux.HandleFunc("/debug/pprof/trace", pprof.Trace) + + return &httpProfile{ + server: &http.Server{ + Addr: DefaultAddress, + Handler: mux, + }, + } +} diff --git a/debug/profile/pprof/pprof.go b/debug/profile/pprof/pprof.go index b1f126d9..5dfd49ba 100644 --- a/debug/profile/pprof/pprof.go +++ b/debug/profile/pprof/pprof.go @@ -107,6 +107,10 @@ func (p *profiler) Stop() error { } } +func (p *profiler) String() string { + return "pprof" +} + func NewProfile(opts ...profile.Option) profile.Profile { var options profile.Options for _, o := range opts { diff --git a/debug/profile/profile.go b/debug/profile/profile.go index 2dbe1e13..3cc075f4 100644 --- a/debug/profile/profile.go +++ b/debug/profile/profile.go @@ -6,6 +6,8 @@ type Profile interface { Start() error // Stop the profiler Stop() error + // Name of the profiler + String() string } type Options struct { diff --git a/service.go b/service.go index efddd0a4..0245bfd6 100644 --- a/service.go +++ b/service.go @@ -3,6 +3,7 @@ package micro import ( "os" "os/signal" + "runtime" "strings" "sync" "syscall" @@ -10,6 +11,7 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/config/cmd" "github.com/micro/go-micro/debug/profile" + "github.com/micro/go-micro/debug/profile/http" "github.com/micro/go-micro/debug/profile/pprof" "github.com/micro/go-micro/debug/service/handler" "github.com/micro/go-micro/plugin" @@ -151,12 +153,25 @@ func (s *service) Run() error { // start the profiler // TODO: set as an option to the service, don't just use pprof if prof := os.Getenv("MICRO_DEBUG_PROFILE"); len(prof) > 0 { - service := s.opts.Server.Options().Name - version := s.opts.Server.Options().Version - id := s.opts.Server.Options().Id - profiler := pprof.NewProfile( - profile.Name(service + "." + version + "." + id), - ) + var profiler profile.Profile + + // to view mutex contention + runtime.SetMutexProfileFraction(5) + // to view blocking profile + runtime.SetBlockProfileRate(1) + + switch prof { + case "http": + profiler = http.NewProfile() + default: + service := s.opts.Server.Options().Name + version := s.opts.Server.Options().Version + id := s.opts.Server.Options().Id + profiler = pprof.NewProfile( + profile.Name(service + "." + version + "." + id), + ) + } + if err := profiler.Start(); err != nil { return err } From 55a15ecf12c55e47ff1be3f1679169fd4f2d78c5 Mon Sep 17 00:00:00 2001 From: Astone Date: Mon, 9 Dec 2019 11:18:45 +0800 Subject: [PATCH 330/344] fix tiny error in linting fixes --- network/resolver/dnssrv/dnssrv.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/resolver/dnssrv/dnssrv.go b/network/resolver/dnssrv/dnssrv.go index 9bfe9638..63a92eda 100644 --- a/network/resolver/dnssrv/dnssrv.go +++ b/network/resolver/dnssrv/dnssrv.go @@ -17,7 +17,7 @@ func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) { if err != nil { return nil, err } - records := make([]*resolver.Record, len(addrs)) + records := make([]*resolver.Record, 0, len(addrs)) for _, addr := range addrs { address := addr.Target if addr.Port > 0 { From 59c168059478aab834500d91e7e8af317eac894c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 9 Dec 2019 09:32:17 +0000 Subject: [PATCH 331/344] Move Debug to Trace in router --- router/default.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/router/default.go b/router/default.go index 02ceac1b..a1995826 100644 --- a/router/default.go +++ b/router/default.go @@ -717,13 +717,15 @@ func (r *router) Process(a *Advert) error { for _, event := range events { // skip if the router is the origin of this route if event.Route.Router == r.options.Id { - log.Debugf("Router skipping processing its own route: %s", r.options.Id) + log.Tracef("Router skipping processing its own route: %s", r.options.Id) continue } // create a copy of the route route := event.Route action := event.Type - log.Debugf("Router %s applying %s from router %s for service %s %s", r.options.Id, action, route.Router, route.Service, route.Address) + + log.Tracef("Router %s applying %s from router %s for service %s %s", r.options.Id, action, route.Router, route.Service, route.Address) + if err := r.manageRoute(route, action.String()); err != nil { return fmt.Errorf("failed applying action %s to routing table: %s", action, err) } @@ -874,7 +876,7 @@ func (r *router) Stop() error { } r.Unlock() - log.Debugf("Router waiting for all goroutines to finish") + log.Tracef("Router waiting for all goroutines to finish") // wait for all goroutines to finish r.wg.Wait() From f25ad35f0a6a15566759517bed338a4532f4c2fb Mon Sep 17 00:00:00 2001 From: Lars Lehtonen Date: Mon, 9 Dec 2019 09:28:42 -0800 Subject: [PATCH 332/344] web: fix test goroutine in TestTLS() --- web/service_test.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/web/service_test.go b/web/service_test.go index 588531b8..a4447174 100644 --- a/web/service_test.go +++ b/web/service_test.go @@ -221,10 +221,10 @@ func TestTLS(t *testing.T) { service.HandleFunc("/", fn) + errCh := make(chan error, 1) go func() { - if err := service.Run(); err != nil { - t.Fatal(err) - } + errCh <- service.Run() + close(errCh) }() var s []*registry.Service @@ -257,4 +257,13 @@ func TestTLS(t *testing.T) { if string(b) != str { t.Errorf("Expected %s got %s", str, string(b)) } + + select { + case err := <-errCh: + if err != nil { + t.Fatalf("Run():%v", err) + } + case <-time.After(time.Duration(time.Second)): + t.Logf("service.Run() survived a client request without an error") + } } From c9af88184bd0d55c39bee202de84a487e30c3dcc Mon Sep 17 00:00:00 2001 From: Lars Lehtonen Date: Mon, 9 Dec 2019 09:44:14 -0800 Subject: [PATCH 333/344] web: fix test goroutine in TestService() --- web/service_test.go | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/web/service_test.go b/web/service_test.go index a4447174..33365535 100644 --- a/web/service_test.go +++ b/web/service_test.go @@ -57,10 +57,10 @@ func TestService(t *testing.T) { service.HandleFunc("/", fn) + errCh := make(chan error, 1) go func() { - if err := service.Run(); err != nil { - t.Fatal(err) - } + errCh <- service.Run() + close(errCh) }() var s []*registry.Service @@ -104,12 +104,32 @@ func TestService(t *testing.T) { } } + select { + case err := <-errCh: + if err != nil { + t.Fatalf("service.Run():%v", err) + } + case <-time.After(time.Duration(time.Second)): + t.Logf("service.Run() survived a client request without an error") + } + ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGTERM) syscall.Kill(syscall.Getpid(), syscall.SIGTERM) <-ch + select { + case err := <-errCh: + if err != nil { + t.Fatalf("service.Run():%v", err) + } else { + t.Log("service.Run() nil return on syscall.SIGTERM") + } + case <-time.After(time.Duration(time.Second)): + t.Logf("service.Run() survived a client request without an error") + } + eventually(func() bool { _, err := reg.GetService("go.micro.web.test") return err == registry.ErrNotFound @@ -128,6 +148,7 @@ func TestService(t *testing.T) { t.Errorf("unexpected %s: want true, have false", tt.subject) } } + } func TestOptions(t *testing.T) { @@ -261,9 +282,10 @@ func TestTLS(t *testing.T) { select { case err := <-errCh: if err != nil { - t.Fatalf("Run():%v", err) + t.Fatalf("service.Run():%v", err) } case <-time.After(time.Duration(time.Second)): t.Logf("service.Run() survived a client request without an error") } + } From 5352d5334657342922da5554b1b37f4b9420cda6 Mon Sep 17 00:00:00 2001 From: Jan Kremlacek Date: Mon, 9 Dec 2019 21:52:28 +0100 Subject: [PATCH 334/344] nlopes/slack dep update to fix broken unmarshal About a month ago Slack introduced the updated structure of RTM messages which resulted in an inability to unmarshal received msg (original issue: https://github.com/nlopes/slack/issues/630). It's not an issue of micro itself, but of the github.com/nlopes/slack lib. The fix was already merged into master (https://github.com/nlopes/slack/pull/618), but the lib has not been released in any new version. Thus so I propose to update directly to the commit: go get github.com/nlopes/slack@d06c2a2b3249b44a9c5dee8485f5a87497beb9ea The MicroBot does now work now with any Slack client newer than around a month old. --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0812f043..3cbfcc37 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/miekg/dns v1.1.22 github.com/mitchellh/hashstructure v1.0.0 github.com/nats-io/nats.go v1.9.1 - github.com/nlopes/slack v0.6.0 + github.com/nlopes/slack@d06c2a2b3249b44a9c5dee8485f5a87497beb9ea github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.4.0 From 1582aa1572b5a9a3144adebfb5a635523a2ec18b Mon Sep 17 00:00:00 2001 From: Jan Kremlacek Date: Mon, 9 Dec 2019 22:08:57 +0100 Subject: [PATCH 335/344] proper go.mod, go.sum --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 3cbfcc37..47c95a32 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/miekg/dns v1.1.22 github.com/mitchellh/hashstructure v1.0.0 github.com/nats-io/nats.go v1.9.1 - github.com/nlopes/slack@d06c2a2b3249b44a9c5dee8485f5a87497beb9ea + github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249 // indirect github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.4.0 diff --git a/go.sum b/go.sum index 113e6bd2..8a137787 100644 --- a/go.sum +++ b/go.sum @@ -294,6 +294,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA= github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk= +github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249 h1:Pr5gZa2VcmktVwq0lyC39MsN5tz356vC/pQHKvq+QBo= +github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk= github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw= github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ= github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= From b29da805391cec3285ea0ab129146b3205be45c2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 9 Dec 2019 22:56:26 +0000 Subject: [PATCH 336/344] Move a few things around --- network/default.go | 824 +++++++++++++++++++++++---------------------- network/node.go | 7 +- 2 files changed, 425 insertions(+), 406 deletions(-) diff --git a/network/default.go b/network/default.go index 9f29414d..a030d9bb 100644 --- a/network/default.go +++ b/network/default.go @@ -74,7 +74,7 @@ type network struct { // whether we've discovered by the network discovered chan bool // solicted checks whether routes were solicited by one node - solicited chan string + solicited chan *node } // message is network message @@ -167,7 +167,7 @@ func newNetwork(opts ...Option) Network { tunClient: make(map[string]transport.Client), peerLinks: make(map[string]tunnel.Link), discovered: make(chan bool, 1), - solicited: make(chan string, 1), + solicited: make(chan *node, 1), } network.node.network = network @@ -202,6 +202,144 @@ func (n *network) Name() string { return n.options.Name } +// acceptNetConn accepts connections from NetworkChannel +func (n *network) acceptNetConn(l tunnel.Listener, recv chan *message) { + var i int + for { + // accept a connection + conn, err := l.Accept() + if err != nil { + sleep := backoff.Do(i) + log.Debugf("Network tunnel [%s] accept error: %v, backing off for %v", ControlChannel, err, sleep) + time.Sleep(sleep) + if i > 5 { + i = 0 + } + i++ + continue + } + + select { + case <-n.closed: + if err := conn.Close(); err != nil { + log.Debugf("Network tunnel [%s] failed to close connection: %v", NetworkChannel, err) + } + return + default: + // go handle NetworkChannel connection + go n.handleNetConn(conn, recv) + } + } +} + +// acceptCtrlConn accepts connections from ControlChannel +func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *message) { + var i int + for { + // accept a connection + conn, err := l.Accept() + if err != nil { + sleep := backoff.Do(i) + log.Debugf("Network tunnel [%s] accept error: %v, backing off for %v", ControlChannel, err, sleep) + time.Sleep(sleep) + if i > 5 { + // reset the counter + i = 0 + } + i++ + continue + } + + select { + case <-n.closed: + if err := conn.Close(); err != nil { + log.Debugf("Network tunnel [%s] failed to close connection: %v", ControlChannel, err) + } + return + default: + // go handle ControlChannel connection + go n.handleCtrlConn(conn, recv) + } + } +} + +// handleCtrlConn handles ControlChannel connections +// advertise advertises routes to the network +func (n *network) advertise(advertChan <-chan *router.Advert) { + hasher := fnv.New64() + for { + select { + // process local adverts and randomly fire them at other nodes + case advert := <-advertChan: + // create a proto advert + var events []*pbRtr.Event + + for _, event := range advert.Events { + // the routes service address + address := event.Route.Address + + // only hash the address if we're advertising our own local routes + if event.Route.Router == advert.Id { + // hash the service before advertising it + hasher.Reset() + // routes for multiple instances of a service will be collapsed here. + // TODO: once we store labels in the table this may need to change + // to include the labels in case they differ but highly unlikely + hasher.Write([]byte(event.Route.Service + n.node.Address())) + address = fmt.Sprintf("%d", hasher.Sum64()) + } + // calculate route metric to advertise + metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link) + // NOTE: we override Gateway, Link and Address here + route := &pbRtr.Route{ + Service: event.Route.Service, + Address: address, + Gateway: n.node.Address(), + Network: event.Route.Network, + Router: event.Route.Router, + Link: DefaultLink, + Metric: metric, + } + e := &pbRtr.Event{ + Type: pbRtr.EventType(event.Type), + Timestamp: event.Timestamp.UnixNano(), + Route: route, + } + events = append(events, e) + } + + msg := &pbRtr.Advert{ + Id: advert.Id, + Type: pbRtr.AdvertType(advert.Type), + Timestamp: advert.Timestamp.UnixNano(), + Events: events, + } + + // send the advert to all on the control channel + // since its not a solicitation + if advert.Type != router.Solicitation { + if err := n.sendMsg("advert", ControlChannel, msg); err != nil { + log.Debugf("Network failed to advertise routes: %v", err) + } + continue + } + + // it's a solication, someone asked for it + // so we're going to pick off the node and send it + select { + case peer := <-n.solicited: + // someone requested the route + n.sendTo("advert", ControlChannel, peer, msg) + default: + // send to all since we can't get anything + n.sendMsg("advert", ControlChannel, msg) + } + case <-n.closed: + return + } + } +} + func (n *network) initNodes(startup bool) { nodes, err := n.resolveNodes() if err != nil && !startup { @@ -306,32 +444,257 @@ func (n *network) handleNetConn(s tunnel.Session, msg chan *message) { } } -// acceptNetConn accepts connections from NetworkChannel -func (n *network) acceptNetConn(l tunnel.Listener, recv chan *message) { - var i int +func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { for { - // accept a connection - conn, err := l.Accept() - if err != nil { - sleep := backoff.Do(i) - log.Debugf("Network tunnel [%s] accept error: %v, backing off for %v", ControlChannel, err, sleep) - time.Sleep(sleep) - if i > 5 { - i = 0 + m := new(transport.Message) + if err := s.Recv(m); err != nil { + log.Debugf("Network tunnel [%s] receive error: %v", ControlChannel, err) + switch err { + case io.EOF, tunnel.ErrReadTimeout: + s.Close() + return } - i++ + continue + } + + // check if peer is set + peer := m.Header["Micro-Peer"] + + // check who the message is intended for + if len(peer) > 0 && peer != n.options.Id { continue } select { + case msg <- &message{ + msg: m, + session: s, + }: + case <-n.closed: + return + } + } +} + +// getHopCount queries network graph and returns hop count for given router +// - Routes for local services have hop count 1 +// - Routes with ID of adjacent nodes have hop count 2 +// - Routes by peers of the advertiser have hop count 3 +// - Routes beyond node neighbourhood have hop count 4 +func (n *network) getHopCount(rtr string) int { + // make sure node.peers are not modified + n.node.RLock() + defer n.node.RUnlock() + + // we are the origin of the route + if rtr == n.options.Id { + return 1 + } + + // the route origin is our peer + if _, ok := n.peers[rtr]; ok { + return 10 + } + + // the route origin is the peer of our peer + for _, peer := range n.peers { + for id := range peer.peers { + if rtr == id { + return 100 + } + } + } + // otherwise we are three hops away + return 1000 +} + +// getRouteMetric calculates router metric and returns it +// Route metric is calculated based on link status and route hopd count +func (n *network) getRouteMetric(router string, gateway string, link string) int64 { + // set the route metric + n.RLock() + defer n.RUnlock() + + // local links are marked as 1 + if link == "local" && gateway == "" { + return 1 + } + + // local links from other gateways as 2 + if link == "local" && gateway != "" { + return 2 + } + + log.Tracef("Network looking up %s link to gateway: %s", link, gateway) + + // attempt to find link based on gateway address + lnk, ok := n.peerLinks[gateway] + if !ok { + log.Debugf("Network failed to find a link to gateway: %s", gateway) + // no link found so infinite metric returned + return math.MaxInt64 + } + + // calculating metric + + delay := lnk.Delay() + hops := n.getHopCount(router) + length := lnk.Length() + + // make sure delay is non-zero + if delay == 0 { + delay = 1 + } + + // make sure length is non-zero + if length == 0 { + log.Debugf("Link length is 0 %v %v", link, lnk.Length()) + length = 10e9 + } + + log.Tracef("Network calculated metric %v delay %v length %v distance %v", (delay*length*int64(hops))/10e6, delay, length, hops) + + return (delay * length * int64(hops)) / 10e6 +} + +// processCtrlChan processes messages received on ControlChannel +func (n *network) processCtrlChan(listener tunnel.Listener) { + defer listener.Close() + + // receive control message queue + recv := make(chan *message, 128) + + // accept ControlChannel cconnections + go n.acceptCtrlConn(listener, recv) + + for { + select { + case m := <-recv: + // switch on type of message and take action + switch m.msg.Header["Micro-Method"] { + case "advert": + pbRtrAdvert := &pbRtr.Advert{} + + if err := proto.Unmarshal(m.msg.Body, pbRtrAdvert); err != nil { + log.Debugf("Network fail to unmarshal advert message: %v", err) + continue + } + + // don't process your own messages + if pbRtrAdvert.Id == n.options.Id { + continue + } + + log.Debugf("Network received advert message from: %s", pbRtrAdvert.Id) + + // loookup advertising node in our peer topology + advertNode := n.node.GetPeerNode(pbRtrAdvert.Id) + if advertNode == nil { + // if we can't find the node in our topology (MaxDepth) we skipp prcessing adverts + log.Debugf("Network skipping advert message from unknown peer: %s", pbRtrAdvert.Id) + continue + } + + var events []*router.Event + + for _, event := range pbRtrAdvert.Events { + // we know the advertising node is not the origin of the route + if pbRtrAdvert.Id != event.Route.Router { + // if the origin router is not the advertising node peer + // we can't rule out potential routing loops so we bail here + if peer := advertNode.GetPeerNode(event.Route.Router); peer == nil { + log.Debugf("Network skipping advert message from peer: %s", pbRtrAdvert.Id) + continue + } + } + + route := router.Route{ + Service: event.Route.Service, + Address: event.Route.Address, + Gateway: event.Route.Gateway, + Network: event.Route.Network, + Router: event.Route.Router, + Link: event.Route.Link, + Metric: event.Route.Metric, + } + + // calculate route metric and add to the advertised metric + // we need to make sure we do not overflow math.MaxInt64 + metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link) + log.Tracef("Network metric for router %s and gateway %s: %v", event.Route.Router, event.Route.Gateway, metric) + + // check we don't overflow max int 64 + if d := route.Metric + metric; d <= 0 { + // set to max int64 if we overflow + route.Metric = math.MaxInt64 + } else { + // set the combined value of metrics otherwise + route.Metric = d + } + + // create router event + e := &router.Event{ + Type: router.EventType(event.Type), + Timestamp: time.Unix(0, pbRtrAdvert.Timestamp), + Route: route, + } + events = append(events, e) + } + + // if no events are eligible for processing continue + if len(events) == 0 { + log.Tracef("Network no events to be processed by router: %s", n.options.Id) + continue + } + + // create an advert and process it + advert := &router.Advert{ + Id: pbRtrAdvert.Id, + Type: router.AdvertType(pbRtrAdvert.Type), + Timestamp: time.Unix(0, pbRtrAdvert.Timestamp), + TTL: time.Duration(pbRtrAdvert.Ttl), + Events: events, + } + + log.Debugf("Network router %s processing advert: %s", n.Id(), advert.Id) + if err := n.router.Process(advert); err != nil { + log.Debugf("Network failed to process advert %s: %v", advert.Id, err) + } + case "solicit": + pbRtrSolicit := &pbRtr.Solicit{} + if err := proto.Unmarshal(m.msg.Body, pbRtrSolicit); err != nil { + log.Debugf("Network fail to unmarshal solicit message: %v", err) + continue + } + + log.Debugf("Network received solicit message from: %s", pbRtrSolicit.Id) + + // ignore solicitation when requested by you + if pbRtrSolicit.Id == n.options.Id { + continue + } + + log.Debugf("Network router flushing routes for: %s", pbRtrSolicit.Id) + + // advertise all the routes when a new node has connected + if err := n.router.Solicit(); err != nil { + log.Debugf("Network failed to solicit routes: %s", err) + } + + peer := &node{ + id: pbRtrSolicit.Id, + link: m.msg.Header["Micro-Link"], + } + + // specify that someone solicited the route + select { + case n.solicited <- peer: + default: + // don't block + } + } case <-n.closed: - if err := conn.Close(); err != nil { - log.Debugf("Network tunnel [%s] failed to close connection: %v", NetworkChannel, err) - } return - default: - // go handle NetworkChannel connection - go n.handleNetConn(conn, recv) } } } @@ -371,13 +734,14 @@ func (n *network) processNetChan(listener tunnel.Listener) { peer := &node{ id: pbNetConnect.Node.Id, address: pbNetConnect.Node.Address, + link: m.msg.Header["Micro-Link"], peers: make(map[string]*node), lastSeen: now, } // update peer links - if err := n.updatePeerLinks(pbNetConnect.Node.Address, m); err != nil { + if err := n.updatePeerLinks(peer); err != nil { log.Debugf("Network failed updating peer links: %s", err) } @@ -385,7 +749,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { if err := n.node.AddPeer(peer); err == ErrPeerExists { log.Debugf("Network peer exists, refreshing: %s", peer.id) // update lastSeen time for the existing node - if err := n.RefreshPeer(peer.id, now); err != nil { + if err := n.RefreshPeer(peer.id, peer.link, now); err != nil { log.Debugf("Network failed refreshing peer %s: %v", peer.id, err) } } @@ -396,10 +760,9 @@ func (n *network) processNetChan(listener tunnel.Listener) { // get node peers down to MaxDepth encoded in protobuf msg := PeersToProto(n.node, MaxDepth) - node := pbNetConnect.Node.Id // advertise yourself to the network - if err := n.sendTo("peer", NetworkChannel, node, msg); err != nil { + if err := n.sendTo("peer", NetworkChannel, peer, msg); err != nil { log.Debugf("Network failed to advertise peers: %v", err) } @@ -410,7 +773,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { // specify that we're soliciting select { - case n.solicited <- node: + case n.solicited <- peer: default: // don't block } @@ -434,13 +797,14 @@ func (n *network) processNetChan(listener tunnel.Listener) { peer := &node{ id: pbNetPeer.Node.Id, address: pbNetPeer.Node.Address, + link: m.msg.Header["Micro-Link"], peers: make(map[string]*node), lastSeen: now, } // update peer links - if err := n.updatePeerLinks(pbNetPeer.Node.Address, m); err != nil { + if err := n.updatePeerLinks(peer); err != nil { log.Debugf("Network failed updating peer links: %s", err) } @@ -450,10 +814,8 @@ func (n *network) processNetChan(listener tunnel.Listener) { Id: n.options.Id, } - node := pbNetPeer.Node.Id - // only solicit this peer - if err := n.sendTo("solicit", ControlChannel, node, msg); err != nil { + if err := n.sendTo("solicit", ControlChannel, peer, msg); err != nil { log.Debugf("Network failed to send solicit message: %s", err) } @@ -467,7 +829,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { log.Debugf("Network peer exists, refreshing: %s", pbNetPeer.Node.Id) // update lastSeen time for the peer - if err := n.RefreshPeer(pbNetPeer.Node.Id, now); err != nil { + if err := n.RefreshPeer(pbNetPeer.Node.Id, peer.link, now); err != nil { log.Debugf("Network failed refreshing peer %s: %v", pbNetPeer.Node.Id, err) } @@ -630,26 +992,43 @@ func (n *network) manage() { } } +func (n *network) sendConnect() { + // send connect message to NetworkChannel + // NOTE: in theory we could do this as soon as + // Dial to NetworkChannel succeeds, but instead + // we initialize all other node resources first + msg := &pbNet.Connect{ + Node: &pbNet.Node{ + Id: n.node.id, + Address: n.node.address, + }, + } + + if err := n.sendMsg("connect", NetworkChannel, msg); err != nil { + log.Debugf("Network failed to send connect message: %s", err) + } +} + // sendTo sends a message to a specific node as a one off. // we need this because when links die, we have no discovery info, // and sending to an existing multicast link doesn't immediately work -func (n *network) sendTo(method, channel, peer string, msg proto.Message) error { +func (n *network) sendTo(method, channel string, peer *node, msg proto.Message) error { body, err := proto.Marshal(msg) if err != nil { return err } - c, err := n.tunnel.Dial(channel, tunnel.DialMode(tunnel.Multicast)) + c, err := n.tunnel.Dial(channel, tunnel.DialMode(tunnel.Multicast), tunnel.DialLink(peer.link)) if err != nil { return err } defer c.Close() - log.Debugf("Network sending %s message from: %s to %s", method, n.options.Id, peer) + log.Debugf("Network sending %s message from: %s to %s", method, n.options.Id, peer.id) return c.Send(&transport.Message{ Header: map[string]string{ "Micro-Method": method, - "Micro-Peer": peer, + "Micro-Peer": peer.id, }, Body: body, }) @@ -682,11 +1061,11 @@ func (n *network) sendMsg(method, channel string, msg proto.Message) error { } // updatePeerLinks updates link for a given peer -func (n *network) updatePeerLinks(peerAddr string, m *message) error { +func (n *network) updatePeerLinks(peer *node) error { n.Lock() defer n.Unlock() - linkId := m.msg.Header["Micro-Link"] + linkId := peer.link log.Tracef("Network looking up link %s in the peer links", linkId) @@ -705,386 +1084,21 @@ func (n *network) updatePeerLinks(peerAddr string, m *message) error { } // if the peerLink is found in the returned links update peerLinks - log.Tracef("Network updating peer links for peer %s", peerAddr) + log.Tracef("Network updating peer links for peer %s", peer.address) // add peerLink to the peerLinks map - if link, ok := n.peerLinks[peerAddr]; ok { + if link, ok := n.peerLinks[peer.address]; ok { // if the existing has better Length then the new, replace it if link.Length() < peerLink.Length() { - n.peerLinks[peerAddr] = peerLink + n.peerLinks[peer.address] = peerLink } } else { - n.peerLinks[peerAddr] = peerLink + n.peerLinks[peer.address] = peerLink } return nil } -// handleCtrlConn handles ControlChannel connections -func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { - for { - m := new(transport.Message) - if err := s.Recv(m); err != nil { - log.Debugf("Network tunnel [%s] receive error: %v", ControlChannel, err) - switch err { - case io.EOF, tunnel.ErrReadTimeout: - s.Close() - return - } - continue - } - - // check if peer is set - peer := m.Header["Micro-Peer"] - - // check who the message is intended for - if len(peer) > 0 && peer != n.options.Id { - continue - } - - select { - case msg <- &message{ - msg: m, - session: s, - }: - case <-n.closed: - return - } - } -} - -// acceptCtrlConn accepts connections from ControlChannel -func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *message) { - var i int - for { - // accept a connection - conn, err := l.Accept() - if err != nil { - sleep := backoff.Do(i) - log.Debugf("Network tunnel [%s] accept error: %v, backing off for %v", ControlChannel, err, sleep) - time.Sleep(sleep) - if i > 5 { - // reset the counter - i = 0 - } - i++ - continue - } - - select { - case <-n.closed: - if err := conn.Close(); err != nil { - log.Debugf("Network tunnel [%s] failed to close connection: %v", ControlChannel, err) - } - return - default: - // go handle ControlChannel connection - go n.handleCtrlConn(conn, recv) - } - } -} - -// getHopCount queries network graph and returns hop count for given router -// - Routes for local services have hop count 1 -// - Routes with ID of adjacent nodes have hop count 2 -// - Routes by peers of the advertiser have hop count 3 -// - Routes beyond node neighbourhood have hop count 4 -func (n *network) getHopCount(rtr string) int { - // make sure node.peers are not modified - n.node.RLock() - defer n.node.RUnlock() - - // we are the origin of the route - if rtr == n.options.Id { - return 1 - } - - // the route origin is our peer - if _, ok := n.peers[rtr]; ok { - return 10 - } - - // the route origin is the peer of our peer - for _, peer := range n.peers { - for id := range peer.peers { - if rtr == id { - return 100 - } - } - } - // otherwise we are three hops away - return 1000 -} - -// getRouteMetric calculates router metric and returns it -// Route metric is calculated based on link status and route hopd count -func (n *network) getRouteMetric(router string, gateway string, link string) int64 { - // set the route metric - n.RLock() - defer n.RUnlock() - - if link == "local" && gateway == "" { - return 1 - } - - if link == "local" && gateway != "" { - return 2 - } - - log.Tracef("Network looking up %s link to gateway: %s", link, gateway) - if link, ok := n.peerLinks[gateway]; ok { - // maka sure delay is non-zero - delay := link.Delay() - if delay == 0 { - delay = 1 - } - // get the route hop count - hops := n.getHopCount(router) - // make sure length is non-zero - length := link.Length() - if length == 0 { - log.Debugf("Link length is 0 %v %v", link, link.Length()) - length = 10e9 - } - log.Tracef("Network calculated metric %v delay %v length %v distance %v", (delay*length*int64(hops))/10e6, delay, length, hops) - return (delay * length * int64(hops)) / 10e6 - } - - log.Debugf("Network failed to find a link to gateway: %s", gateway) - - return math.MaxInt64 -} - -// processCtrlChan processes messages received on ControlChannel -func (n *network) processCtrlChan(listener tunnel.Listener) { - defer listener.Close() - - // receive control message queue - recv := make(chan *message, 128) - - // accept ControlChannel cconnections - go n.acceptCtrlConn(listener, recv) - - for { - select { - case m := <-recv: - // switch on type of message and take action - switch m.msg.Header["Micro-Method"] { - case "advert": - pbRtrAdvert := &pbRtr.Advert{} - - if err := proto.Unmarshal(m.msg.Body, pbRtrAdvert); err != nil { - log.Debugf("Network fail to unmarshal advert message: %v", err) - continue - } - - // don't process your own messages - if pbRtrAdvert.Id == n.options.Id { - continue - } - - log.Debugf("Network received advert message from: %s", pbRtrAdvert.Id) - - // loookup advertising node in our peer topology - advertNode := n.node.GetPeerNode(pbRtrAdvert.Id) - if advertNode == nil { - // if we can't find the node in our topology (MaxDepth) we skipp prcessing adverts - log.Debugf("Network skipping advert message from unknown peer: %s", pbRtrAdvert.Id) - continue - } - - var events []*router.Event - - for _, event := range pbRtrAdvert.Events { - // we know the advertising node is not the origin of the route - if pbRtrAdvert.Id != event.Route.Router { - // if the origin router is not the advertising node peer - // we can't rule out potential routing loops so we bail here - if peer := advertNode.GetPeerNode(event.Route.Router); peer == nil { - log.Debugf("Network skipping advert message from peer: %s", pbRtrAdvert.Id) - continue - } - } - - route := router.Route{ - Service: event.Route.Service, - Address: event.Route.Address, - Gateway: event.Route.Gateway, - Network: event.Route.Network, - Router: event.Route.Router, - Link: event.Route.Link, - Metric: event.Route.Metric, - } - - // calculate route metric and add to the advertised metric - // we need to make sure we do not overflow math.MaxInt64 - metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link) - log.Tracef("Network metric for router %s and gateway %s: %v", event.Route.Router, event.Route.Gateway, metric) - - // check we don't overflow max int 64 - if d := route.Metric + metric; d <= 0 { - // set to max int64 if we overflow - route.Metric = math.MaxInt64 - } else { - // set the combined value of metrics otherwise - route.Metric = d - } - - // create router event - e := &router.Event{ - Type: router.EventType(event.Type), - Timestamp: time.Unix(0, pbRtrAdvert.Timestamp), - Route: route, - } - events = append(events, e) - } - - // if no events are eligible for processing continue - if len(events) == 0 { - log.Tracef("Network no events to be processed by router: %s", n.options.Id) - continue - } - - // create an advert and process it - advert := &router.Advert{ - Id: pbRtrAdvert.Id, - Type: router.AdvertType(pbRtrAdvert.Type), - Timestamp: time.Unix(0, pbRtrAdvert.Timestamp), - TTL: time.Duration(pbRtrAdvert.Ttl), - Events: events, - } - - log.Debugf("Network router %s processing advert: %s", n.Id(), advert.Id) - if err := n.router.Process(advert); err != nil { - log.Debugf("Network failed to process advert %s: %v", advert.Id, err) - } - case "solicit": - pbRtrSolicit := &pbRtr.Solicit{} - if err := proto.Unmarshal(m.msg.Body, pbRtrSolicit); err != nil { - log.Debugf("Network fail to unmarshal solicit message: %v", err) - continue - } - - log.Debugf("Network received solicit message from: %s", pbRtrSolicit.Id) - - // ignore solicitation when requested by you - if pbRtrSolicit.Id == n.options.Id { - continue - } - - log.Debugf("Network router flushing routes for: %s", pbRtrSolicit.Id) - - // advertise all the routes when a new node has connected - if err := n.router.Solicit(); err != nil { - log.Debugf("Network failed to solicit routes: %s", err) - } - - // specify that someone solicited the route - select { - case n.solicited <- pbRtrSolicit.Id: - default: - // don't block - } - } - case <-n.closed: - return - } - } -} - -// advertise advertises routes to the network -func (n *network) advertise(advertChan <-chan *router.Advert) { - hasher := fnv.New64() - for { - select { - // process local adverts and randomly fire them at other nodes - case advert := <-advertChan: - // create a proto advert - var events []*pbRtr.Event - - for _, event := range advert.Events { - // the routes service address - address := event.Route.Address - - // only hash the address if we're advertising our own local routes - if event.Route.Router == advert.Id { - // hash the service before advertising it - hasher.Reset() - // routes for multiple instances of a service will be collapsed here. - // TODO: once we store labels in the table this may need to change - // to include the labels in case they differ but highly unlikely - hasher.Write([]byte(event.Route.Service + n.node.Address())) - address = fmt.Sprintf("%d", hasher.Sum64()) - } - // calculate route metric to advertise - metric := n.getRouteMetric(event.Route.Router, event.Route.Gateway, event.Route.Link) - // NOTE: we override Gateway, Link and Address here - route := &pbRtr.Route{ - Service: event.Route.Service, - Address: address, - Gateway: n.node.Address(), - Network: event.Route.Network, - Router: event.Route.Router, - Link: DefaultLink, - Metric: metric, - } - e := &pbRtr.Event{ - Type: pbRtr.EventType(event.Type), - Timestamp: event.Timestamp.UnixNano(), - Route: route, - } - events = append(events, e) - } - - msg := &pbRtr.Advert{ - Id: advert.Id, - Type: pbRtr.AdvertType(advert.Type), - Timestamp: advert.Timestamp.UnixNano(), - Events: events, - } - - // send the advert to all on the control channel - // since its not a solicitation - if advert.Type != router.Solicitation { - if err := n.sendMsg("advert", ControlChannel, msg); err != nil { - log.Debugf("Network failed to advertise routes: %v", err) - } - continue - } - - // it's a solication, someone asked for it - // so we're going to pick off the node and send it - select { - case node := <-n.solicited: - // someone requested the route - n.sendTo("advert", ControlChannel, node, msg) - default: - // send to all since we can't get anything - n.sendMsg("advert", ControlChannel, msg) - } - case <-n.closed: - return - } - } -} - -func (n *network) sendConnect() { - // send connect message to NetworkChannel - // NOTE: in theory we could do this as soon as - // Dial to NetworkChannel succeeds, but instead - // we initialize all other node resources first - msg := &pbNet.Connect{ - Node: &pbNet.Node{ - Id: n.node.id, - Address: n.node.address, - }, - } - - if err := n.sendMsg("connect", NetworkChannel, msg); err != nil { - log.Debugf("Network failed to send connect message: %s", err) - } -} - // connect will wait for a link to be established and send the connect // message. We're trying to ensure convergence pretty quickly. So we want // to hear back. In the case we become completely disconnected we'll diff --git a/network/node.go b/network/node.go index f1a51b7d..9964f347 100644 --- a/network/node.go +++ b/network/node.go @@ -28,6 +28,8 @@ type node struct { id string // address is node address address string + // link on which we communicate with the peer + link string // peers are nodes with direct link to this node peers map[string]*node // network returns the node network @@ -127,7 +129,7 @@ func (n *node) UpdatePeer(peer *node) error { // RefreshPeer updates node timestamp // It returns false if the peer has not been found. -func (n *node) RefreshPeer(id string, now time.Time) error { +func (n *node) RefreshPeer(id, link string, now time.Time) error { n.Lock() defer n.Unlock() @@ -136,6 +138,9 @@ func (n *node) RefreshPeer(id string, now time.Time) error { return ErrPeerNotFound } + // set peer link + peer.link = link + if peer.lastSeen.Before(now) { peer.lastSeen = now } From 7e46ff5d92af0b0299accbd78036bb6c0300b90b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 10 Dec 2019 09:08:03 +0000 Subject: [PATCH 337/344] strip some more logging down --- network/default.go | 4 ++-- router/default.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/network/default.go b/network/default.go index a030d9bb..14150527 100644 --- a/network/default.go +++ b/network/default.go @@ -656,7 +656,7 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { Events: events, } - log.Debugf("Network router %s processing advert: %s", n.Id(), advert.Id) + log.Tracef("Network router %s processing advert: %s", n.Id(), advert.Id) if err := n.router.Process(advert); err != nil { log.Debugf("Network failed to process advert %s: %v", advert.Id, err) } @@ -674,7 +674,7 @@ func (n *network) processCtrlChan(listener tunnel.Listener) { continue } - log.Debugf("Network router flushing routes for: %s", pbRtrSolicit.Id) + log.Tracef("Network router flushing routes for: %s", pbRtrSolicit.Id) // advertise all the routes when a new node has connected if err := n.router.Solicit(); err != nil { diff --git a/router/default.go b/router/default.go index a1995826..459488df 100644 --- a/router/default.go +++ b/router/default.go @@ -712,7 +712,7 @@ func (r *router) Process(a *Advert) error { return events[i].Timestamp.Before(events[j].Timestamp) }) - log.Debugf("Router %s processing advert from: %s", r.options.Id, a.Id) + log.Tracef("Router %s processing advert from: %s", r.options.Id, a.Id) for _, event := range events { // skip if the router is the origin of this route From f8533551a4b98281bcf528b92702327157b4b28c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 10 Dec 2019 09:09:24 +0000 Subject: [PATCH 338/344] move debug to trace for network peer refresh --- network/default.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/network/default.go b/network/default.go index 14150527..19b9c8c6 100644 --- a/network/default.go +++ b/network/default.go @@ -747,7 +747,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { // add peer to the list of node peers if err := n.node.AddPeer(peer); err == ErrPeerExists { - log.Debugf("Network peer exists, refreshing: %s", peer.id) + log.Tracef("Network peer exists, refreshing: %s", peer.id) // update lastSeen time for the existing node if err := n.RefreshPeer(peer.id, peer.link, now); err != nil { log.Debugf("Network failed refreshing peer %s: %v", peer.id, err) @@ -826,7 +826,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { continue } - log.Debugf("Network peer exists, refreshing: %s", pbNetPeer.Node.Id) + log.Tracef("Network peer exists, refreshing: %s", pbNetPeer.Node.Id) // update lastSeen time for the peer if err := n.RefreshPeer(pbNetPeer.Node.Id, peer.link, now); err != nil { From d50f30d7435630b55af80015626ee57e139f152d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 10 Dec 2019 11:46:13 +0000 Subject: [PATCH 339/344] strip handlers --- broker/service/handler/handler.go | 66 ------ client/selector/router/router.go | 2 +- go.mod | 2 +- network/default.go | 4 +- network/node.go | 2 +- network/node_test.go | 2 +- network/service/handler/handler.go | 207 ------------------ network/{ => service}/proto/network.pb.go | 64 +++--- .../{ => service}/proto/network.pb.micro.go | 2 +- network/{ => service}/proto/network.proto | 2 +- registry/service/handler/handler.go | 82 ------- router/handler/router.go | 190 ---------------- router/handler/table.go | 115 ---------- router/{ => service}/proto/router.pb.go | 0 router/{ => service}/proto/router.pb.micro.go | 0 router/{ => service}/proto/router.proto | 0 router/service/service.go | 2 +- router/service/table.go | 2 +- router/service/watcher.go | 2 +- runtime/service/handler/handler.go | 142 ------------ store/service/handler/handler.go | 89 -------- 21 files changed, 43 insertions(+), 934 deletions(-) delete mode 100644 broker/service/handler/handler.go delete mode 100644 network/service/handler/handler.go rename network/{ => service}/proto/network.pb.go (88%) rename network/{ => service}/proto/network.pb.micro.go (99%) rename network/{ => service}/proto/network.proto (96%) delete mode 100644 registry/service/handler/handler.go delete mode 100644 router/handler/router.go delete mode 100644 router/handler/table.go rename router/{ => service}/proto/router.pb.go (100%) rename router/{ => service}/proto/router.pb.micro.go (100%) rename router/{ => service}/proto/router.proto (100%) delete mode 100644 runtime/service/handler/handler.go delete mode 100644 store/service/handler/handler.go diff --git a/broker/service/handler/handler.go b/broker/service/handler/handler.go deleted file mode 100644 index 3c96fd0d..00000000 --- a/broker/service/handler/handler.go +++ /dev/null @@ -1,66 +0,0 @@ -package handler - -import ( - "context" - - "github.com/micro/go-micro/broker" - pb "github.com/micro/go-micro/broker/service/proto" - "github.com/micro/go-micro/errors" - "github.com/micro/go-micro/util/log" -) - -type Broker struct { - Broker broker.Broker -} - -func (b *Broker) Publish(ctx context.Context, req *pb.PublishRequest, rsp *pb.Empty) error { - log.Debugf("Publishing message to %s topic", req.Topic) - err := b.Broker.Publish(req.Topic, &broker.Message{ - Header: req.Message.Header, - Body: req.Message.Body, - }) - log.Debugf("Published message to %s topic", req.Topic) - if err != nil { - return errors.InternalServerError("go.micro.broker", err.Error()) - } - return nil -} - -func (b *Broker) Subscribe(ctx context.Context, req *pb.SubscribeRequest, stream pb.Broker_SubscribeStream) error { - errChan := make(chan error, 1) - - // message handler to stream back messages from broker - handler := func(p broker.Event) error { - if err := stream.Send(&pb.Message{ - Header: p.Message().Header, - Body: p.Message().Body, - }); err != nil { - select { - case errChan <- err: - return err - default: - return err - } - } - return nil - } - - log.Debugf("Subscribing to %s topic", req.Topic) - sub, err := b.Broker.Subscribe(req.Topic, handler, broker.Queue(req.Queue)) - if err != nil { - return errors.InternalServerError("go.micro.broker", err.Error()) - } - defer func() { - log.Debugf("Unsubscribing from topic %s", req.Topic) - sub.Unsubscribe() - }() - - select { - case <-ctx.Done(): - log.Debugf("Context done for subscription to topic %s", req.Topic) - return nil - case err := <-errChan: - log.Debugf("Subscription error for topic %s: %v", req.Topic, err) - return err - } -} diff --git a/client/selector/router/router.go b/client/selector/router/router.go index ed7c10e6..d8e8aae3 100644 --- a/client/selector/router/router.go +++ b/client/selector/router/router.go @@ -11,7 +11,7 @@ import ( "github.com/micro/go-micro/client/selector" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/router" - pb "github.com/micro/go-micro/router/proto" + pb "github.com/micro/go-micro/router/service/proto" ) type routerSelector struct { diff --git a/go.mod b/go.mod index 47c95a32..6b438e41 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/miekg/dns v1.1.22 github.com/mitchellh/hashstructure v1.0.0 github.com/nats-io/nats.go v1.9.1 - github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249 // indirect + github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249 github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.4.0 diff --git a/network/default.go b/network/default.go index 19b9c8c6..914653ec 100644 --- a/network/default.go +++ b/network/default.go @@ -12,11 +12,11 @@ import ( "github.com/golang/protobuf/proto" "github.com/micro/go-micro/client" rtr "github.com/micro/go-micro/client/selector/router" - pbNet "github.com/micro/go-micro/network/proto" "github.com/micro/go-micro/network/resolver/dns" + pbNet "github.com/micro/go-micro/network/service/proto" "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/router" - pbRtr "github.com/micro/go-micro/router/proto" + pbRtr "github.com/micro/go-micro/router/service/proto" "github.com/micro/go-micro/server" "github.com/micro/go-micro/transport" "github.com/micro/go-micro/tunnel" diff --git a/network/node.go b/network/node.go index 9964f347..658c0964 100644 --- a/network/node.go +++ b/network/node.go @@ -6,7 +6,7 @@ import ( "sync" "time" - pb "github.com/micro/go-micro/network/proto" + pb "github.com/micro/go-micro/network/service/proto" ) var ( diff --git a/network/node_test.go b/network/node_test.go index 71b21a19..51c4988f 100644 --- a/network/node_test.go +++ b/network/node_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - pb "github.com/micro/go-micro/network/proto" + pb "github.com/micro/go-micro/network/service/proto" ) var ( diff --git a/network/service/handler/handler.go b/network/service/handler/handler.go deleted file mode 100644 index d8538a7c..00000000 --- a/network/service/handler/handler.go +++ /dev/null @@ -1,207 +0,0 @@ -// Package handler implements network RPC handler -package handler - -import ( - "context" - - "github.com/micro/go-micro/errors" - "github.com/micro/go-micro/network" - pbNet "github.com/micro/go-micro/network/proto" - "github.com/micro/go-micro/router" - pbRtr "github.com/micro/go-micro/router/proto" - "github.com/micro/go-micro/util/log" -) - -// Network implements network handler -type Network struct { - Network network.Network -} - -func flatten(n network.Node, visited map[string]bool) []network.Node { - // if node is nil runaway - if n == nil { - return nil - } - - // set visisted - if visited == nil { - visited = make(map[string]bool) - } - - // create new list of nodes - //nolint:prealloc - var nodes []network.Node - - // check if already visited - if !visited[n.Id()] { - // append the current node - nodes = append(nodes, n) - } - - // set to visited - visited[n.Id()] = true - - // visit the list of peers - for _, node := range n.Peers() { - nodes = append(nodes, flatten(node, visited)...) - } - - return nodes -} - -func (n *Network) Connect(ctx context.Context, req *pbNet.ConnectRequest, resp *pbNet.ConnectResponse) error { - if len(req.Nodes) == 0 { - return nil - } - - // get list of existing nodes - nodes := n.Network.Options().Nodes - - // generate a node map - nodeMap := make(map[string]bool) - - for _, node := range nodes { - nodeMap[node] = true - } - - for _, node := range req.Nodes { - // TODO: we may have been provided a network only - // so process anad resolve node.Network - if len(node.Address) == 0 { - continue - } - - // already exists - if _, ok := nodeMap[node.Address]; ok { - continue - } - - nodeMap[node.Address] = true - nodes = append(nodes, node.Address) - } - - log.Infof("Network.Connect setting peers: %v", nodes) - - // reinitialise the peers - n.Network.Init( - network.Nodes(nodes...), - ) - - // call the connect method - n.Network.Connect() - - return nil -} - -// Nodes returns the list of nodes -func (n *Network) Nodes(ctx context.Context, req *pbNet.NodesRequest, resp *pbNet.NodesResponse) error { - // root node - nodes := map[string]network.Node{} - - // get peers encoded into protobuf - peers := flatten(n.Network, nil) - - // walk all the peers - for _, peer := range peers { - if peer == nil { - continue - } - if _, ok := nodes[peer.Id()]; ok { - continue - } - - // add to visited list - nodes[n.Network.Id()] = peer - - resp.Nodes = append(resp.Nodes, &pbNet.Node{ - Id: peer.Id(), - Address: peer.Address(), - }) - } - - return nil -} - -// Graph returns the network graph from this root node -func (n *Network) Graph(ctx context.Context, req *pbNet.GraphRequest, resp *pbNet.GraphResponse) error { - depth := uint(req.Depth) - if depth <= 0 || depth > network.MaxDepth { - depth = network.MaxDepth - } - - // get peers encoded into protobuf - peers := network.PeersToProto(n.Network, depth) - - // set the root node - resp.Root = peers - - return nil -} - -// Routes returns a list of routing table routes -func (n *Network) Routes(ctx context.Context, req *pbNet.RoutesRequest, resp *pbNet.RoutesResponse) error { - // build query - - var qOpts []router.QueryOption - - if q := req.Query; q != nil { - if len(q.Service) > 0 { - qOpts = append(qOpts, router.QueryService(q.Service)) - } - if len(q.Address) > 0 { - qOpts = append(qOpts, router.QueryAddress(q.Address)) - } - if len(q.Gateway) > 0 { - qOpts = append(qOpts, router.QueryGateway(q.Gateway)) - } - if len(q.Router) > 0 { - qOpts = append(qOpts, router.QueryRouter(q.Router)) - } - if len(q.Network) > 0 { - qOpts = append(qOpts, router.QueryNetwork(q.Network)) - } - } - - routes, err := n.Network.Options().Router.Table().Query(qOpts...) - if err != nil { - return errors.InternalServerError("go.micro.network", "failed to list routes: %s", err) - } - - respRoutes := make([]*pbRtr.Route, 0, len(routes)) - for _, route := range routes { - respRoute := &pbRtr.Route{ - Service: route.Service, - Address: route.Address, - Gateway: route.Gateway, - Network: route.Network, - Router: route.Router, - Link: route.Link, - Metric: int64(route.Metric), - } - respRoutes = append(respRoutes, respRoute) - } - - resp.Routes = respRoutes - - return nil -} - -// Services returns a list of services based on the routing table -func (n *Network) Services(ctx context.Context, req *pbNet.ServicesRequest, resp *pbNet.ServicesResponse) error { - routes, err := n.Network.Options().Router.Table().List() - if err != nil { - return errors.InternalServerError("go.micro.network", "failed to list services: %s", err) - } - - services := make(map[string]bool) - - for _, route := range routes { - if _, ok := services[route.Service]; ok { - continue - } - services[route.Service] = true - resp.Services = append(resp.Services, route.Service) - } - - return nil -} diff --git a/network/proto/network.pb.go b/network/service/proto/network.pb.go similarity index 88% rename from network/proto/network.pb.go rename to network/service/proto/network.pb.go index 97b38402..d94687f5 100644 --- a/network/proto/network.pb.go +++ b/network/service/proto/network.pb.go @@ -6,7 +6,7 @@ package go_micro_network import ( fmt "fmt" proto "github.com/golang/protobuf/proto" - proto1 "github.com/micro/go-micro/router/proto" + proto1 "github.com/micro/go-micro/router/service/proto" math "math" ) @@ -697,41 +697,41 @@ func init() { } var fileDescriptor_0b7953b26a7c4730 = []byte{ - // 573 bytes of a gzipped FileDescriptorProto + // 576 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x61, 0x6a, 0xdb, 0x4c, 0x10, 0x8d, 0x2c, 0xcb, 0x76, 0xe6, 0x8b, 0xfd, 0xb9, 0x4b, 0x49, 0x85, 0x7e, 0xb4, 0xee, 0xe2, - 0x1f, 0xa1, 0x34, 0x32, 0xc4, 0x04, 0x4a, 0x43, 0x43, 0x20, 0x94, 0x42, 0x21, 0x21, 0x55, 0x2e, + 0x1f, 0xa1, 0x34, 0x32, 0x24, 0x04, 0x4a, 0x4d, 0x43, 0x20, 0x94, 0x42, 0x21, 0x21, 0x55, 0x2e, 0x50, 0xc5, 0x1a, 0x6c, 0x93, 0x58, 0xeb, 0xac, 0xd6, 0x09, 0x3e, 0x41, 0x8f, 0xd0, 0x33, 0xf5, 0x56, 0x65, 0x77, 0x47, 0x8a, 0x1d, 0xcb, 0xa2, 0xf9, 0xe7, 0xd1, 0xbc, 0xf7, 0x66, 0x67, 0xe6, - 0x8d, 0xe1, 0x78, 0x3c, 0x55, 0x93, 0xc5, 0x4d, 0x38, 0x12, 0xb3, 0xc1, 0x6c, 0x3a, 0x92, 0x62, + 0x8d, 0xe1, 0x64, 0x3c, 0x55, 0x93, 0xc5, 0x4d, 0x38, 0x12, 0xb3, 0xc1, 0x6c, 0x3a, 0x92, 0x62, 0x30, 0x16, 0x87, 0xf6, 0x47, 0x8a, 0xea, 0x51, 0xc8, 0xdb, 0xc1, 0x5c, 0x0a, 0x55, 0x44, 0xa1, 0x89, 0x58, 0x77, 0x2c, 0x42, 0x83, 0x0a, 0xe9, 0x7b, 0x30, 0xdc, 0x2e, 0x24, 0xc5, 0x42, 0xa1, - 0x24, 0x1d, 0x1b, 0x58, 0x19, 0xfe, 0xcb, 0x01, 0xef, 0xc7, 0x02, 0xe5, 0x92, 0xf9, 0xd0, 0xcc, - 0x50, 0x3e, 0x4c, 0x47, 0xe8, 0x3b, 0x3d, 0xe7, 0x60, 0x37, 0xca, 0x43, 0x9d, 0x89, 0x93, 0x44, - 0x62, 0x96, 0xf9, 0x35, 0x9b, 0xa1, 0x50, 0x67, 0xc6, 0xb1, 0xc2, 0xc7, 0x78, 0xe9, 0xbb, 0x36, - 0x43, 0x21, 0xdb, 0x87, 0x86, 0xad, 0xe3, 0xd7, 0x4d, 0x82, 0x22, 0xcd, 0xa0, 0xf7, 0xfa, 0x9e, - 0x65, 0x50, 0xc8, 0x4f, 0xa1, 0x73, 0x2e, 0xd2, 0x14, 0x47, 0x2a, 0xc2, 0xfb, 0x05, 0x66, 0x8a, - 0x7d, 0x04, 0x2f, 0x15, 0x09, 0x66, 0xbe, 0xd3, 0x73, 0x0f, 0xfe, 0x3b, 0xda, 0x0f, 0x9f, 0xb7, - 0x1c, 0x5e, 0x8a, 0x04, 0x23, 0x0b, 0xe2, 0xaf, 0xe0, 0xff, 0x82, 0x9f, 0xcd, 0x45, 0x9a, 0x21, - 0xef, 0xc3, 0x9e, 0x46, 0x64, 0xb9, 0xe0, 0x6b, 0xf0, 0x12, 0x9c, 0xab, 0x89, 0x69, 0xb0, 0x1d, - 0xd9, 0x80, 0x7f, 0x81, 0x36, 0xa1, 0x2c, 0xed, 0x85, 0x75, 0xfb, 0xb0, 0xf7, 0x4d, 0xc6, 0xf3, - 0x49, 0x75, 0x91, 0x13, 0x68, 0x13, 0x8a, 0x8a, 0x7c, 0x80, 0xba, 0x14, 0x42, 0x19, 0x54, 0x69, - 0x8d, 0x2b, 0x44, 0x19, 0x19, 0x0c, 0x3f, 0x85, 0x76, 0xa4, 0xc7, 0x57, 0x34, 0x72, 0x08, 0xde, - 0xbd, 0x5e, 0x1a, 0xb1, 0xdf, 0x6c, 0xb2, 0xcd, 0x4e, 0x23, 0x8b, 0xe2, 0x67, 0xd0, 0xc9, 0xf9, - 0x54, 0x3d, 0xa4, 0xf5, 0x94, 0xf4, 0x48, 0xf6, 0x30, 0x04, 0x5a, 0x9b, 0x19, 0xee, 0xb5, 0x75, - 0x43, 0xfe, 0x06, 0x1e, 0x42, 0xf7, 0xe9, 0x13, 0xc9, 0x06, 0xd0, 0x22, 0xd3, 0x58, 0xe1, 0xdd, - 0xa8, 0x88, 0xf9, 0x1f, 0x07, 0xea, 0x7a, 0x6e, 0xac, 0x03, 0xb5, 0x69, 0x42, 0x1e, 0xab, 0x4d, - 0x93, 0x6a, 0x7b, 0xe5, 0x66, 0x71, 0xd7, 0xcc, 0xc2, 0xce, 0xa0, 0x35, 0x43, 0x15, 0x27, 0xb1, - 0x8a, 0xfd, 0xba, 0xe9, 0xa0, 0x5f, 0xbe, 0xa5, 0xf0, 0x82, 0x60, 0x5f, 0x53, 0x25, 0x97, 0x51, - 0xc1, 0x0a, 0x4e, 0xa0, 0xbd, 0x96, 0x62, 0x5d, 0x70, 0x6f, 0x71, 0x49, 0xef, 0xd2, 0x3f, 0xf5, - 0x26, 0x1f, 0xe2, 0xbb, 0x05, 0xd2, 0xb3, 0x6c, 0xf0, 0xb9, 0xf6, 0xc9, 0xe1, 0xc7, 0xd0, 0x24, - 0xaf, 0xe9, 0x3d, 0x6a, 0x1f, 0x6c, 0xdf, 0xa3, 0xf1, 0x8a, 0xc1, 0xf0, 0x21, 0x78, 0xe7, 0x77, - 0xc2, 0x2e, 0xff, 0x9f, 0x49, 0x3f, 0xa1, 0xae, 0xad, 0xf0, 0x12, 0x8e, 0x76, 0xf0, 0x1c, 0x51, - 0xea, 0x81, 0xba, 0x15, 0xee, 0xb2, 0xa0, 0xa3, 0xdf, 0x2e, 0x34, 0x2f, 0x69, 0xb0, 0x57, 0x4f, - 0x9d, 0xf5, 0x36, 0x59, 0xeb, 0x07, 0x1a, 0xbc, 0xaf, 0x40, 0xd0, 0x09, 0xee, 0xb0, 0xef, 0xe0, - 0x19, 0xe7, 0xb3, 0xb7, 0x9b, 0xe8, 0xd5, 0xc3, 0x09, 0xde, 0x6d, 0xcd, 0xaf, 0x6a, 0x99, 0x53, - 0x2d, 0xd3, 0x5a, 0xbd, 0xf4, 0x32, 0xad, 0xb5, 0x1b, 0xe7, 0x3b, 0xec, 0x02, 0x1a, 0xf6, 0x28, - 0x58, 0x09, 0x78, 0xed, 0xdc, 0x82, 0xde, 0x76, 0x40, 0x21, 0x77, 0x0d, 0xad, 0xfc, 0x1c, 0x58, - 0xc9, 0x5c, 0x9e, 0x5d, 0x4f, 0xc0, 0xab, 0x20, 0xb9, 0xe8, 0x4d, 0xc3, 0xfc, 0x49, 0x0f, 0xff, - 0x06, 0x00, 0x00, 0xff, 0xff, 0x79, 0x8a, 0x5f, 0xf0, 0x24, 0x06, 0x00, 0x00, + 0x1c, 0x64, 0x28, 0x1f, 0xa6, 0x23, 0x24, 0x3d, 0xfb, 0xd1, 0xca, 0xf1, 0x5f, 0x0e, 0x78, 0x3f, + 0x16, 0x28, 0x97, 0xcc, 0x87, 0x26, 0xe1, 0x7c, 0xa7, 0xe7, 0x1c, 0xec, 0x46, 0x79, 0xa8, 0x33, + 0x71, 0x92, 0x48, 0xcc, 0x32, 0xbf, 0x66, 0x33, 0x14, 0xea, 0xcc, 0x38, 0x56, 0xf8, 0x18, 0x2f, + 0x7d, 0xd7, 0x66, 0x28, 0x64, 0xfb, 0xd0, 0xb0, 0x75, 0xfc, 0xba, 0x49, 0x50, 0xa4, 0x19, 0xf4, + 0x6e, 0xdf, 0xb3, 0x0c, 0x0a, 0xf9, 0x29, 0x74, 0xce, 0x45, 0x9a, 0xe2, 0x48, 0x45, 0x78, 0xbf, + 0xc0, 0x4c, 0xb1, 0x8f, 0xe0, 0xa5, 0x22, 0xc1, 0xcc, 0x77, 0x7a, 0xee, 0xc1, 0x7f, 0x47, 0xfb, + 0xe1, 0xf3, 0xd6, 0xc3, 0x4b, 0x91, 0x60, 0x64, 0x41, 0xfc, 0x15, 0xfc, 0x5f, 0xf0, 0xb3, 0xb9, + 0x48, 0x33, 0xe4, 0x7d, 0xd8, 0xd3, 0x88, 0x2c, 0x17, 0x7c, 0x0d, 0x5e, 0x82, 0x73, 0x35, 0x31, + 0x0d, 0xb6, 0x23, 0x1b, 0xf0, 0x2f, 0xd0, 0x26, 0x94, 0xa5, 0xbd, 0xb0, 0x6e, 0x1f, 0xf6, 0xbe, + 0xc9, 0x78, 0x3e, 0xa9, 0x2e, 0x32, 0x84, 0x36, 0xa1, 0xa8, 0xc8, 0x07, 0xa8, 0x4b, 0x21, 0x94, + 0x41, 0x95, 0xd6, 0xb8, 0x42, 0x94, 0x91, 0xc1, 0xf0, 0x53, 0x68, 0x47, 0x7a, 0x7c, 0x45, 0x23, + 0x87, 0xe0, 0xdd, 0xeb, 0xa5, 0x11, 0xfb, 0xcd, 0x26, 0xdb, 0xec, 0x34, 0xb2, 0x28, 0x7e, 0x06, + 0x9d, 0x9c, 0x4f, 0xd5, 0x43, 0x5a, 0x4f, 0x49, 0x8f, 0x64, 0x0f, 0x43, 0xa0, 0xb5, 0x99, 0xe1, + 0x5e, 0x5b, 0x37, 0xe4, 0x6f, 0xe0, 0x21, 0x74, 0x9f, 0x3e, 0x91, 0x6c, 0x00, 0x2d, 0x32, 0x8d, + 0x15, 0xde, 0x8d, 0x8a, 0x98, 0xff, 0x71, 0xa0, 0xae, 0xe7, 0xc6, 0x3a, 0x50, 0x9b, 0x26, 0xe4, + 0xb1, 0xda, 0x34, 0xa9, 0xb6, 0x57, 0x6e, 0x16, 0x77, 0xcd, 0x2c, 0xec, 0x0c, 0x5a, 0x33, 0x54, + 0x71, 0x12, 0xab, 0xd8, 0xaf, 0x9b, 0x0e, 0xfa, 0xe5, 0x5b, 0x0a, 0x2f, 0x08, 0xf6, 0x35, 0x55, + 0x72, 0x19, 0x15, 0xac, 0x60, 0x08, 0xed, 0xb5, 0x14, 0xeb, 0x82, 0x7b, 0x8b, 0x4b, 0x7a, 0x97, + 0xfe, 0xa9, 0x37, 0xf9, 0x10, 0xdf, 0x2d, 0x90, 0x9e, 0x65, 0x83, 0xcf, 0xb5, 0x4f, 0x0e, 0x3f, + 0x81, 0x26, 0x79, 0x4d, 0xef, 0x51, 0xfb, 0x60, 0xfb, 0x1e, 0x8d, 0x57, 0x0c, 0x86, 0x1f, 0x83, + 0x77, 0x7e, 0x27, 0xec, 0xf2, 0xff, 0x99, 0xf4, 0x13, 0xea, 0xda, 0x0a, 0x2f, 0xe1, 0x68, 0x07, + 0xcf, 0x11, 0xa5, 0x1e, 0xa8, 0x5b, 0xe1, 0x2e, 0x0b, 0x3a, 0xfa, 0xed, 0x42, 0xf3, 0x92, 0x06, + 0x7b, 0xf5, 0xd4, 0x59, 0x6f, 0x93, 0xb5, 0x7e, 0xa0, 0xc1, 0xfb, 0x0a, 0x04, 0x9d, 0xe0, 0x0e, + 0xfb, 0x0e, 0x9e, 0x71, 0x3e, 0x7b, 0xbb, 0x89, 0x5e, 0x3d, 0x9c, 0xe0, 0xdd, 0xd6, 0xfc, 0xaa, + 0x96, 0x39, 0xd5, 0x32, 0xad, 0xd5, 0x4b, 0x2f, 0xd3, 0x5a, 0xbb, 0x71, 0xbe, 0xc3, 0x2e, 0xa0, + 0x61, 0x8f, 0x82, 0x95, 0x80, 0xd7, 0xce, 0x2d, 0xe8, 0x6d, 0x07, 0x14, 0x72, 0xd7, 0xd0, 0xca, + 0xcf, 0x81, 0x95, 0xcc, 0xe5, 0xd9, 0xf5, 0x04, 0xbc, 0x0a, 0x92, 0x8b, 0xde, 0x34, 0xcc, 0x9f, + 0xf4, 0xf1, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa7, 0x5b, 0x0a, 0x25, 0x2c, 0x06, 0x00, 0x00, } diff --git a/network/proto/network.pb.micro.go b/network/service/proto/network.pb.micro.go similarity index 99% rename from network/proto/network.pb.micro.go rename to network/service/proto/network.pb.micro.go index 28e473cb..488d0c97 100644 --- a/network/proto/network.pb.micro.go +++ b/network/service/proto/network.pb.micro.go @@ -6,7 +6,7 @@ package go_micro_network import ( fmt "fmt" proto "github.com/golang/protobuf/proto" - _ "github.com/micro/go-micro/router/proto" + _ "github.com/micro/go-micro/router/service/proto" math "math" ) diff --git a/network/proto/network.proto b/network/service/proto/network.proto similarity index 96% rename from network/proto/network.proto rename to network/service/proto/network.proto index d58ed5b8..b4dece64 100644 --- a/network/proto/network.proto +++ b/network/service/proto/network.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package go.micro.network; -import "github.com/micro/go-micro/router/proto/router.proto"; +import "github.com/micro/go-micro/router/service/proto/router.proto"; // Network service is usesd to gain visibility into networks service Network { diff --git a/registry/service/handler/handler.go b/registry/service/handler/handler.go deleted file mode 100644 index e2042e5e..00000000 --- a/registry/service/handler/handler.go +++ /dev/null @@ -1,82 +0,0 @@ -package handler - -import ( - "context" - "time" - - "github.com/micro/go-micro/errors" - "github.com/micro/go-micro/registry" - "github.com/micro/go-micro/registry/service" - pb "github.com/micro/go-micro/registry/service/proto" -) - -type Registry struct { - // internal registry - Registry registry.Registry -} - -func (r *Registry) GetService(ctx context.Context, req *pb.GetRequest, rsp *pb.GetResponse) error { - services, err := r.Registry.GetService(req.Service) - if err != nil { - return errors.InternalServerError("go.micro.registry", err.Error()) - } - for _, srv := range services { - rsp.Services = append(rsp.Services, service.ToProto(srv)) - } - return nil -} - -func (r *Registry) Register(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error { - var regOpts []registry.RegisterOption - if req.Options != nil { - ttl := time.Duration(req.Options.Ttl) * time.Second - regOpts = append(regOpts, registry.RegisterTTL(ttl)) - } - - err := r.Registry.Register(service.ToService(req), regOpts...) - if err != nil { - return errors.InternalServerError("go.micro.registry", err.Error()) - } - - return nil -} - -func (r *Registry) Deregister(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error { - err := r.Registry.Deregister(service.ToService(req)) - if err != nil { - return errors.InternalServerError("go.micro.registry", err.Error()) - } - return nil -} - -func (r *Registry) ListServices(ctx context.Context, req *pb.ListRequest, rsp *pb.ListResponse) error { - services, err := r.Registry.ListServices() - if err != nil { - return errors.InternalServerError("go.micro.registry", err.Error()) - } - for _, srv := range services { - rsp.Services = append(rsp.Services, service.ToProto(srv)) - } - return nil -} - -func (r *Registry) Watch(ctx context.Context, req *pb.WatchRequest, rsp pb.Registry_WatchStream) error { - watcher, err := r.Registry.Watch(registry.WatchService(req.Service)) - if err != nil { - return errors.InternalServerError("go.micro.registry", err.Error()) - } - - for { - next, err := watcher.Next() - if err != nil { - return errors.InternalServerError("go.micro.registry", err.Error()) - } - err = rsp.Send(&pb.Result{ - Action: next.Action, - Service: service.ToProto(next.Service), - }) - if err != nil { - return errors.InternalServerError("go.micro.registry", err.Error()) - } - } -} diff --git a/router/handler/router.go b/router/handler/router.go deleted file mode 100644 index 971e2336..00000000 --- a/router/handler/router.go +++ /dev/null @@ -1,190 +0,0 @@ -package handler - -import ( - "context" - "io" - "time" - - "github.com/micro/go-micro/errors" - "github.com/micro/go-micro/router" - pb "github.com/micro/go-micro/router/proto" -) - -// Router implements router handler -type Router struct { - Router router.Router -} - -// Lookup looks up routes in the routing table and returns them -func (r *Router) Lookup(ctx context.Context, req *pb.LookupRequest, resp *pb.LookupResponse) error { - routes, err := r.Router.Lookup(router.QueryService(req.Query.Service)) - if err != nil { - return errors.InternalServerError("go.micro.router", "failed to lookup routes: %v", err) - } - - respRoutes := make([]*pb.Route, 0, len(routes)) - for _, route := range routes { - respRoute := &pb.Route{ - Service: route.Service, - Address: route.Address, - Gateway: route.Gateway, - Network: route.Network, - Router: route.Router, - Link: route.Link, - Metric: route.Metric, - } - respRoutes = append(respRoutes, respRoute) - } - - resp.Routes = respRoutes - - return nil -} - -// Solicit triggers full routing table advertisement -func (r *Router) Solicit(ctx context.Context, req *pb.Request, resp *pb.Response) error { - if err := r.Router.Solicit(); err != nil { - return err - } - - return nil -} - -// Advertise streams router advertisements -func (r *Router) Advertise(ctx context.Context, req *pb.Request, stream pb.Router_AdvertiseStream) error { - advertChan, err := r.Router.Advertise() - if err != nil { - return errors.InternalServerError("go.micro.router", "failed to get adverts: %v", err) - } - - for advert := range advertChan { - var events []*pb.Event - for _, event := range advert.Events { - route := &pb.Route{ - Service: event.Route.Service, - Address: event.Route.Address, - Gateway: event.Route.Gateway, - Network: event.Route.Network, - Router: event.Route.Router, - Link: event.Route.Link, - Metric: event.Route.Metric, - } - e := &pb.Event{ - Type: pb.EventType(event.Type), - Timestamp: event.Timestamp.UnixNano(), - Route: route, - } - events = append(events, e) - } - - advert := &pb.Advert{ - Id: advert.Id, - Type: pb.AdvertType(advert.Type), - Timestamp: advert.Timestamp.UnixNano(), - Events: events, - } - - // send the advert - err := stream.Send(advert) - if err == io.EOF { - return nil - } - if err != nil { - return errors.InternalServerError("go.micro.router", "error sending message %v", err) - } - } - - return nil -} - -// Process processes advertisements -func (r *Router) Process(ctx context.Context, req *pb.Advert, rsp *pb.ProcessResponse) error { - events := make([]*router.Event, len(req.Events)) - for i, event := range req.Events { - route := router.Route{ - Service: event.Route.Service, - Address: event.Route.Address, - Gateway: event.Route.Gateway, - Network: event.Route.Network, - Router: event.Route.Router, - Link: event.Route.Link, - Metric: event.Route.Metric, - } - - events[i] = &router.Event{ - Type: router.EventType(event.Type), - Timestamp: time.Unix(0, event.Timestamp), - Route: route, - } - } - - advert := &router.Advert{ - Id: req.Id, - Type: router.AdvertType(req.Type), - Timestamp: time.Unix(0, req.Timestamp), - TTL: time.Duration(req.Ttl), - Events: events, - } - - if err := r.Router.Process(advert); err != nil { - return errors.InternalServerError("go.micro.router", "error publishing advert: %v", err) - } - - return nil -} - -// Status returns router status -func (r *Router) Status(ctx context.Context, req *pb.Request, rsp *pb.StatusResponse) error { - status := r.Router.Status() - - rsp.Status = &pb.Status{ - Code: status.Code.String(), - } - - if status.Error != nil { - rsp.Status.Error = status.Error.Error() - } - - return nil -} - -// Watch streans routing table events -func (r *Router) Watch(ctx context.Context, req *pb.WatchRequest, stream pb.Router_WatchStream) error { - watcher, err := r.Router.Watch() - if err != nil { - return errors.InternalServerError("go.micro.router", "failed creating event watcher: %v", err) - } - - defer stream.Close() - - for { - event, err := watcher.Next() - if err == router.ErrWatcherStopped { - return errors.InternalServerError("go.micro.router", "watcher stopped") - } - - if err != nil { - return errors.InternalServerError("go.micro.router", "error watching events: %v", err) - } - - route := &pb.Route{ - Service: event.Route.Service, - Address: event.Route.Address, - Gateway: event.Route.Gateway, - Network: event.Route.Network, - Router: event.Route.Router, - Link: event.Route.Link, - Metric: event.Route.Metric, - } - - tableEvent := &pb.Event{ - Type: pb.EventType(event.Type), - Timestamp: event.Timestamp.UnixNano(), - Route: route, - } - - if err := stream.Send(tableEvent); err != nil { - return err - } - } -} diff --git a/router/handler/table.go b/router/handler/table.go deleted file mode 100644 index 42a824fe..00000000 --- a/router/handler/table.go +++ /dev/null @@ -1,115 +0,0 @@ -package handler - -import ( - "context" - - "github.com/micro/go-micro/errors" - "github.com/micro/go-micro/router" - pb "github.com/micro/go-micro/router/proto" -) - -type Table struct { - Router router.Router -} - -func (t *Table) Create(ctx context.Context, route *pb.Route, resp *pb.CreateResponse) error { - err := t.Router.Table().Create(router.Route{ - Service: route.Service, - Address: route.Address, - Gateway: route.Gateway, - Network: route.Network, - Router: route.Router, - Link: route.Link, - Metric: route.Metric, - }) - if err != nil { - return errors.InternalServerError("go.micro.router", "failed to create route: %s", err) - } - - return nil -} - -func (t *Table) Update(ctx context.Context, route *pb.Route, resp *pb.UpdateResponse) error { - err := t.Router.Table().Update(router.Route{ - Service: route.Service, - Address: route.Address, - Gateway: route.Gateway, - Network: route.Network, - Router: route.Router, - Link: route.Link, - Metric: route.Metric, - }) - if err != nil { - return errors.InternalServerError("go.micro.router", "failed to update route: %s", err) - } - - return nil -} - -func (t *Table) Delete(ctx context.Context, route *pb.Route, resp *pb.DeleteResponse) error { - err := t.Router.Table().Delete(router.Route{ - Service: route.Service, - Address: route.Address, - Gateway: route.Gateway, - Network: route.Network, - Router: route.Router, - Link: route.Link, - Metric: route.Metric, - }) - if err != nil { - return errors.InternalServerError("go.micro.router", "failed to delete route: %s", err) - } - - return nil -} - -// List returns all routes in the routing table -func (t *Table) List(ctx context.Context, req *pb.Request, resp *pb.ListResponse) error { - routes, err := t.Router.Table().List() - if err != nil { - return errors.InternalServerError("go.micro.router", "failed to list routes: %s", err) - } - - respRoutes := make([]*pb.Route, 0, len(routes)) - for _, route := range routes { - respRoute := &pb.Route{ - Service: route.Service, - Address: route.Address, - Gateway: route.Gateway, - Network: route.Network, - Router: route.Router, - Link: route.Link, - Metric: route.Metric, - } - respRoutes = append(respRoutes, respRoute) - } - - resp.Routes = respRoutes - - return nil -} - -func (t *Table) Query(ctx context.Context, req *pb.QueryRequest, resp *pb.QueryResponse) error { - routes, err := t.Router.Table().Query(router.QueryService(req.Query.Service)) - if err != nil { - return errors.InternalServerError("go.micro.router", "failed to lookup routes: %s", err) - } - - respRoutes := make([]*pb.Route, 0, len(routes)) - for _, route := range routes { - respRoute := &pb.Route{ - Service: route.Service, - Address: route.Address, - Gateway: route.Gateway, - Network: route.Network, - Router: route.Router, - Link: route.Link, - Metric: route.Metric, - } - respRoutes = append(respRoutes, respRoute) - } - - resp.Routes = respRoutes - - return nil -} diff --git a/router/proto/router.pb.go b/router/service/proto/router.pb.go similarity index 100% rename from router/proto/router.pb.go rename to router/service/proto/router.pb.go diff --git a/router/proto/router.pb.micro.go b/router/service/proto/router.pb.micro.go similarity index 100% rename from router/proto/router.pb.micro.go rename to router/service/proto/router.pb.micro.go diff --git a/router/proto/router.proto b/router/service/proto/router.proto similarity index 100% rename from router/proto/router.proto rename to router/service/proto/router.proto diff --git a/router/service/service.go b/router/service/service.go index 15a0ae37..1087da3d 100644 --- a/router/service/service.go +++ b/router/service/service.go @@ -10,7 +10,7 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/router" - pb "github.com/micro/go-micro/router/proto" + pb "github.com/micro/go-micro/router/service/proto" ) type svc struct { diff --git a/router/service/table.go b/router/service/table.go index 77e288db..bcfc8ef3 100644 --- a/router/service/table.go +++ b/router/service/table.go @@ -5,7 +5,7 @@ import ( "github.com/micro/go-micro/client" "github.com/micro/go-micro/router" - pb "github.com/micro/go-micro/router/proto" + pb "github.com/micro/go-micro/router/service/proto" ) type table struct { diff --git a/router/service/watcher.go b/router/service/watcher.go index 616dc2d4..663d0fce 100644 --- a/router/service/watcher.go +++ b/router/service/watcher.go @@ -6,7 +6,7 @@ import ( "time" "github.com/micro/go-micro/router" - pb "github.com/micro/go-micro/router/proto" + pb "github.com/micro/go-micro/router/service/proto" ) type watcher struct { diff --git a/runtime/service/handler/handler.go b/runtime/service/handler/handler.go deleted file mode 100644 index b545eab4..00000000 --- a/runtime/service/handler/handler.go +++ /dev/null @@ -1,142 +0,0 @@ -package handler - -import ( - "context" - - "github.com/micro/go-micro/errors" - "github.com/micro/go-micro/runtime" - pb "github.com/micro/go-micro/runtime/service/proto" -) - -type Runtime struct { - Runtime runtime.Runtime -} - -func toProto(s *runtime.Service) *pb.Service { - return &pb.Service{ - Name: s.Name, - Version: s.Version, - Source: s.Source, - Metadata: s.Metadata, - } -} - -func toService(s *pb.Service) *runtime.Service { - return &runtime.Service{ - Name: s.Name, - Version: s.Version, - Source: s.Source, - Metadata: s.Metadata, - } -} - -func toCreateOptions(opts *pb.CreateOptions) []runtime.CreateOption { - options := []runtime.CreateOption{} - // command options - if len(opts.Command) > 0 { - options = append(options, runtime.WithCommand(opts.Command...)) - } - // env options - if len(opts.Env) > 0 { - options = append(options, runtime.WithEnv(opts.Env)) - } - - // TODO: output options - - return options -} - -func toReadOptions(opts *pb.ReadOptions) []runtime.ReadOption { - options := []runtime.ReadOption{} - if len(opts.Service) > 0 { - options = append(options, runtime.ReadService(opts.Service)) - } - if len(opts.Version) > 0 { - options = append(options, runtime.ReadVersion(opts.Version)) - } - if len(opts.Type) > 0 { - options = append(options, runtime.ReadType(opts.Type)) - } - - return options -} - -func (r *Runtime) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error { - if req.Service == nil { - return errors.BadRequest("go.micro.runtime", "blank service") - } - - var options []runtime.CreateOption - if req.Options != nil { - options = toCreateOptions(req.Options) - } - - service := toService(req.Service) - err := r.Runtime.Create(service, options...) - if err != nil { - return errors.InternalServerError("go.micro.runtime", err.Error()) - } - - return nil -} - -func (r *Runtime) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error { - var options []runtime.ReadOption - if req.Options != nil { - options = toReadOptions(req.Options) - } - - services, err := r.Runtime.Read(options...) - if err != nil { - return errors.InternalServerError("go.micro.runtime", err.Error()) - } - - for _, service := range services { - rsp.Services = append(rsp.Services, toProto(service)) - } - - return nil -} - -func (r *Runtime) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error { - if req.Service == nil { - return errors.BadRequest("go.micro.runtime", "blank service") - } - - // TODO: add opts - service := toService(req.Service) - err := r.Runtime.Update(service) - if err != nil { - return errors.InternalServerError("go.micro.runtime", err.Error()) - } - - return nil -} - -func (r *Runtime) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.DeleteResponse) error { - if req.Service == nil { - return errors.BadRequest("go.micro.runtime", "blank service") - } - - // TODO: add opts - service := toService(req.Service) - err := r.Runtime.Delete(service) - if err != nil { - return errors.InternalServerError("go.micro.runtime", err.Error()) - } - - return nil -} - -func (r *Runtime) List(ctx context.Context, req *pb.ListRequest, rsp *pb.ListResponse) error { - services, err := r.Runtime.List() - if err != nil { - return errors.InternalServerError("go.micro.runtime", err.Error()) - } - - for _, service := range services { - rsp.Services = append(rsp.Services, toProto(service)) - } - - return nil -} diff --git a/store/service/handler/handler.go b/store/service/handler/handler.go deleted file mode 100644 index 3f546a9d..00000000 --- a/store/service/handler/handler.go +++ /dev/null @@ -1,89 +0,0 @@ -package handler - -import ( - "context" - "io" - "time" - - "github.com/micro/go-micro/errors" - "github.com/micro/go-micro/store" - pb "github.com/micro/go-micro/store/service/proto" -) - -type Store struct { - Store store.Store -} - -func (s *Store) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error { - vals, err := s.Store.Read(req.Keys...) - if err != nil { - return errors.InternalServerError("go.micro.store", err.Error()) - } - for _, val := range vals { - rsp.Records = append(rsp.Records, &pb.Record{ - Key: val.Key, - Value: val.Value, - Expiry: int64(val.Expiry.Seconds()), - }) - } - return nil -} - -func (s *Store) Write(ctx context.Context, req *pb.WriteRequest, rsp *pb.WriteResponse) error { - records := make([]*store.Record, 0, len(req.Records)) - - for _, record := range req.Records { - records = append(records, &store.Record{ - Key: record.Key, - Value: record.Value, - Expiry: time.Duration(record.Expiry) * time.Second, - }) - } - - err := s.Store.Write(records...) - if err != nil { - return errors.InternalServerError("go.micro.store", err.Error()) - } - return nil -} - -func (s *Store) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.DeleteResponse) error { - err := s.Store.Delete(req.Keys...) - if err != nil { - return errors.InternalServerError("go.micro.store", err.Error()) - } - return nil -} - -func (s *Store) List(ctx context.Context, req *pb.ListRequest, stream pb.Store_ListStream) error { - var vals []*store.Record - var err error - - if len(req.Key) > 0 { - vals, err = s.Store.Read(req.Key) - } else { - vals, err = s.Store.List() - } - if err != nil { - return errors.InternalServerError("go.micro.store", err.Error()) - } - rsp := new(pb.ListResponse) - - // TODO: batch sync - for _, val := range vals { - rsp.Records = append(rsp.Records, &pb.Record{ - Key: val.Key, - Value: val.Value, - Expiry: int64(val.Expiry.Seconds()), - }) - } - - err = stream.Send(rsp) - if err == io.EOF { - return nil - } - if err != nil { - return errors.InternalServerError("go.micro.store", err.Error()) - } - return nil -} From 8da77a3ddc8e28c61a06dcf9e78688005d2b7063 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 10 Dec 2019 14:05:05 +0000 Subject: [PATCH 340/344] use fixed port names for runtime k8s --- runtime/kubernetes/client/kubernetes.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/kubernetes/client/kubernetes.go b/runtime/kubernetes/client/kubernetes.go index 9a683b27..a9d3a653 100644 --- a/runtime/kubernetes/client/kubernetes.go +++ b/runtime/kubernetes/client/kubernetes.go @@ -53,7 +53,7 @@ func NewService(name, version, typ string) *Service { Type: "ClusterIP", Selector: Labels, Ports: []ServicePort{{ - name + "-port", 9090, "", + "service-port", 9090, "", }}, } @@ -107,7 +107,7 @@ func NewDeployment(name, version, typ string) *Deployment { Env: []EnvVar{env}, Command: []string{"go", "run", "main.go"}, Ports: []ContainerPort{{ - Name: name + "-port", + Name: "service-port", ContainerPort: 8080, }}, }}, From e966944ae54094b13509b517b18d0b313f1f141c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 10 Dec 2019 17:57:04 +0000 Subject: [PATCH 341/344] sort resolved node list in network by lowest priority --- network/default.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/network/default.go b/network/default.go index 914653ec..dfc73bd2 100644 --- a/network/default.go +++ b/network/default.go @@ -6,6 +6,7 @@ import ( "hash/fnv" "io" "math" + "sort" "sync" "time" @@ -363,6 +364,11 @@ func (n *network) resolveNodes() ([]string, error) { log.Debugf("Network failed to resolve nodes: %v", err) } + // sort by lowest priority + if err == nil { + sort.Slice(records, func(i, j int) bool { return records[i].Priority < records[j].Priority }) + } + // keep processing nodeMap := make(map[string]bool) From ff69d46c98bb3411bd2141e5e2963c759a7f5ba6 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 10 Dec 2019 18:12:29 +0000 Subject: [PATCH 342/344] strip some cruft from config/cmd --- config/cmd/cmd.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/config/cmd/cmd.go b/config/cmd/cmd.go index 18f12528..f436ab18 100644 --- a/config/cmd/cmd.go +++ b/config/cmd/cmd.go @@ -194,11 +194,10 @@ var ( } DefaultBrokers = map[string]func(...broker.Option) broker.Broker{ - "go.micro.broker": brokerSrv.NewBroker, - "service": brokerSrv.NewBroker, - "http": http.NewBroker, - "memory": memory.NewBroker, - "nats": nats.NewBroker, + "service": brokerSrv.NewBroker, + "http": http.NewBroker, + "memory": memory.NewBroker, + "nats": nats.NewBroker, } DefaultClients = map[string]func(...client.Option) client.Client{ @@ -208,11 +207,10 @@ var ( } DefaultRegistries = map[string]func(...registry.Option) registry.Registry{ - "go.micro.registry": regSrv.NewRegistry, - "service": regSrv.NewRegistry, - "etcd": etcd.NewRegistry, - "mdns": mdns.NewRegistry, - "memory": rmem.NewRegistry, + "service": regSrv.NewRegistry, + "etcd": etcd.NewRegistry, + "mdns": mdns.NewRegistry, + "memory": rmem.NewRegistry, } DefaultSelectors = map[string]func(...selector.Option) selector.Selector{ From 27bab29e3c06636a0e7121f1adb3bfe750fc423d Mon Sep 17 00:00:00 2001 From: Lars Lehtonen Date: Wed, 11 Dec 2019 08:24:26 -0800 Subject: [PATCH 343/344] service/grpc: t.Fatal out of TestGRPCService() goroutine --- service/grpc/grpc_test.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/service/grpc/grpc_test.go b/service/grpc/grpc_test.go index bf7c0a95..2158d08a 100644 --- a/service/grpc/grpc_test.go +++ b/service/grpc/grpc_test.go @@ -5,6 +5,7 @@ import ( "crypto/tls" "sync" "testing" + "time" "github.com/micro/go-micro" "github.com/micro/go-micro/registry/memory" @@ -44,10 +45,10 @@ func TestGRPCService(t *testing.T) { hello.RegisterTestHandler(service.Server(), &testHandler{}) // run service + errCh := make(chan error, 1) go func() { - if err := service.Run(); err != nil { - t.Fatal(err) - } + defer close(errCh) + errCh <- service.Run() }() // wait for start @@ -57,13 +58,23 @@ func TestGRPCService(t *testing.T) { test := hello.NewTestService("test.service", service.Client()) // call service - rsp, err := test.Call(context.Background(), &hello.Request{ + ctx2, cancel2 := context.WithTimeout(context.Background(), time.Duration(time.Second)) + defer cancel2() + rsp, err := test.Call(ctx2, &hello.Request{ Name: "John", }) if err != nil { t.Fatal(err) } + // check server + select { + case err := <-errCh: + t.Fatal(err) + case <-time.After(time.Second): + break + } + // check message if rsp.Msg != "Hello John" { t.Fatalf("unexpected response %s", rsp.Msg) From fd531349d7edb98f02573908f5aeb4a8847aca51 Mon Sep 17 00:00:00 2001 From: Lars Lehtonen Date: Wed, 11 Dec 2019 08:28:49 -0800 Subject: [PATCH 344/344] service/grpc: t.Fatal out of TestGRPCTLSService() goroutine --- service/grpc/grpc_test.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/service/grpc/grpc_test.go b/service/grpc/grpc_test.go index 2158d08a..5978c4fb 100644 --- a/service/grpc/grpc_test.go +++ b/service/grpc/grpc_test.go @@ -162,10 +162,10 @@ func TestGRPCTLSService(t *testing.T) { hello.RegisterTestHandler(service.Server(), &testHandler{}) // run service + errCh := make(chan error, 1) go func() { - if err := service.Run(); err != nil { - t.Fatal(err) - } + defer close(errCh) + errCh <- service.Run() }() // wait for start @@ -175,13 +175,23 @@ func TestGRPCTLSService(t *testing.T) { test := hello.NewTestService("test.service", service.Client()) // call service - rsp, err := test.Call(context.Background(), &hello.Request{ + ctx2, cancel2 := context.WithTimeout(context.Background(), time.Duration(time.Second)) + defer cancel2() + rsp, err := test.Call(ctx2, &hello.Request{ Name: "John", }) if err != nil { t.Fatal(err) } + // check server + select { + case err := <-errCh: + t.Fatal(err) + case <-time.After(time.Second): + break + } + // check message if rsp.Msg != "Hello John" { t.Fatalf("unexpected response %s", rsp.Msg)