fix: append dot to recordName and target as required by RFC 2782

According to RFC2782 [1], SRV records are to be fully-qualified,
ending with a final dot. Most providers are liberal, but e.g. OpenStack
Designate expects the record name and targets to end with a dot ([2])

[1] https://datatracker.ietf.org/doc/html/rfc2782
[2] https://github.com/openstack/designate

Signed-off-by: Christian Rohmann <christian.rohmann@inovex.de>
This commit is contained in:
Christian Rohmann 2025-06-16 23:56:49 +02:00
parent 051c900d1c
commit 5ff2b6dd7e
2 changed files with 12 additions and 11 deletions

View File

@ -35,6 +35,7 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"sigs.k8s.io/external-dns/provider"
"sigs.k8s.io/external-dns/source/informers"
"sigs.k8s.io/external-dns/source/annotations"
@ -719,7 +720,7 @@ func (sc *serviceSource) extractNodePortEndpoints(svc *v1.Service, hostname stri
// see https://en.wikipedia.org/wiki/SRV_record
// build a target with a priority of 0, weight of 50, and pointing the given port on the given host
target := fmt.Sprintf("0 50 %d %s", port.NodePort, hostname)
target := fmt.Sprintf("0 50 %d %s", port.NodePort, provider.EnsureTrailingDot(hostname))
// take the service name from the K8s Service object
// it is safe to use since it is DNS compatible
@ -732,7 +733,7 @@ func (sc *serviceSource) extractNodePortEndpoints(svc *v1.Service, hostname stri
protocol = "tcp"
}
recordName := fmt.Sprintf("_%s._%s.%s", serviceName, protocol, hostname)
recordName := fmt.Sprintf("_%s._%s.%s", serviceName, protocol, provider.EnsureTrailingDot(hostname))
var ep *endpoint.Endpoint
if ttl.IsConfigured() {

View File

@ -1718,7 +1718,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
},
expected: []*endpoint.Endpoint{
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "_foo._tcp.foo.example.org.", Targets: endpoint.Targets{"0 50 30192 foo.example.org."}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
},
@ -1789,7 +1789,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
svcTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeCluster,
fqdnTemplate: "{{.Name}}.bar.example.com",
expected: []*endpoint.Endpoint{
{DNSName: "_foo._tcp.foo.bar.example.com", Targets: endpoint.Targets{"0 50 30192 foo.bar.example.com"}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "_foo._tcp.foo.bar.example.com.", Targets: endpoint.Targets{"0 50 30192 foo.bar.example.com."}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "foo.bar.example.com", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
{DNSName: "foo.bar.example.com", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
},
@ -1827,7 +1827,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
},
expected: []*endpoint.Endpoint{
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "_foo._tcp.foo.example.org.", Targets: endpoint.Targets{"0 50 30192 foo.example.org."}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
},
@ -1863,7 +1863,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
},
expected: []*endpoint.Endpoint{
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "_foo._tcp.foo.example.org.", Targets: endpoint.Targets{"0 50 30192 foo.example.org."}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
},
@ -1907,7 +1907,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
},
expected: []*endpoint.Endpoint{
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "_foo._tcp.foo.example.org.", Targets: endpoint.Targets{"0 50 30192 foo.example.org."}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
},
@ -1954,7 +1954,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
},
expected: []*endpoint.Endpoint{
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "_foo._tcp.foo.example.org.", Targets: endpoint.Targets{"0 50 30192 foo.example.org."}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA},
},
nodes: []*v1.Node{{
@ -1998,7 +1998,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
},
expected: []*endpoint.Endpoint{
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "_foo._tcp.foo.example.org.", Targets: endpoint.Targets{"0 50 30192 foo.example.org."}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA},
},
nodes: []*v1.Node{{
@ -2054,7 +2054,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
accessAnnotationKey: "private",
},
expected: []*endpoint.Endpoint{
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "_foo._tcp.foo.example.org.", Targets: endpoint.Targets{"0 50 30192 foo.example.org."}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
},
@ -2094,7 +2094,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
accessAnnotationKey: "public",
},
expected: []*endpoint.Endpoint{
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "_foo._tcp.foo.example.org.", Targets: endpoint.Targets{"0 50 30192 foo.example.org."}, RecordType: endpoint.RecordTypeSRV},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
},