Return Node.Meta info using the DNS interface

This commit is contained in:
Patrick Sodré 2017-08-01 03:01:49 -04:00 committed by Frank Schroeder
parent ab90865865
commit 53e812e759
No known key found for this signature in database
GPG Key ID: 4D65C6EAEC87DECD
1 changed files with 42 additions and 14 deletions

View File

@ -341,7 +341,7 @@ func (d *DNSServer) nameservers(edns bool) (ns []dns.RR, extra []dns.RR) {
} }
ns = append(ns, nsrr) ns = append(ns, nsrr)
glue := d.formatNodeRecord(addr, fqdn, dns.TypeANY, d.config.NodeTTL, edns) glue := d.formatNodeRecord(nil, addr, fqdn, dns.TypeANY, d.config.NodeTTL, edns)
extra = append(extra, glue...) extra = append(extra, glue...)
// don't provide more than 3 servers // don't provide more than 3 servers
@ -485,9 +485,9 @@ INVALID:
// nodeLookup is used to handle a node query // nodeLookup is used to handle a node query
func (d *DNSServer) nodeLookup(network, datacenter, node string, req, resp *dns.Msg) { func (d *DNSServer) nodeLookup(network, datacenter, node string, req, resp *dns.Msg) {
// Only handle ANY, A and AAAA type requests // Only handle ANY, A, AAAA and TXT type requests
qType := req.Question[0].Qtype qType := req.Question[0].Qtype
if qType != dns.TypeANY && qType != dns.TypeA && qType != dns.TypeAAAA { if qType != dns.TypeANY && qType != dns.TypeA && qType != dns.TypeAAAA && qType != dns.TypeTXT {
return return
} }
@ -530,23 +530,36 @@ RPC:
n := out.NodeServices.Node n := out.NodeServices.Node
edns := req.IsEdns0() != nil edns := req.IsEdns0() != nil
addr := d.agent.TranslateAddress(datacenter, n.Address, n.TaggedAddresses) addr := d.agent.TranslateAddress(datacenter, n.Address, n.TaggedAddresses)
records := d.formatNodeRecord(addr, req.Question[0].Name, qType, d.config.NodeTTL, edns) records := d.formatNodeRecord(out.NodeServices.Node, addr, req.Question[0].Name, qType, d.config.NodeTTL, edns)
if records != nil { if records != nil {
resp.Answer = append(resp.Answer, records...) resp.Answer = append(resp.Answer, records...)
} }
} }
// formatNodeRecord takes a Node and returns an A, AAAA, or CNAME record // formatTxtRecords takes a kv-map and returns it as "[k=]v" for non-empty k not starting with rfc1035-
func (d *DNSServer) formatNodeRecord(addr, qName string, qType uint16, ttl time.Duration, edns bool) (records []dns.RR) { func (d *DNSServer) formatTxtRecords(meta map[string]string) (txt []string) {
for k, v := range meta {
if strings.HasPrefix(k, "rfc1035-") {
txt = append(txt, v)
} else {
txt = append(txt, k+"="+v)
}
}
return txt
}
// formatNodeRecord takes a Node and returns an A, AAAA, TXT or CNAME record
func (d *DNSServer) formatNodeRecord(node *structs.Node, addr, qName string, qType uint16, ttl time.Duration, edns bool) (records []dns.RR) {
// Parse the IP // Parse the IP
ip := net.ParseIP(addr) ip := net.ParseIP(addr)
var ipv4 net.IP var ipv4 net.IP
if ip != nil { if ip != nil {
ipv4 = ip.To4() ipv4 = ip.To4()
} }
switch { switch {
case ipv4 != nil && (qType == dns.TypeANY || qType == dns.TypeA): case ipv4 != nil && (qType == dns.TypeANY || qType == dns.TypeA):
return []dns.RR{&dns.A{ records = append(records, &dns.A{
Hdr: dns.RR_Header{ Hdr: dns.RR_Header{
Name: qName, Name: qName,
Rrtype: dns.TypeA, Rrtype: dns.TypeA,
@ -554,10 +567,10 @@ func (d *DNSServer) formatNodeRecord(addr, qName string, qType uint16, ttl time.
Ttl: uint32(ttl / time.Second), Ttl: uint32(ttl / time.Second),
}, },
A: ip, A: ip,
}} })
case ip != nil && ipv4 == nil && (qType == dns.TypeANY || qType == dns.TypeAAAA): case ip != nil && ipv4 == nil && (qType == dns.TypeANY || qType == dns.TypeAAAA):
return []dns.RR{&dns.AAAA{ records = append(records, &dns.AAAA{
Hdr: dns.RR_Header{ Hdr: dns.RR_Header{
Name: qName, Name: qName,
Rrtype: dns.TypeAAAA, Rrtype: dns.TypeAAAA,
@ -565,10 +578,10 @@ func (d *DNSServer) formatNodeRecord(addr, qName string, qType uint16, ttl time.
Ttl: uint32(ttl / time.Second), Ttl: uint32(ttl / time.Second),
}, },
AAAA: ip, AAAA: ip,
}} })
case ip == nil && (qType == dns.TypeANY || qType == dns.TypeCNAME || case ip == nil && (qType == dns.TypeANY || qType == dns.TypeCNAME ||
qType == dns.TypeA || qType == dns.TypeAAAA): qType == dns.TypeA || qType == dns.TypeAAAA || qType == dns.TypeTXT):
// Get the CNAME // Get the CNAME
cnRec := &dns.CNAME{ cnRec := &dns.CNAME{
Hdr: dns.RR_Header{ Hdr: dns.RR_Header{
@ -587,7 +600,7 @@ func (d *DNSServer) formatNodeRecord(addr, qName string, qType uint16, ttl time.
MORE_REC: MORE_REC:
for _, rr := range more { for _, rr := range more {
switch rr.Header().Rrtype { switch rr.Header().Rrtype {
case dns.TypeCNAME, dns.TypeA, dns.TypeAAAA: case dns.TypeCNAME, dns.TypeA, dns.TypeAAAA, dns.TypeTXT:
records = append(records, rr) records = append(records, rr)
extra++ extra++
if extra == maxRecurseRecords && !edns { if extra == maxRecurseRecords && !edns {
@ -596,6 +609,21 @@ func (d *DNSServer) formatNodeRecord(addr, qName string, qType uint16, ttl time.
} }
} }
} }
if node != nil && len(node.Meta) > 0 && (qType == dns.TypeANY || qType == dns.TypeTXT) {
for _, txt := range d.formatTxtRecords(node.Meta) {
records = append(records, &dns.TXT{
Hdr: dns.RR_Header{
Name: qName,
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: uint32(ttl / time.Second),
},
Txt: []string{txt},
})
}
}
return records return records
} }
@ -929,7 +957,7 @@ func (d *DNSServer) serviceNodeRecords(dc string, nodes structs.CheckServiceNode
handled[addr] = struct{}{} handled[addr] = struct{}{}
// Add the node record // Add the node record
records := d.formatNodeRecord(addr, qName, qType, ttl, edns) records := d.formatNodeRecord(node.Node, addr, qName, qType, ttl, edns)
if records != nil { if records != nil {
resp.Answer = append(resp.Answer, records...) resp.Answer = append(resp.Answer, records...)
} }
@ -973,7 +1001,7 @@ func (d *DNSServer) serviceSRVRecords(dc string, nodes structs.CheckServiceNodes
} }
// Add the extra record // Add the extra record
records := d.formatNodeRecord(addr, srvRec.Target, dns.TypeANY, ttl, edns) records := d.formatNodeRecord(node.Node, addr, srvRec.Target, dns.TypeANY, ttl, edns)
if len(records) > 0 { if len(records) > 0 {
// Use the node address if it doesn't differ from the service address // Use the node address if it doesn't differ from the service address
if addr == node.Node.Address { if addr == node.Node.Address {