Browse Source

feat(v2dns): addr. query support (#20224)

pull/20231/head
Dan Stough 10 months ago committed by GitHub
parent
commit
cb384ac068
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 19
      agent/discovery/discovery.go
  2. 2
      agent/dns.go
  3. 385
      agent/dns/router.go
  4. 466
      agent/dns/router_test.go
  5. 30
      agent/dns_node_lookup_test.go
  6. 86
      agent/dns_service_lookup_test.go
  7. 117
      agent/dns_test.go

19
agent/discovery/discovery.go

@ -60,15 +60,26 @@ type QueryPayload struct {
DisableFailover bool
}
// ResultType indicates the Consul resource that a discovery record represents.
// This is useful for things like adding TTLs for different objects in the DNS.
type ResultType string
const (
ResultTypeService ResultType = "SERVICE"
ResultTypeNode ResultType = "NODE"
ResultTypeVirtual ResultType = "VIRTUAL"
ResultTypeWorkload ResultType = "WORKLOAD"
)
// Result is a generic format of targets that could be returned in a query.
// It is the responsibility of the DNS encoder to know what to do with
// each Result, based on the query type.
type Result struct {
Address string // A/AAAA/CNAME records - could be used in the Extra section. CNAME is required to handle hostname addresses in workloads & nodes.
Weight uint32 // SRV queries
Port uint32 // SRV queries
TTL uint32
Address string // A/AAAA/CNAME records - could be used in the Extra section. CNAME is required to handle hostname addresses in workloads & nodes.
Weight uint32 // SRV queries
Port uint32 // SRV queries
Metadata []string // Used to collect metadata into TXT Records
Type ResultType
// Used in SRV & PTR queries to point at an A/AAAA Record.
// In V1, this could be a full-qualified Service or Node name.

2
agent/dns.go

@ -1060,6 +1060,8 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi
} else {
resp.Answer = append(resp.Answer, aaaaRecord)
}
default:
return invalid()
}
return nil
default:

385
agent/dns/router.go

@ -4,6 +4,8 @@
package dns
import (
"encoding/hex"
"errors"
"fmt"
"net"
"sync/atomic"
@ -16,6 +18,21 @@ import (
"github.com/hashicorp/consul/agent/config"
"github.com/hashicorp/consul/agent/discovery"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/logging"
)
const (
addrLabel = "addr"
arpaDomain = "in-addr.arpa."
suffixFailover = "failover."
suffixNoFailover = "no-failover."
)
var (
errInvalidQuestion = fmt.Errorf("invalid question")
errNameNotFound = fmt.Errorf("invalid question")
)
// TODO (v2-dns): metrics
@ -77,8 +94,21 @@ type Router struct {
var _ = dns.Handler(&Router{})
func NewRouter(cfg Config) (*Router, error) {
// Make sure domains are FQDN, make them case-insensitive for DNSRequestRouter
domain := dns.CanonicalName(cfg.AgentConfig.DNSDomain)
altDomain := dns.CanonicalName(cfg.AgentConfig.DNSAltDomain)
// TODO (v2-dns): need to figure out tenancy information here in a way that work for V2 and V1
router := &Router{
// TODO (v2-dns): implement stub
processor: cfg.Processor,
domain: domain,
altDomain: altDomain,
logger: cfg.Logger.Named(logging.DNS),
tokenFunc: cfg.TokenFunc,
// TODO (v2-dns): see tenancy question above
//defaultPartition: ?,
//defaultNamespace: ?,
}
if err := router.ReloadConfig(cfg.AgentConfig); err != nil {
@ -88,42 +118,71 @@ func NewRouter(cfg Config) (*Router, error) {
}
// HandleRequest is used to process and individual DNS request. It returns a message in success or fail cases.
func (r Router) HandleRequest(req *dns.Msg, reqCtx discovery.Context, remoteAddress net.Addr) *dns.Msg {
func (r *Router) HandleRequest(req *dns.Msg, reqCtx discovery.Context, remoteAddress net.Addr) *dns.Msg {
cfg := r.dynamicConfig.Load().(*RouterDynamicConfig)
// TODO (v2-dns): implement HandleRequest. This is just temporary
return createServerFailureResponse(req, cfg, false)
err := validateAndNormalizeRequest(req)
if err != nil {
r.logger.Error("error parsing DNS query", "error", err)
if errors.Is(err, errInvalidQuestion) {
return createRefusedResponse(req)
}
return createServerFailureResponse(req, cfg, false)
}
// Parse fields of the message
reqType, responseDomain, needRecurse := r.parseDomain(req)
// Route the request to the appropriate destination
// 1. r.processor.QueryByName
// 2. r.processor.QueryByIP
// 3. recurse
if needRecurse && canRecurse(cfg) {
// TODO (v2-dns): handle recursion
r.logger.Error("recursion not implemented")
return createServerFailureResponse(req, cfg, false)
}
// Serialize the output
var results []*discovery.Result
switch reqType {
case requestTypeName:
//query, err := r.buildQuery(req, reqCtx)
//results, err = r.processor.QueryByName(query, reqCtx)
// TODO (v2-dns): implement requestTypeName
// This will call discovery.QueryByName
r.logger.Error("requestTypeName not implemented")
case requestTypeIP:
// TODO (v2-dns): implement requestTypeIP
// This will call discovery.QueryByIP
r.logger.Error("requestTypeIP not implemented")
case requestTypeAddress:
results, err = buildAddressResults(req)
}
if err != nil && errors.Is(err, errNameNotFound) {
r.logger.Error("name not found", "name", req.Question[0].Name)
return createNameErrorResponse(req, cfg, responseDomain)
}
if err != nil {
r.logger.Error("error processing discovery query", "error", err)
return createServerFailureResponse(req, cfg, false)
}
// This needs the question information because it affects the serialization format.
// e.g., the Consul service has the same "results" for both NS and A/AAAA queries, but the serialization differs.
resp, err := r.serializeQueryResults(req, results, cfg, responseDomain)
if err != nil {
r.logger.Error("error serializing DNS results", "error", err)
return createServerFailureResponse(req, cfg, false)
}
return resp
}
// ServeDNS implements the miekg/dns.Handler interface
func (r Router) ServeDNS(w dns.ResponseWriter, req *dns.Msg) {
// ServeDNS implements the miekg/dns.Handler interface.
// This is a standard DNS listener, so we inject a default request context based on the agent's config.
func (r *Router) ServeDNS(w dns.ResponseWriter, req *dns.Msg) {
reqCtx := r.defaultAgentDNSRequestContext()
out := r.HandleRequest(req, reqCtx, w.RemoteAddr())
w.WriteMsg(out)
}
// GetDynamicRouterConfig takes global config and creates the config used by DNS server
func GetDynamicRouterConfig(conf *config.RuntimeConfig) (*RouterDynamicConfig, error) {
cfg := &RouterDynamicConfig{
// TODO (v2-dns)
}
return cfg, nil
}
// ReloadConfig hot-reloads the router config with new parameters
func (r Router) ReloadConfig(newCfg *config.RuntimeConfig) error {
cfg, err := GetDynamicRouterConfig(newCfg)
func (r *Router) ReloadConfig(newCfg *config.RuntimeConfig) error {
cfg, err := getDynamicRouterConfig(newCfg)
if err != nil {
return fmt.Errorf("error loading DNS config: %w", err)
}
@ -131,10 +190,142 @@ func (r Router) ReloadConfig(newCfg *config.RuntimeConfig) error {
return nil
}
func (r Router) defaultAgentDNSRequestContext() discovery.Context {
func (r *Router) defaultAgentDNSRequestContext() discovery.Context {
return discovery.Context{
// TODO (v2-dns): implement stub
Token: r.tokenFunc(),
// TODO (v2-dns): tenancy information; maybe we choose not to specify and use the default
// attached to the Router (from the agent's config)
}
}
func validateAndNormalizeRequest(req *dns.Msg) error {
// like upstream miekg/dns, we require at least one question,
// but we will only answer the first.
if len(req.Question) == 0 {
return errInvalidQuestion
}
// We mutate the request name to respond with the canonical name.
// This is Consul convention.
req.Question[0].Name = dns.CanonicalName(req.Question[0].Name)
return nil
}
// Request type is similar to miekg/dns.Type, but correlates to the different query processors we might need to invoke.
type requestType string
const (
requestTypeName requestType = "NAME" // A/AAAA/CNAME/SRV/SOA
requestTypeIP requestType = "IP"
requestTypeAddress requestType = "ADDR"
)
// parseQuery converts a DNS message into a generic discovery request.
// If the request domain does not match "consul." or the alternative domain,
// it will return true for needRecurse. The logic is based on miekg/dns.ServeDNS matcher.
// The implementation assumes that the only valid domains are "consul." and the alternative domain, and
// that DS query types are not supported.
func (r *Router) parseDomain(req *dns.Msg) (requestType, string, bool) {
target := dns.CanonicalName(req.Question[0].Name)
target, _ = stripSuffix(target)
for offset, overflow := 0, false; !overflow; offset, overflow = dns.NextLabel(target, offset) {
subdomain := target[offset:]
switch subdomain {
case r.domain:
if isAddrSubdomain(target) {
return requestTypeAddress, r.domain, false
}
return requestTypeName, r.domain, false
case r.altDomain:
// TODO (v2-dns): the default, unspecified alt domain should be ".". Next label should never return this
// but write a test to verify that.
if isAddrSubdomain(target) {
return requestTypeAddress, r.altDomain, false
}
return requestTypeName, r.altDomain, false
case arpaDomain:
// PTR queries always respond with the primary domain.
return requestTypeIP, r.domain, false
// Default: fallthrough
}
}
// No match found; recurse if possible
return "", "", true
}
func (r *Router) serializeQueryResults(req *dns.Msg, results []*discovery.Result, cfg *RouterDynamicConfig, responseDomain string) (*dns.Msg, error) {
resp := new(dns.Msg)
resp.SetReply(req)
resp.Compress = !cfg.DisableCompression
resp.Authoritative = true
resp.RecursionAvailable = canRecurse(cfg)
// TODO (v2-dns): add SOA if that is the question type
for _, result := range results {
appendResultToDNSResponse(result, req, resp, responseDomain, cfg)
}
return resp, nil
}
func stripSuffix(target string) (string, bool) {
enableFailover := false
// Strip off any suffixes that may have been added.
offset, underflow := dns.PrevLabel(target, 1)
if !underflow {
maybeSuffix := target[offset:]
switch maybeSuffix {
case suffixFailover:
target = target[:offset]
enableFailover = true
case suffixNoFailover:
target = target[:offset]
}
}
return target, enableFailover
}
func isAddrSubdomain(domain string) bool {
labels := dns.SplitDomainName(domain)
// Looking for <hexadecimal-encoded IP>.addr.<optional datacenter>.consul.
if len(labels) > 2 {
return labels[1] == addrLabel
}
return false
}
// getDynamicRouterConfig takes agent config and creates/resets the config used by DNS Router
func getDynamicRouterConfig(conf *config.RuntimeConfig) (*RouterDynamicConfig, error) {
cfg := &RouterDynamicConfig{
ARecordLimit: conf.DNSARecordLimit,
EnableTruncate: conf.DNSEnableTruncate,
NodeTTL: conf.DNSNodeTTL,
RecursorStrategy: conf.DNSRecursorStrategy,
RecursorTimeout: conf.DNSRecursorTimeout,
UDPAnswerLimit: conf.DNSUDPAnswerLimit,
NodeMetaTXT: conf.DNSNodeMetaTXT,
DisableCompression: conf.DNSDisableCompression,
SOAConfig: SOAConfig{
Expire: conf.DNSSOA.Expire,
Minttl: conf.DNSSOA.Minttl,
Refresh: conf.DNSSOA.Refresh,
Retry: conf.DNSSOA.Retry,
},
}
// TODO (v2-dns): add service TTL recalculation
// TODO (v2-dns): add recursor address formatting
return cfg, nil
}
func canRecurse(cfg *RouterDynamicConfig) bool {
return len(cfg.Recursors) > 0
}
func createServerFailureResponse(req *dns.Msg, cfg *RouterDynamicConfig, recursionAvailable bool) *dns.Msg {
@ -143,6 +334,150 @@ func createServerFailureResponse(req *dns.Msg, cfg *RouterDynamicConfig, recursi
m.SetReply(req)
m.Compress = !cfg.DisableCompression
m.SetRcode(req, dns.RcodeServerFailure)
// TODO (2-dns): set EDNS
m.RecursionAvailable = recursionAvailable
return m
}
func createRefusedResponse(req *dns.Msg) *dns.Msg {
// Return a REFUSED message
m := &dns.Msg{}
m.SetRcode(req, dns.RcodeRefused)
return m
}
func createNameErrorResponse(req *dns.Msg, cfg *RouterDynamicConfig, domain string) *dns.Msg {
// Return a NXDOMAIN message
m := &dns.Msg{}
m.SetRcode(req, dns.RcodeNameError)
m.Compress = !cfg.DisableCompression
m.Authoritative = true
// We add the SOA on NameErrors
// TODO (v2-dns): refactor into a common function
soa := &dns.SOA{
Hdr: dns.RR_Header{
Name: domain,
Rrtype: dns.TypeSOA,
Class: dns.ClassINET,
// Has to be consistent with MinTTL to avoid invalidation
Ttl: cfg.SOAConfig.Minttl,
},
Ns: "ns." + domain,
Serial: uint32(time.Now().Unix()),
Mbox: "hostmaster." + domain,
Refresh: cfg.SOAConfig.Refresh,
Retry: cfg.SOAConfig.Retry,
Expire: cfg.SOAConfig.Expire,
Minttl: cfg.SOAConfig.Minttl,
}
m.Ns = append(m.Ns, soa)
return m
}
func buildAddressResults(req *dns.Msg) ([]*discovery.Result, error) {
domain := dns.CanonicalName(req.Question[0].Name)
labels := dns.SplitDomainName(domain)
hexadecimal := labels[0]
if len(hexadecimal)/2 != 4 && len(hexadecimal)/2 != 16 {
return nil, errNameNotFound
}
var ip net.IP
ip, err := hex.DecodeString(hexadecimal)
if err != nil {
return nil, errNameNotFound
}
return []*discovery.Result{
{
Address: ip.String(),
Type: discovery.ResultTypeNode, // We choose node by convention since we do not know the origin of the IP
},
}, nil
}
func appendResultToDNSResponse(result *discovery.Result, req *dns.Msg, resp *dns.Msg, _ string, cfg *RouterDynamicConfig) {
ip, ok := convertToIp(result)
// if the result is not an IP, we can try to recurse on the hostname.
// TODO (v2-dns): hostnames are valid for workloads in V2, do we just want to return the CNAME?
if !ok {
// TODO (v2-dns): recurse on HandleRequest()
panic("not implemented")
}
var ttl uint32
switch result.Type {
case discovery.ResultTypeNode:
ttl = uint32(cfg.NodeTTL / time.Second)
case discovery.ResultTypeService:
// TODO (v2-dns): implement service TTL using the radix tree
}
qName := dns.CanonicalName(req.Question[0].Name)
qType := req.Question[0].Qtype
record, isIPV4 := makeRecord(qName, ip, ttl)
if qType == dns.TypeSRV {
// We put A/AAAA/CNAME records in the additional section for SRV requests
resp.Extra = append(resp.Extra, record)
// TODO (v2-dns): implement SRV records for the answer section
return
}
// For explicit A/AAAA queries, we must only return those records in the answer section.
if isIPV4 && qType != dns.TypeA && qType != dns.TypeANY {
resp.Extra = append(resp.Extra, record)
return
}
if !isIPV4 && qType != dns.TypeAAAA && qType != dns.TypeANY {
resp.Extra = append(resp.Extra, record)
return
}
resp.Answer = append(resp.Answer, record)
}
func convertToIp(result *discovery.Result) (net.IP, bool) {
ip := net.ParseIP(result.Address)
if ip == nil {
return nil, false
}
return ip, true
}
// Note: we might want to pass in the Query Name here, which is used in addr. and virtual. queries
// since there is only ever one result. Right now choosing to leave it off for simplification.
func makeRecord(name string, ip net.IP, ttl uint32) (dns.RR, bool) {
isIPV4 := ip.To4() != nil
if isIPV4 {
// check if the query type is A for IPv4 or ANY
return &dns.A{
Hdr: dns.RR_Header{
Name: name,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: ttl,
},
A: ip,
}, true
}
return &dns.AAAA{
Hdr: dns.RR_Header{
Name: name,
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: ttl,
},
AAAA: ip,
}, false
}

466
agent/dns/router_test.go

@ -3,4 +3,470 @@
package dns
import (
"net"
"testing"
"time"
"github.com/hashicorp/go-hclog"
"github.com/miekg/dns"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/agent/config"
"github.com/hashicorp/consul/agent/discovery"
)
// TODO (v2-dns)
// Test Parameters
// 1. Domain vs AltDomain vs non-consul Main domain
// 2. Reload the configuration (e.g. SOA)
// 3. Something to check the token makes it through to the data fetcher
// 4. Something case insensitive
func Test_HandleRequest(t *testing.T) {
type testCase struct {
name string
agentConfig *config.RuntimeConfig // This will override the default test Router Config
mockProcessorResponseByName []*discovery.Result // These will be fed to the mock processor to be returned in order
mockProcessorResponseByIP []*discovery.Result
mockProcessorError error
request *dns.Msg
requestContext *discovery.Context
remoteAddress net.Addr
response *dns.Msg
}
testCases := []testCase{
{
name: "test A 'addr.' query, ipv4 response",
request: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
},
Question: []dns.Question{
{
Name: "c000020a.addr.dc1.consul", // "intentionally missing the trailing dot"
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
},
},
},
response: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
Response: true,
Authoritative: true,
},
Compress: true,
Question: []dns.Question{
{
Name: "c000020a.addr.dc1.consul.",
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "c000020a.addr.dc1.consul.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 123,
},
A: net.ParseIP("192.0.2.10"),
},
},
},
},
{
name: "test AAAA 'addr.' query, ipv4 response",
// Since we asked for an AAAA record, the A record that resolves from the address is attached as an extra
request: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
},
Question: []dns.Question{
{
Name: "c000020a.addr.dc1.consul",
Qtype: dns.TypeAAAA,
Qclass: dns.ClassINET,
},
},
},
response: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
Response: true,
Authoritative: true,
},
Compress: true,
Question: []dns.Question{
{
Name: "c000020a.addr.dc1.consul.",
Qtype: dns.TypeAAAA,
Qclass: dns.ClassINET,
},
},
Extra: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "c000020a.addr.dc1.consul.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 123,
},
A: net.ParseIP("192.0.2.10"),
},
},
},
},
{
name: "test SRV 'addr.' query, ipv4 response",
// Since we asked for a SRV record, the A record that resolves from the address is attached as an extra
request: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
},
Question: []dns.Question{
{
Name: "c000020a.addr.dc1.consul",
Qtype: dns.TypeSRV,
Qclass: dns.ClassINET,
},
},
},
response: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
Response: true,
Authoritative: true,
},
Compress: true,
Question: []dns.Question{
{
Name: "c000020a.addr.dc1.consul.",
Qtype: dns.TypeSRV,
Qclass: dns.ClassINET,
},
},
Extra: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "c000020a.addr.dc1.consul.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 123,
},
A: net.ParseIP("192.0.2.10"),
},
},
},
},
{
name: "test ANY 'addr.' query, ipv4 response",
// The response to ANY should look the same as the A response
request: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
},
Question: []dns.Question{
{
Name: "c000020a.addr.dc1.consul",
Qtype: dns.TypeANY,
Qclass: dns.ClassINET,
},
},
},
response: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
Response: true,
Authoritative: true,
},
Compress: true,
Question: []dns.Question{
{
Name: "c000020a.addr.dc1.consul.",
Qtype: dns.TypeANY,
Qclass: dns.ClassINET,
},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "c000020a.addr.dc1.consul.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 123,
},
A: net.ParseIP("192.0.2.10"),
},
},
},
},
{
name: "test AAAA 'addr.' query, ipv6 response",
request: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
},
Question: []dns.Question{
{
Name: "20010db800010002cafe000000001337.addr.dc1.consul",
Qtype: dns.TypeAAAA,
Qclass: dns.ClassINET,
},
},
},
response: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
Response: true,
Authoritative: true,
},
Compress: true,
Question: []dns.Question{
{
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
Qtype: dns.TypeAAAA,
Qclass: dns.ClassINET,
},
},
Answer: []dns.RR{
&dns.AAAA{
Hdr: dns.RR_Header{
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: 123,
},
AAAA: net.ParseIP("2001:db8:1:2:cafe::1337"),
},
},
},
},
{
name: "test A 'addr.' query, ipv6 response",
// Since we asked for an A record, the AAAA record that resolves from the address is attached as an extra
request: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
},
Question: []dns.Question{
{
Name: "20010db800010002cafe000000001337.addr.dc1.consul",
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
},
},
},
response: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
Response: true,
Authoritative: true,
},
Compress: true,
Question: []dns.Question{
{
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
},
},
Extra: []dns.RR{
&dns.AAAA{
Hdr: dns.RR_Header{
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: 123,
},
AAAA: net.ParseIP("2001:db8:1:2:cafe::1337"),
},
},
},
},
{
name: "test SRV 'addr.' query, ipv6 response",
// Since we asked for an SRV record, the AAAA record that resolves from the address is attached as an extra
request: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
},
Question: []dns.Question{
{
Name: "20010db800010002cafe000000001337.addr.dc1.consul",
Qtype: dns.TypeSRV,
Qclass: dns.ClassINET,
},
},
},
response: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
Response: true,
Authoritative: true,
},
Compress: true,
Question: []dns.Question{
{
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
Qtype: dns.TypeSRV,
Qclass: dns.ClassINET,
},
},
Extra: []dns.RR{
&dns.AAAA{
Hdr: dns.RR_Header{
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: 123,
},
AAAA: net.ParseIP("2001:db8:1:2:cafe::1337"),
},
},
},
},
{
name: "test ANY 'addr.' query, ipv6 response",
// The response to ANY should look the same as the AAAA response
request: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
},
Question: []dns.Question{
{
Name: "20010db800010002cafe000000001337.addr.dc1.consul",
Qtype: dns.TypeANY,
Qclass: dns.ClassINET,
},
},
},
response: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
Response: true,
Authoritative: true,
},
Compress: true,
Question: []dns.Question{
{
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
Qtype: dns.TypeANY,
Qclass: dns.ClassINET,
},
},
Answer: []dns.RR{
&dns.AAAA{
Hdr: dns.RR_Header{
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: 123,
},
AAAA: net.ParseIP("2001:db8:1:2:cafe::1337"),
},
},
},
},
{
name: "test malformed 'addr.' query",
request: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
},
Question: []dns.Question{
{
Name: "c000.addr.dc1.consul", // too short
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
},
},
},
response: &dns.Msg{
MsgHdr: dns.MsgHdr{
Opcode: dns.OpcodeQuery,
Response: true,
Rcode: dns.RcodeNameError, // NXDOMAIN
Authoritative: true,
},
Compress: true,
Question: []dns.Question{
{
Name: "c000.addr.dc1.consul.",
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
},
},
Ns: []dns.RR{
&dns.SOA{
Hdr: dns.RR_Header{
Name: "consul.",
Rrtype: dns.TypeSOA,
Class: dns.ClassINET,
Ttl: 4,
},
Ns: "ns.consul.",
Serial: uint32(time.Now().Unix()),
Mbox: "hostmaster.consul.",
Refresh: 1,
Expire: 3,
Retry: 2,
Minttl: 4,
},
},
},
},
}
run := func(t *testing.T, tc testCase) {
cfg := buildDNSConfig(tc.agentConfig, tc.mockProcessorResponseByName, tc.mockProcessorResponseByIP, tc.mockProcessorError)
router, err := NewRouter(cfg)
require.NoError(t, err)
ctx := tc.requestContext
if ctx == nil {
ctx = &discovery.Context{}
}
actual := router.HandleRequest(tc.request, *ctx, tc.remoteAddress)
require.Equal(t, tc.response, actual)
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
run(t, tc)
})
}
}
func buildDNSConfig(agentConfig *config.RuntimeConfig, _ []*discovery.Result, _ []*discovery.Result, _ error) Config {
cfg := Config{
AgentConfig: &config.RuntimeConfig{
DNSDomain: "consul",
DNSNodeTTL: 123 * time.Second,
DNSSOA: config.RuntimeSOAConfig{
Refresh: 1,
Retry: 2,
Expire: 3,
Minttl: 4,
},
},
EntMeta: nil,
Logger: hclog.NewNullLogger(),
Processor: nil, // TODO (v2-dns): build this from a mock with the reponses loaded
TokenFunc: func() string { return "" },
}
if agentConfig != nil {
cfg.AgentConfig = agentConfig
}
return cfg
}

30
agent/dns_node_lookup_test.go

@ -5,11 +5,13 @@ package agent
import (
"context"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/testrpc"
"testing"
"github.com/miekg/dns"
"github.com/stretchr/testify/require"
"testing"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/testrpc"
)
func TestDNS_NodeLookup(t *testing.T) {
@ -18,7 +20,7 @@ func TestDNS_NodeLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -121,7 +123,7 @@ func TestDNS_CaseInsensitiveNodeLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -161,7 +163,7 @@ func TestDNS_NodeLookup_PeriodName(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -209,7 +211,7 @@ func TestDNS_NodeLookup_AAAA(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -269,7 +271,7 @@ func TestDNS_NodeLookup_CNAME(t *testing.T) {
})
defer recursor.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
recursors = ["`+recursor.Addr+`"]
@ -327,7 +329,7 @@ func TestDNS_NodeLookup_TXT(t *testing.T) {
t.Skip("too slow for testing.Short")
}
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -381,7 +383,7 @@ func TestDNS_NodeLookup_TXT_DontSuppress(t *testing.T) {
t.Skip("too slow for testing.Short")
}
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false } `+experimentsHCL)
defer a.Shutdown()
@ -435,7 +437,7 @@ func TestDNS_NodeLookup_ANY(t *testing.T) {
t.Skip("too slow for testing.Short")
}
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -484,7 +486,7 @@ func TestDNS_NodeLookup_ANY_DontSuppressTXT(t *testing.T) {
t.Skip("too slow for testing.Short")
}
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false } `+experimentsHCL)
defer a.Shutdown()
@ -533,7 +535,7 @@ func TestDNS_NodeLookup_A_SuppressTXT(t *testing.T) {
t.Skip("too slow for testing.Short")
}
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false } `+experimentsHCL)
defer a.Shutdown()
@ -586,7 +588,7 @@ func TestDNS_NodeLookup_TTL(t *testing.T) {
})
defer recursor.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
recursors = ["`+recursor.Addr+`"]

86
agent/dns_service_lookup_test.go

@ -6,16 +6,18 @@ package agent
import (
"context"
"fmt"
"sort"
"strings"
"testing"
"github.com/miekg/dns"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/sdk/testutil/retry"
"github.com/hashicorp/consul/testrpc"
"github.com/miekg/dns"
"github.com/stretchr/testify/require"
"sort"
"strings"
"testing"
)
func TestDNS_ServiceReverseLookup(t *testing.T) {
@ -24,7 +26,7 @@ func TestDNS_ServiceReverseLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -80,7 +82,7 @@ func TestDNS_ServiceReverseLookup_IPV6(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -136,7 +138,7 @@ func TestDNS_ServiceReverseLookup_CustomDomain(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
domain = "custom"
@ -194,7 +196,7 @@ func TestDNS_ServiceReverseLookupNodeAddress(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -250,7 +252,7 @@ func TestDNS_ServiceLookupNoMultiCNAME(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -313,7 +315,7 @@ func TestDNS_ServiceLookupPreferNoCNAME(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -379,7 +381,7 @@ func TestDNS_ServiceLookupMultiAddrNoCNAME(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -461,7 +463,7 @@ func TestDNS_ServiceLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -589,7 +591,7 @@ func TestDNS_ServiceLookupWithInternalServiceAddress(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
node_name = "my.test-node"
@ -655,7 +657,7 @@ func TestDNS_ConnectServiceLookup(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -708,7 +710,7 @@ func TestDNS_IngressServiceLookup(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -818,7 +820,7 @@ func TestDNS_ExternalServiceLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -884,7 +886,7 @@ func TestDNS_ExternalServiceToConsulCNAMELookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
domain = "CONSUL."
@ -990,7 +992,7 @@ func TestDNS_ExternalServiceToConsulCNAMENestedLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
node_name = "test-node"
@ -1125,7 +1127,7 @@ func TestDNS_ServiceLookup_ServiceAddress_A(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1226,7 +1228,7 @@ func TestDNS_AltDomain_ServiceLookup_ServiceAddress_A(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
alt_domain = "test-domain"
@ -1342,7 +1344,7 @@ func TestDNS_ServiceLookup_ServiceAddress_SRV(t *testing.T) {
})
defer recursor.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
recursors = ["`+recursor.Addr+`"]
@ -1455,7 +1457,7 @@ func TestDNS_ServiceLookup_ServiceAddressIPV6(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1556,7 +1558,7 @@ func TestDNS_AltDomain_ServiceLookup_ServiceAddressIPV6(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
alt_domain = "test-domain"
@ -1664,7 +1666,7 @@ func TestDNS_ServiceLookup_WanTranslation(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a1 := NewTestAgent(t, `
datacenter = "dc1"
@ -1897,7 +1899,7 @@ func TestDNS_CaseInsensitiveServiceLookup(t *testing.T) {
}
for _, tst := range tests {
t.Run(fmt.Sprintf("A lookup %v", tst.name), func(t *testing.T) {
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, fmt.Sprintf("%s %s", tst.config, experimentsHCL))
defer a.Shutdown()
@ -1982,7 +1984,7 @@ func TestDNS_ServiceLookup_TagPeriod(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2062,7 +2064,7 @@ func TestDNS_ServiceLookup_PreparedQueryNamePeriod(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2149,7 +2151,7 @@ func TestDNS_ServiceLookup_Dedup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2260,7 +2262,7 @@ func TestDNS_ServiceLookup_Dedup_SRV(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2399,7 +2401,7 @@ func TestDNS_ServiceLookup_FilterCritical(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2563,7 +2565,7 @@ func TestDNS_ServiceLookup_OnlyFailing(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2684,7 +2686,7 @@ func TestDNS_ServiceLookup_OnlyPassing(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
dns_config {
@ -2835,7 +2837,7 @@ func TestDNS_ServiceLookup_Randomize(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2934,7 +2936,7 @@ func TestDNS_ServiceLookup_Truncate(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
dns_config {
@ -3011,7 +3013,7 @@ func TestDNS_ServiceLookup_LargeResponses(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
dns_config {
@ -3217,7 +3219,7 @@ func checkDNSService(
expectedResultsCount int,
udpSize uint16,
) {
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
node_name = "test-node"
@ -3390,7 +3392,7 @@ func TestDNS_ServiceLookup_AnswerLimits(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
// Build a matrix of config parameters (udpAnswerLimit), and the
@ -3473,7 +3475,7 @@ func TestDNS_ServiceLookup_CNAME(t *testing.T) {
})
defer recursor.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
recursors = ["`+recursor.Addr+`"]
@ -3578,7 +3580,7 @@ func TestDNS_ServiceLookup_ServiceAddress_CNAME(t *testing.T) {
})
defer recursor.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
recursors = ["`+recursor.Addr+`"]
@ -3676,7 +3678,7 @@ func TestDNS_ServiceLookup_TTL(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
dns_config {
@ -3762,7 +3764,7 @@ func TestDNS_ServiceLookup_SRV_RFC(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()

117
agent/dns_test.go

@ -116,9 +116,16 @@ func dnsTXT(src string, txt []string) *dns.TXT {
}
}
var versionHCL = map[string]string{
"DNS: v1 / Catalog: v1": "",
//"DNS: v2 / Catalog: v1": `experiments=["v2-dns"]`,
func getVersionHCL(enableV2 bool) map[string]string {
versions := map[string]string{
"DNS: v1 / Catalog: v1": "",
//"DNS: v2 / Catalog: v1": `experiments=["v2dns"]`,
}
if enableV2 {
versions["DNS: v2 / Catalog: v1"] = `experiments=["v2dns"]`
}
return versions
}
func TestRecursorAddr(t *testing.T) {
@ -182,7 +189,7 @@ func TestDNS_Over_TCP(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -223,7 +230,7 @@ func TestDNS_EmptyAltDomain(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -259,7 +266,7 @@ func TestDNSCycleRecursorCheck(t *testing.T) {
},
})
defer server2.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
// Mock the agent startup with the necessary configs
agent := NewTestAgent(t,
@ -301,7 +308,7 @@ func TestDNSCycleRecursorCheckAllFail(t *testing.T) {
MsgHdr: dns.MsgHdr{Rcode: dns.RcodeRefused},
})
defer server3.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
// Mock the agent startup with the necessary configs
agent := NewTestAgent(t,
@ -326,7 +333,7 @@ func TestDNS_EDNS0(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -374,7 +381,7 @@ func TestDNS_EDNS0_ECS(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -473,7 +480,7 @@ func TestDNS_ReverseLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -521,7 +528,7 @@ func TestDNS_ReverseLookup_CustomDomain(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
domain = "custom"
@ -571,7 +578,7 @@ func TestDNS_ReverseLookup_IPV6(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -640,7 +647,7 @@ func TestDNS_SOA_Settings(t *testing.T) {
require.Equal(t, uint32(retry), soaRec.Retry)
require.Equal(t, uint32(ttl), soaRec.Hdr.Ttl)
}
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
// Default configuration
@ -662,7 +669,7 @@ func TestDNS_VirtualIPLookup(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := StartTestAgent(t, TestAgent{HCL: experimentsHCL, Overrides: `peering = { test_allow_peer_registrations = true }`})
defer a.Shutdown()
@ -760,7 +767,7 @@ func TestDNS_InifiniteRecursion(t *testing.T) {
// This test should not create an infinite recursion
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
domain = "CONSUL."
@ -822,7 +829,7 @@ func TestDNS_NSRecords(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
domain = "CONSUL."
@ -865,7 +872,7 @@ func TestDNS_AltDomain_NSRecords(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
@ -921,7 +928,7 @@ func TestDNS_NSRecords_IPV6(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
domain = "CONSUL."
@ -965,7 +972,7 @@ func TestDNS_AltDomain_NSRecords_IPV6(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
domain = "CONSUL."
@ -1021,7 +1028,7 @@ func TestDNS_Lookup_TaggedIPAddresses(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1230,7 +1237,7 @@ func TestDNS_PreparedQueryNearIPEDNS(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1365,7 +1372,7 @@ func TestDNS_PreparedQueryNearIP(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1483,7 +1490,7 @@ func TestDNS_Recurse(t *testing.T) {
})
defer recursor.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
recursors = ["`+recursor.Addr+`"]
@ -1523,7 +1530,7 @@ func TestDNS_Recurse_Truncation(t *testing.T) {
})
defer recursor.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
recursors = ["`+recursor.Addr+`"]
@ -1572,7 +1579,7 @@ func TestDNS_RecursorTimeout(t *testing.T) {
}
defer resolver.Close()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
recursors = ["`+resolver.LocalAddr().String()+`"] // host must cause a connection|read|write timeout
@ -1659,7 +1666,7 @@ func TestDNS_TCP_and_UDP_Truncate(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
dns_config {
@ -1777,7 +1784,7 @@ func TestDNS_AddressLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(true) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1815,7 +1822,7 @@ func TestDNS_AddressLookupANY(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(true) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1851,7 +1858,7 @@ func TestDNS_AddressLookupInvalidType(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(true) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1883,7 +1890,7 @@ func TestDNS_AddressLookupIPV6(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(true) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1932,7 +1939,7 @@ func TestDNS_AddressLookupIPV6InvalidType(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(true) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -1970,7 +1977,7 @@ func TestDNS_NonExistentDC_Server(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2001,7 +2008,7 @@ func TestDNS_NonExistentDC_RPC(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
s := NewTestAgent(t, `
node_name = "test-server"
@ -2043,7 +2050,7 @@ func TestDNS_NonExistingLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2080,7 +2087,7 @@ func TestDNS_NonExistingLookupEmptyAorAAAA(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2222,7 +2229,7 @@ func TestDNS_AltDomains_Service(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
alt_domain = "test-domain."
@ -2321,7 +2328,7 @@ func TestDNS_AltDomains_SOA(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
node_name = "test-node"
@ -2377,7 +2384,7 @@ func TestDNS_AltDomains_Overlap(t *testing.T) {
// than one potential match (i.e. ambiguous match)
// it should select the longer matching domain when dispatching
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
node_name = "test-node"
@ -2428,7 +2435,7 @@ func TestDNS_AltDomain_DCName_Overlap(t *testing.T) {
// this tests the DC name overlap with the consul domain/alt-domain
// we should get response when DC suffix is a prefix of consul alt-domain
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
datacenter = "dc-test"
@ -2469,7 +2476,7 @@ func TestDNS_PreparedQuery_AllowStale(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
dns_config {
@ -2526,7 +2533,7 @@ func TestDNS_InvalidQueries(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2575,7 +2582,7 @@ func TestDNS_PreparedQuery_AgentSource(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()
@ -2616,7 +2623,7 @@ func TestDNS_EDNS_Truncate_AgentSource(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
dns_config {
@ -2661,7 +2668,7 @@ func TestDNS_EDNS_Truncate_AgentSource(t *testing.T) {
func TestDNS_trimUDPResponse_NoTrim(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
req := &dns.Msg{}
@ -2724,7 +2731,7 @@ func TestDNS_trimUDPResponse_NoTrim(t *testing.T) {
func TestDNS_trimUDPResponse_TrimLimit(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `+experimentsHCL)
@ -2768,7 +2775,7 @@ func TestDNS_trimUDPResponse_TrimLimit(t *testing.T) {
func TestDNS_trimUDPResponse_TrimLimitWithNS(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `+experimentsHCL)
@ -2820,7 +2827,7 @@ func TestDNS_trimUDPResponse_TrimLimitWithNS(t *testing.T) {
func TestDNS_trimTCPResponse_TrimLimitWithNS(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `+experimentsHCL)
@ -2881,7 +2888,7 @@ func loadRuntimeConfig(t *testing.T, hcl string) *config.RuntimeConfig {
func TestDNS_trimUDPResponse_TrimSize(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `+experimentsHCL)
@ -2938,7 +2945,7 @@ func TestDNS_trimUDPResponse_TrimSize(t *testing.T) {
func TestDNS_trimUDPResponse_TrimSizeEDNS(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `+experimentsHCL)
@ -3022,7 +3029,7 @@ func TestDNS_trimUDPResponse_TrimSizeEDNS(t *testing.T) {
func TestDNS_trimUDPResponse_TrimSizeMaxSize(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `+experimentsHCL)
@ -3299,7 +3306,7 @@ func TestDNS_syncExtra(t *testing.T) {
func TestDNS_Compression_trimUDPResponse(t *testing.T) {
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
cfg := loadRuntimeConfig(t, `data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `+experimentsHCL)
@ -3327,7 +3334,7 @@ func TestDNS_Compression_Query(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
@ -3423,7 +3430,7 @@ func TestDNS_Compression_ReverseLookup(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
@ -3489,7 +3496,7 @@ func TestDNS_Compression_Recurse(t *testing.T) {
})
defer recursor.Shutdown()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, `
@ -3683,7 +3690,7 @@ func TestDNS_ReloadConfig_DuringQuery(t *testing.T) {
}
t.Parallel()
for name, experimentsHCL := range versionHCL {
for name, experimentsHCL := range getVersionHCL(false) {
t.Run(name, func(t *testing.T) {
a := NewTestAgent(t, experimentsHCL)
defer a.Shutdown()

Loading…
Cancel
Save