dns: add endpoint for querying service virtual IPs

This commit is contained in:
Kyle Havlovitz 2021-12-02 16:29:50 -08:00
parent 6f34a4f777
commit 0546bbe08a
3 changed files with 57 additions and 1 deletions

3
.changelog/11725.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
dns: Added a `virtual` endpoint for querying the assigned virtual IP for a service.
```

View File

@ -695,7 +695,7 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi
done := false
for i := len(labels) - 1; i >= 0 && !done; i-- {
switch labels[i] {
case "service", "connect", "ingress", "node", "query", "addr":
case "service", "connect", "virtual", "ingress", "node", "query", "addr":
queryParts = labels[:i]
querySuffixes = labels[i+1:]
queryKind = labels[i]
@ -785,6 +785,41 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi
// name.connect.consul
return d.serviceLookup(cfg, lookup, req, resp)
case "virtual":
if len(queryParts) < 1 {
return invalid()
}
if !d.parseDatacenterAndEnterpriseMeta(querySuffixes, cfg, &datacenter, &entMeta) {
return invalid()
}
args := structs.ServiceSpecificRequest{
Datacenter: datacenter,
ServiceName: queryParts[len(queryParts)-1],
EnterpriseMeta: entMeta,
QueryOptions: structs.QueryOptions{
Token: d.agent.tokens.UserToken(),
},
}
var out string
if err := d.agent.RPC("Catalog.VirtualIPForService", &args, &out); err != nil {
return err
}
if out != "" {
resp.Answer = append(resp.Answer, &dns.A{
Hdr: dns.RR_Header{
Name: qName + respDomain,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: uint32(cfg.NodeTTL / time.Second),
},
A: net.ParseIP(out),
})
}
return nil
case "ingress":
if len(queryParts) < 1 {
return invalid()

View File

@ -1756,6 +1756,24 @@ func TestDNS_ConnectServiceLookup(t *testing.T) {
require.Equal(t, uint32(0), srvRec.Hdr.Ttl)
require.Equal(t, "127.0.0.55", cnameRec.A.String())
}
// Look up the virtual IP of the proxy.
questions = []string{
"db.virtual.consul.",
}
for _, question := range questions {
m := new(dns.Msg)
m.SetQuestion(question, dns.TypeA)
c := new(dns.Client)
in, _, err := c.Exchange(m, a.DNSAddr())
require.Nil(t, err)
require.Len(t, in.Answer, 1)
aRec, ok := in.Answer[0].(*dns.A)
require.True(t, ok)
require.Equal(t, "240.0.0.1", aRec.A.String())
}
}
func TestDNS_IngressServiceLookup(t *testing.T) {