2024-01-17 23:46:18 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
|
|
|
|
package dns
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/miekg/dns"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
2024-02-02 23:29:38 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/consul/agent/discovery"
|
2024-01-17 23:46:18 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// testCaseBuildQueryFromDNSMessage is a test case for the buildQueryFromDNSMessage function.
|
|
|
|
type testCaseBuildQueryFromDNSMessage struct {
|
|
|
|
name string
|
|
|
|
request *dns.Msg
|
2024-02-02 23:29:38 +00:00
|
|
|
requestContext *Context
|
2024-01-17 23:46:18 +00:00
|
|
|
expectedQuery *discovery.Query
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test_buildQueryFromDNSMessage tests the buildQueryFromDNSMessage function.
|
|
|
|
func Test_buildQueryFromDNSMessage(t *testing.T) {
|
|
|
|
|
2024-02-02 23:29:38 +00:00
|
|
|
testCases := []testCaseBuildQueryFromDNSMessage{
|
|
|
|
// virtual ip queries
|
|
|
|
{
|
|
|
|
name: "test A 'virtual.' query",
|
|
|
|
request: &dns.Msg{
|
|
|
|
MsgHdr: dns.MsgHdr{
|
|
|
|
Opcode: dns.OpcodeQuery,
|
|
|
|
},
|
|
|
|
Question: []dns.Question{
|
|
|
|
{
|
|
|
|
Name: "db.virtual.consul", // "intentionally missing the trailing dot"
|
|
|
|
Qtype: dns.TypeA,
|
|
|
|
Qclass: dns.ClassINET,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedQuery: &discovery.Query{
|
|
|
|
QueryType: discovery.QueryTypeVirtual,
|
|
|
|
QueryPayload: discovery.QueryPayload{
|
|
|
|
Name: "db",
|
|
|
|
Tenancy: discovery.QueryTenancy{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "test A 'virtual.' with kitchen sink labels",
|
|
|
|
request: &dns.Msg{
|
|
|
|
MsgHdr: dns.MsgHdr{
|
|
|
|
Opcode: dns.OpcodeQuery,
|
|
|
|
},
|
|
|
|
Question: []dns.Question{
|
|
|
|
{
|
|
|
|
Name: "db.virtual.banana.ns.orange.ap.foo.peer.consul", // "intentionally missing the trailing dot"
|
|
|
|
Qtype: dns.TypeA,
|
|
|
|
Qclass: dns.ClassINET,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedQuery: &discovery.Query{
|
|
|
|
QueryType: discovery.QueryTypeVirtual,
|
|
|
|
QueryPayload: discovery.QueryPayload{
|
|
|
|
Name: "db",
|
|
|
|
Tenancy: discovery.QueryTenancy{
|
|
|
|
Peer: "foo",
|
|
|
|
Namespace: "banana",
|
|
|
|
Partition: "orange",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "test A 'virtual.' with implicit peer",
|
|
|
|
request: &dns.Msg{
|
|
|
|
MsgHdr: dns.MsgHdr{
|
|
|
|
Opcode: dns.OpcodeQuery,
|
|
|
|
},
|
|
|
|
Question: []dns.Question{
|
|
|
|
{
|
|
|
|
Name: "db.virtual.foo.consul", // "intentionally missing the trailing dot"
|
|
|
|
Qtype: dns.TypeA,
|
|
|
|
Qclass: dns.ClassINET,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedQuery: &discovery.Query{
|
|
|
|
QueryType: discovery.QueryTypeVirtual,
|
|
|
|
QueryPayload: discovery.QueryPayload{
|
|
|
|
Name: "db",
|
|
|
|
Tenancy: discovery.QueryTenancy{
|
|
|
|
Peer: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "test A 'virtual.' with implicit peer and namespace query",
|
|
|
|
request: &dns.Msg{
|
|
|
|
MsgHdr: dns.MsgHdr{
|
|
|
|
Opcode: dns.OpcodeQuery,
|
|
|
|
},
|
|
|
|
Question: []dns.Question{
|
|
|
|
{
|
|
|
|
Name: "db.virtual.frontend.foo.consul", // "intentionally missing the trailing dot"
|
|
|
|
Qtype: dns.TypeA,
|
|
|
|
Qclass: dns.ClassINET,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedQuery: &discovery.Query{
|
|
|
|
QueryType: discovery.QueryTypeVirtual,
|
|
|
|
QueryPayload: discovery.QueryPayload{
|
|
|
|
Name: "db",
|
|
|
|
Tenancy: discovery.QueryTenancy{
|
|
|
|
Namespace: "frontend",
|
|
|
|
Peer: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "test A 'workload.'",
|
|
|
|
request: &dns.Msg{
|
|
|
|
MsgHdr: dns.MsgHdr{
|
|
|
|
Opcode: dns.OpcodeQuery,
|
|
|
|
},
|
|
|
|
Question: []dns.Question{
|
|
|
|
{
|
|
|
|
Name: "foo.workload.consul", // "intentionally missing the trailing dot"
|
|
|
|
Qtype: dns.TypeA,
|
|
|
|
Qclass: dns.ClassINET,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedQuery: &discovery.Query{
|
|
|
|
QueryType: discovery.QueryTypeWorkload,
|
|
|
|
QueryPayload: discovery.QueryPayload{
|
|
|
|
Name: "foo",
|
|
|
|
Tenancy: discovery.QueryTenancy{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "test A 'workload.' with all possible labels",
|
|
|
|
request: &dns.Msg{
|
|
|
|
MsgHdr: dns.MsgHdr{
|
|
|
|
Opcode: dns.OpcodeQuery,
|
|
|
|
},
|
|
|
|
Question: []dns.Question{
|
|
|
|
{
|
|
|
|
Name: "api.port.foo.workload.banana.ns.orange.ap.apple.peer.consul", // "intentionally missing the trailing dot"
|
|
|
|
Qtype: dns.TypeA,
|
|
|
|
Qclass: dns.ClassINET,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-02-09 02:56:04 +00:00
|
|
|
requestContext: &Context{
|
2024-04-22 18:30:43 +00:00
|
|
|
DefaultPartition: "default-partition",
|
2024-02-09 02:56:04 +00:00
|
|
|
},
|
2024-02-02 23:29:38 +00:00
|
|
|
expectedQuery: &discovery.Query{
|
|
|
|
QueryType: discovery.QueryTypeWorkload,
|
|
|
|
QueryPayload: discovery.QueryPayload{
|
|
|
|
Name: "foo",
|
|
|
|
PortName: "api",
|
|
|
|
Tenancy: discovery.QueryTenancy{
|
2024-04-22 18:30:43 +00:00
|
|
|
Namespace: "banana",
|
|
|
|
Partition: "orange",
|
|
|
|
Peer: "apple",
|
2024-02-02 23:29:38 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "test sameness group with all possible labels",
|
|
|
|
request: &dns.Msg{
|
|
|
|
MsgHdr: dns.MsgHdr{
|
|
|
|
Opcode: dns.OpcodeQuery,
|
|
|
|
},
|
|
|
|
Question: []dns.Question{
|
|
|
|
{
|
|
|
|
Name: "foo.service.apple.sg.banana.ns.orange.ap.consul", // "intentionally missing the trailing dot"
|
|
|
|
Qtype: dns.TypeA,
|
|
|
|
Qclass: dns.ClassINET,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-02-09 02:56:04 +00:00
|
|
|
requestContext: &Context{
|
2024-04-22 18:30:43 +00:00
|
|
|
DefaultPartition: "default-partition",
|
2024-02-09 02:56:04 +00:00
|
|
|
},
|
2024-02-02 23:29:38 +00:00
|
|
|
expectedQuery: &discovery.Query{
|
|
|
|
QueryType: discovery.QueryTypeService,
|
|
|
|
QueryPayload: discovery.QueryPayload{
|
|
|
|
Name: "foo",
|
|
|
|
Tenancy: discovery.QueryTenancy{
|
|
|
|
Namespace: "banana",
|
|
|
|
Partition: "orange",
|
|
|
|
SamenessGroup: "apple",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2024-01-17 23:46:18 +00:00
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
2024-02-02 23:29:38 +00:00
|
|
|
context := tc.requestContext
|
|
|
|
if context == nil {
|
|
|
|
context = &Context{}
|
|
|
|
}
|
2024-02-03 03:23:52 +00:00
|
|
|
query, err := buildQueryFromDNSMessage(tc.request, *context, "consul.", ".", nil)
|
2024-01-17 23:46:18 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, tc.expectedQuery, query)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|