fix etcd keys for services (#1922)

This commit is contained in:
Asim Aslam
2020-08-10 21:58:35 +01:00
committed by GitHub
parent 4db8ea8f6a
commit 61d12d3a39
4 changed files with 98 additions and 47 deletions

View File

@@ -143,9 +143,10 @@ func configure(e *etcdRegistry, opts ...registry.Option) error {
return nil
}
// hasName checks if the key has the name we expect
// getName returns the domain and name
// it returns false if there's an issue
// the key is a path of /prefix/domain/name/id e.g /micro/registry/domain/service/uuid
func hasName(key, prefix, name string) bool {
func getName(key, prefix string) (string, string, bool) {
// strip the prefix from keys
key = strings.TrimPrefix(key, prefix)
@@ -153,7 +154,7 @@ func hasName(key, prefix, name string) bool {
parts := strings.Split(key, "/")
if len(parts) == 0 {
return false
return "", "", false
}
if len(parts[0]) == 0 {
@@ -162,11 +163,11 @@ func hasName(key, prefix, name string) bool {
// we expect a domain and then name domain/service
if len(parts) < 2 {
return false
return "", "", false
}
// ensure the name matches what we expect
return parts[1] == name
// return name, domain
return parts[0], parts[1], true
}
func encode(s *registry.Service) string {
@@ -220,12 +221,16 @@ func (e *etcdRegistry) registerNode(s *registry.Service, node *registry.Node, op
options.Domain = defaultDomain
}
// set the domain in metadata so it can be retrieved by wildcard queries
if s.Metadata == nil {
s.Metadata = map[string]string{"domain": options.Domain}
} else {
s.Metadata["domain"] = options.Domain
s.Metadata = map[string]string{}
}
if node.Metadata == nil {
node.Metadata = map[string]string{}
}
// set the domain in metadata so it can be retrieved by wildcard queries
s.Metadata["domain"] = options.Domain
node.Metadata["domain"] = options.Domain
e.Lock()
// ensure the leases and registers are setup for this domain
@@ -465,7 +470,8 @@ func (e *etcdRegistry) GetService(name string, opts ...registry.GetOption) ([]*r
// filter the results for the key we care about
for _, kv := range rsp.Kvs {
// if the key does not contain the name then pass
if !hasName(string(kv.Key), prefix, name) {
_, service, ok := getName(string(kv.Key), prefix)
if !ok || service != name {
continue
}
@@ -489,12 +495,16 @@ func (e *etcdRegistry) GetService(name string, opts ...registry.GetOption) ([]*r
for _, n := range results {
// only process the things we care about
if !hasName(string(n.Key), prefix, name) {
domain, service, ok := getName(string(n.Key), prefix)
if !ok || service != name {
continue
}
if sn := decode(n.Value); sn != nil {
s, ok := versions[sn.Version]
// compose a key of name/version/domain
key := sn.Name + sn.Version + domain
s, ok := versions[key]
if !ok {
s = &registry.Service{
Name: sn.Name,
@@ -502,7 +512,7 @@ func (e *etcdRegistry) GetService(name string, opts ...registry.GetOption) ([]*r
Metadata: sn.Metadata,
Endpoints: sn.Endpoints,
}
versions[s.Version] = s
versions[key] = s
}
s.Nodes = append(s.Nodes, sn.Nodes...)
}
@@ -514,8 +524,6 @@ func (e *etcdRegistry) GetService(name string, opts ...registry.GetOption) ([]*r
services = append(services, service)
}
logger.Tracef("[etcd] registry get service %s returned %v", name, services)
return services, nil
}
@@ -550,15 +558,22 @@ func (e *etcdRegistry) ListServices(opts ...registry.ListOption) ([]*registry.Se
versions := make(map[string]*registry.Service)
for _, n := range rsp.Kvs {
sn := decode(n.Value)
if sn == nil {
domain, service, ok := getName(string(n.Key), prefix)
if !ok {
continue
}
v, ok := versions[sn.Name+sn.Version]
sn := decode(n.Value)
if sn == nil || sn.Name != service {
continue
}
// key based on name/version/domain
key := sn.Name + sn.Version + domain
v, ok := versions[key]
if !ok {
versions[sn.Name+sn.Version] = sn
versions[key] = sn
continue
}

View File

@@ -10,44 +10,59 @@ func TestEtcdHasName(t *testing.T) {
key string
prefix string
name string
domain string
expect bool
}{
{
"/micro/registry/micro/registry",
"/micro/registry",
"registry",
"micro",
true,
},
{
"/micro/registry/micro/store",
"/micro/registry/micro",
"/micro/registry",
"registry",
"store",
"micro",
false,
},
{
"/prefix/baz/*/registry",
"/prefix/baz",
"registry",
"*",
true,
},
{
"/prefix/baz/micro/registry",
"/prefix/baz",
"/prefix/baz",
"store",
"micro",
false,
},
{
"/prefix/baz/micro/registry",
"/prefix/baz/foobar/registry",
"/prefix/baz",
"registry",
"foobar",
true,
},
}
for _, c := range testCases {
v := hasName(c.key, c.prefix, c.name)
if v != c.expect {
t.Fatalf("Expected %t for %v got: %t", c.expect, c, v)
domain, service, ok := getName(c.key, c.prefix)
if ok != c.expect {
t.Fatalf("Expected %t for %v got: %t", c.expect, c, ok)
}
if !ok {
continue
}
if service != c.name {
t.Fatalf("Expected service %s got %s", c.name, service)
}
if domain != c.domain {
t.Fatalf("Expected domain %s got %s", c.domain, domain)
}
}
}