agent: working DNS for Connect queries, I think, but have to

implement Health endpoints to be sure
This commit is contained in:
Mitchell Hashimoto 2018-03-09 09:09:21 -08:00
parent fa4f0d353b
commit a5fe6204d5
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
2 changed files with 59 additions and 7 deletions

View File

@ -337,7 +337,7 @@ func (d *DNSServer) addSOA(msg *dns.Msg) {
// nameservers returns the names and ip addresses of up to three random servers // nameservers returns the names and ip addresses of up to three random servers
// in the current cluster which serve as authoritative name servers for zone. // in the current cluster which serve as authoritative name servers for zone.
func (d *DNSServer) nameservers(edns bool) (ns []dns.RR, extra []dns.RR) { func (d *DNSServer) nameservers(edns bool) (ns []dns.RR, extra []dns.RR) {
out, err := d.lookupServiceNodes(d.agent.config.Datacenter, structs.ConsulServiceName, "") out, err := d.lookupServiceNodes(d.agent.config.Datacenter, structs.ConsulServiceName, "", false)
if err != nil { if err != nil {
d.logger.Printf("[WARN] dns: Unable to get list of servers: %s", err) d.logger.Printf("[WARN] dns: Unable to get list of servers: %s", err)
return nil, nil return nil, nil
@ -415,7 +415,7 @@ PARSE:
n = n + 1 n = n + 1
} }
switch labels[n-1] { switch kind := labels[n-1]; kind {
case "service": case "service":
if n == 1 { if n == 1 {
goto INVALID goto INVALID
@ -433,7 +433,7 @@ PARSE:
} }
// _name._tag.service.consul // _name._tag.service.consul
d.serviceLookup(network, datacenter, labels[n-3][1:], tag, req, resp) d.serviceLookup(network, datacenter, labels[n-3][1:], tag, false, req, resp)
// Consul 0.3 and prior format for SRV queries // Consul 0.3 and prior format for SRV queries
} else { } else {
@ -445,9 +445,17 @@ PARSE:
} }
// tag[.tag].name.service.consul // tag[.tag].name.service.consul
d.serviceLookup(network, datacenter, labels[n-2], tag, req, resp) d.serviceLookup(network, datacenter, labels[n-2], tag, false, req, resp)
} }
case "connect":
if n == 1 {
goto INVALID
}
// name.connect.consul
d.serviceLookup(network, datacenter, labels[n-2], "", true, req, resp)
case "node": case "node":
if n == 1 { if n == 1 {
goto INVALID goto INVALID
@ -898,8 +906,9 @@ func (d *DNSServer) trimDNSResponse(network string, req, resp *dns.Msg) (trimmed
} }
// lookupServiceNodes returns nodes with a given service. // lookupServiceNodes returns nodes with a given service.
func (d *DNSServer) lookupServiceNodes(datacenter, service, tag string) (structs.IndexedCheckServiceNodes, error) { func (d *DNSServer) lookupServiceNodes(datacenter, service, tag string, connect bool) (structs.IndexedCheckServiceNodes, error) {
args := structs.ServiceSpecificRequest{ args := structs.ServiceSpecificRequest{
Connect: connect,
Datacenter: datacenter, Datacenter: datacenter,
ServiceName: service, ServiceName: service,
ServiceTag: tag, ServiceTag: tag,
@ -935,8 +944,8 @@ func (d *DNSServer) lookupServiceNodes(datacenter, service, tag string) (structs
} }
// serviceLookup is used to handle a service query // serviceLookup is used to handle a service query
func (d *DNSServer) serviceLookup(network, datacenter, service, tag string, req, resp *dns.Msg) { func (d *DNSServer) serviceLookup(network, datacenter, service, tag string, connect bool, req, resp *dns.Msg) {
out, err := d.lookupServiceNodes(datacenter, service, tag) out, err := d.lookupServiceNodes(datacenter, service, tag, connect)
if err != nil { if err != nil {
d.logger.Printf("[ERR] dns: rpc error: %v", err) d.logger.Printf("[ERR] dns: rpc error: %v", err)
resp.SetRcode(req, dns.RcodeServerFailure) resp.SetRcode(req, dns.RcodeServerFailure)

View File

@ -17,6 +17,7 @@ import (
"github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/coordinate"
"github.com/miekg/dns" "github.com/miekg/dns"
"github.com/pascaldekloe/goe/verify" "github.com/pascaldekloe/goe/verify"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -1041,6 +1042,48 @@ func TestDNS_ServiceLookupWithInternalServiceAddress(t *testing.T) {
verify.Values(t, "extra", in.Extra, wantExtra) verify.Values(t, "extra", in.Extra, wantExtra)
} }
func TestDNS_ConnectServiceLookup(t *testing.T) {
t.Parallel()
assert := assert.New(t)
a := NewTestAgent(t.Name(), "")
defer a.Shutdown()
// Register a node with an external service.
{
args := structs.TestRegisterRequestProxy(t)
args.Service.ProxyDestination = "db"
args.Service.Port = 12345
var out struct{}
assert.Nil(a.RPC("Catalog.Register", args, &out))
}
// Look up the service
questions := []string{
"db.connect.consul.",
}
for _, question := range questions {
m := new(dns.Msg)
m.SetQuestion(question, dns.TypeSRV)
c := new(dns.Client)
in, _, err := c.Exchange(m, a.DNSAddr())
assert.Nil(err)
assert.Len(in.Answer, 1)
srvRec, ok := in.Answer[0].(*dns.SRV)
assert.True(ok)
assert.Equal(12345, srvRec.Port)
assert.Equal("foo.node.dc1.consul.", srvRec.Target)
assert.Equal(0, srvRec.Hdr.Ttl)
cnameRec, ok := in.Extra[0].(*dns.CNAME)
assert.True(ok)
assert.Equal("foo.node.dc1.consul.", cnameRec.Hdr.Name)
assert.Equal(0, srvRec.Hdr.Ttl)
}
}
func TestDNS_ExternalServiceLookup(t *testing.T) { func TestDNS_ExternalServiceLookup(t *testing.T) {
t.Parallel() t.Parallel()
a := NewTestAgent(t.Name(), "") a := NewTestAgent(t.Name(), "")