mirror of
https://github.com/status-im/consul.git
synced 2025-01-22 03:29:43 +00:00
Add support for reverse lookup of services
This commit is contained in:
parent
ad27d72d6a
commit
5c04864b28
@ -240,7 +240,7 @@ func (c *Catalog) ServiceNodes(args *structs.ServiceSpecificRequest, reply *stru
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify the arguments
|
// Verify the arguments
|
||||||
if args.ServiceName == "" {
|
if args.ServiceName == "" && args.ServiceAddress == "" {
|
||||||
return fmt.Errorf("Must provide service name")
|
return fmt.Errorf("Must provide service name")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,6 +256,9 @@ func (c *Catalog) ServiceNodes(args *structs.ServiceSpecificRequest, reply *stru
|
|||||||
} else {
|
} else {
|
||||||
index, services, err = state.ServiceNodes(ws, args.ServiceName)
|
index, services, err = state.ServiceNodes(ws, args.ServiceName)
|
||||||
}
|
}
|
||||||
|
if args.ServiceAddress != "" {
|
||||||
|
index, services, err = state.ServiceAddressNodes(ws, args.ServiceAddress)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -855,6 +855,36 @@ func serviceTagFilter(sn *structs.ServiceNode, tag string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServiceAddressNodes returns the nodes associated with a given service, filtering
|
||||||
|
// out services that don't match the given serviceAddress
|
||||||
|
func (s *Store) ServiceAddressNodes(ws memdb.WatchSet, address string) (uint64, structs.ServiceNodes, error) {
|
||||||
|
tx := s.db.Txn(false)
|
||||||
|
defer tx.Abort()
|
||||||
|
|
||||||
|
// List all the services.
|
||||||
|
services, err := tx.Get("services", "id")
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, fmt.Errorf("failed service lookup: %s", err)
|
||||||
|
}
|
||||||
|
ws.Add(services.WatchCh())
|
||||||
|
|
||||||
|
// Gather all the services and apply the tag filter.
|
||||||
|
var results structs.ServiceNodes
|
||||||
|
for service := services.Next(); service != nil; service = services.Next() {
|
||||||
|
svc := service.(*structs.ServiceNode)
|
||||||
|
if svc.ServiceAddress == address {
|
||||||
|
results = append(results, svc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in the node details.
|
||||||
|
results, err = s.parseServiceNodes(tx, ws, results)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, fmt.Errorf("failed parsing service nodes: %s", err)
|
||||||
|
}
|
||||||
|
return 0, results, nil
|
||||||
|
}
|
||||||
|
|
||||||
// parseServiceNodes iterates over a services query and fills in the node details,
|
// parseServiceNodes iterates over a services query and fills in the node details,
|
||||||
// returning a ServiceNodes slice.
|
// returning a ServiceNodes slice.
|
||||||
func (s *Store) parseServiceNodes(tx *memdb.Txn, ws memdb.WatchSet, services structs.ServiceNodes) (structs.ServiceNodes, error) {
|
func (s *Store) parseServiceNodes(tx *memdb.Txn, ws memdb.WatchSet, services structs.ServiceNodes) (structs.ServiceNodes, error) {
|
||||||
|
26
agent/dns.go
26
agent/dns.go
@ -12,6 +12,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/armon/go-metrics"
|
"github.com/armon/go-metrics"
|
||||||
|
"github.com/coredns/coredns/plugin/pkg/dnsutil"
|
||||||
"github.com/hashicorp/consul/agent/config"
|
"github.com/hashicorp/consul/agent/config"
|
||||||
"github.com/hashicorp/consul/agent/consul"
|
"github.com/hashicorp/consul/agent/consul"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
@ -207,6 +208,31 @@ func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lookup the service address
|
||||||
|
serviceAddress := dnsutil.ExtractAddressFromReverse(qName)
|
||||||
|
sargs := structs.ServiceSpecificRequest{
|
||||||
|
Datacenter: datacenter,
|
||||||
|
QueryOptions: structs.QueryOptions{
|
||||||
|
Token: d.agent.tokens.UserToken(),
|
||||||
|
AllowStale: d.config.AllowStale,
|
||||||
|
},
|
||||||
|
ServiceAddress: serviceAddress,
|
||||||
|
}
|
||||||
|
|
||||||
|
var sout structs.IndexedServiceNodes
|
||||||
|
if err := d.agent.RPC("Catalog.ServiceNodes", &sargs, &sout); err == nil {
|
||||||
|
for _, n := range sout.ServiceNodes {
|
||||||
|
if n.ServiceAddress == serviceAddress {
|
||||||
|
ptr := &dns.PTR{
|
||||||
|
Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: 0},
|
||||||
|
Ptr: fmt.Sprintf("%s.service.%s", n.ServiceName, d.domain),
|
||||||
|
}
|
||||||
|
m.Answer = append(m.Answer, ptr)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// nothing found locally, recurse
|
// nothing found locally, recurse
|
||||||
if len(m.Answer) == 0 {
|
if len(m.Answer) == 0 {
|
||||||
d.handleRecurse(resp, req)
|
d.handleRecurse(resp, req)
|
||||||
|
@ -279,6 +279,7 @@ type ServiceSpecificRequest struct {
|
|||||||
NodeMetaFilters map[string]string
|
NodeMetaFilters map[string]string
|
||||||
ServiceName string
|
ServiceName string
|
||||||
ServiceTag string
|
ServiceTag string
|
||||||
|
ServiceAddress string
|
||||||
TagFilter bool // Controls tag filtering
|
TagFilter bool // Controls tag filtering
|
||||||
Source QuerySource
|
Source QuerySource
|
||||||
QueryOptions
|
QueryOptions
|
||||||
|
Loading…
x
Reference in New Issue
Block a user