Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions internal/designate/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package provider

import (
"context"
"external-dns-openstack-webhook/internal/designate/client"
"fmt"
"strings"

Expand All @@ -31,8 +32,6 @@ import (
"sigs.k8s.io/external-dns/provider"
)

import "external-dns-openstack-webhook/internal/designate/client"

const (
// ID of the RecordSet from which endpoint was created
designateRecordSetID = "designate-recordset-id"
Expand Down Expand Up @@ -72,10 +71,23 @@ func NewDesignateProvider(domainFilter endpoint.DomainFilter, dryRun bool) (prov
func canonicalizeDomainNames(domains []string) []string {
var cDomains []string
for _, d := range domains {
if !strings.HasSuffix(d, ".") {
d += "."
cDomains = append(cDomains, strings.ToLower(d))
cDomains = append(cDomains, canonicalizeDomainName(d))
}
return cDomains
}

func canonicalizeDomainNamesForMX(domains []string) []string {
var cDomains []string

for _, d := range domains {
parts := strings.Split(d, " ")
if len(parts) == 2 {
// If the format does not conform to the expected one, play it safe and just pass the value on.
// Otherwise, canonicalize the hostname.
d = fmt.Sprintf("%s %s", parts[0], canonicalizeDomainName(parts[1]))
}

cDomains = append(cDomains, canonicalizeDomainName(d))
}
return cDomains
}
Expand Down Expand Up @@ -116,7 +128,7 @@ func getHostZoneID(hostname string, managedZones map[string]string) string {
resultID := ""

for zoneID, zoneName := range managedZones {
if !strings.HasSuffix(hostname, "." + zoneName) && hostname != zoneName {
if !strings.HasSuffix(hostname, "."+zoneName) && hostname != zoneName {
continue
}
ln := len(zoneName)
Expand All @@ -139,7 +151,7 @@ func (p designateProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, e
for zoneID := range managedZones {
err = p.client.ForEachRecordSet(ctx, zoneID,
func(recordSet *recordsets.RecordSet) error {
if recordSet.Type != endpoint.RecordTypeA && recordSet.Type != endpoint.RecordTypeTXT && recordSet.Type != endpoint.RecordTypeCNAME {
if !p.supportedRecordType(recordSet.Type) {
return nil
}

Expand All @@ -160,6 +172,15 @@ func (p designateProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, e
return result, nil
}

func (p designateProvider) supportedRecordType(recordType string) bool {
switch recordType {
case endpoint.RecordTypeA, endpoint.RecordTypeTXT, endpoint.RecordTypeCNAME, endpoint.RecordTypeNS, endpoint.RecordTypeMX:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this will need further adjustment as I noticed we don't even support all record types supported by external-dns (https://github.com/kubernetes-sigs/external-dns/blob/e22cd737cd666db7394df506cd3f1a596a57a184/endpoint/endpoint.go#L32-L65 ?).

Not your fault and not part of the change, but since I just looked a little closer at the code, this really needs fixing.

I recently also fiddled with the proper format of SRV records emitted by external-dns itself, see
kubernetes-sigs/external-dns@fde978f, but there is not even SRV support in this webhook provider yet.

After all, adding support for more records types can also happen after your MR is merged.

return true
default:
return false
}
}

// temporary structure to hold recordset parameters so that we could aggregate endpoints into recordsets
type recordSet struct {
dnsName string
Expand Down Expand Up @@ -197,9 +218,12 @@ func addEndpoint(ep *endpoint.Endpoint, recordSets map[string]*recordSet, oldEnd
}
}
targets := ep.Targets
if ep.RecordType == endpoint.RecordTypeCNAME {
if ep.RecordType == endpoint.RecordTypeCNAME || ep.RecordType == endpoint.RecordTypeNS {
targets = canonicalizeDomainNames(targets)
}
if ep.RecordType == endpoint.RecordTypeMX {
targets = canonicalizeDomainNamesForMX(targets)
}
for _, t := range targets {
rs.names[t] = !delete
}
Expand Down
46 changes: 45 additions & 1 deletion internal/designate/provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,6 @@ func testDesignateCreateRecords(t *testing.T, client *fakeDesignateClient) []*re
TTL: 60,
Type: endpoint.RecordTypeTXT,
})

if err != nil {
t.Fatal("failed to prefill records")
}
Expand Down Expand Up @@ -452,6 +451,18 @@ func testDesignateCreateRecords(t *testing.T, client *fakeDesignateClient) []*re
Targets: endpoint.Targets{"sql.test.net"},
Labels: map[string]string{},
},
{
DNSName: "ns.test.net",
RecordType: endpoint.RecordTypeNS,
Targets: endpoint.Targets{"ns1.test.net", "ns2.test.net", "ns3.test.net"},
Labels: map[string]string{},
},
{
DNSName: "mx.test.net",
RecordType: endpoint.RecordTypeMX,
Targets: endpoint.Targets{"10 mx1.test.net", "100 mx2.test.net"},
Labels: map[string]string{},
},
}
expected := []*recordsets.RecordSet{
{
Expand Down Expand Up @@ -485,6 +496,18 @@ func testDesignateCreateRecords(t *testing.T, client *fakeDesignateClient) []*re
Records: []string{"sql.test.net."},
ZoneID: "zone-2",
},
{
Name: "ns.test.net.",
Type: endpoint.RecordTypeNS,
Records: []string{"ns1.test.net.", "ns2.test.net.", "ns3.test.net."},
ZoneID: "zone-2",
},
{
Name: "mx.test.net.",
Type: endpoint.RecordTypeMX,
Records: []string{"10 mx1.test.net.", "100 mx2.test.net."},
ZoneID: "zone-2",
},
}
expectedCopy := make([]*recordsets.RecordSet, len(expected))
copy(expectedCopy, expected)
Expand Down Expand Up @@ -550,6 +573,16 @@ func testDesignateUpdateRecords(t *testing.T, client *fakeDesignateClient) []*re
designateOriginalRecords: "10.2.1.1\00010.2.1.2",
},
},
{
DNSName: "ns.test.net.",
RecordType: endpoint.RecordTypeNS,
Targets: endpoint.Targets{"ns1.test.net", "ns2.test.net", "ns3.test.net"},
Labels: map[string]string{
designateZoneID: "zone-2",
designateRecordSetID: expected[5].ID,
designateOriginalRecords: "ns1.test.net.\000ns2.test.net.\000ns3.test.net.",
},
},
}
updatesNew := []*endpoint.Endpoint{
{
Expand All @@ -573,13 +606,24 @@ func testDesignateUpdateRecords(t *testing.T, client *fakeDesignateClient) []*re
designateOriginalRecords: "10.2.1.1\00010.2.1.2",
},
},
{
DNSName: "ns.test.net.",
RecordType: endpoint.RecordTypeNS,
Targets: endpoint.Targets{"ns1.test.invalid", "ns2.test.invalid", "ns3.test.invalid"},
Labels: map[string]string{
designateZoneID: "zone-2",
designateRecordSetID: expected[5].ID,
designateOriginalRecords: "ns1.test.net.\000ns2.test.net.\000ns3.test.net.",
},
},
}
expectedCopy := make([]*recordsets.RecordSet, len(expected))
copy(expectedCopy, expected)

expected[2].Records = []string{"10.3.3.1"}
expected[2].TTL = 60
expected[3].Records = []string{"10.2.1.1", "10.3.3.2"}
expected[5].Records = []string{"ns1.test.invalid.", "ns2.test.invalid.", "ns3.test.invalid."}

err := client.ToProvider().ApplyChanges(context.Background(), &plan.Changes{UpdateOld: updatesOld, UpdateNew: updatesNew})
if err != nil {
Expand Down