Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inititial support for multiple targets per record #493

Merged
merged 5 commits into from
Apr 18, 2018
Merged
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
13 changes: 9 additions & 4 deletions endpoint/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,20 @@ type Endpoint struct {
}

// NewEndpoint initialization method to be used to create an endpoint
func NewEndpoint(dnsName, target, recordType string) *Endpoint {
return NewEndpointWithTTL(dnsName, target, recordType, TTL(0))
func NewEndpoint(dnsName, recordType string, targets ...string) *Endpoint {
return NewEndpointWithTTL(dnsName, recordType, TTL(0), targets...)
}

// NewEndpointWithTTL initialization method to be used to create an endpoint with a TTL struct
func NewEndpointWithTTL(dnsName, target, recordType string, ttl TTL) *Endpoint {
func NewEndpointWithTTL(dnsName, recordType string, ttl TTL, targets ...string) *Endpoint {
cleanTargets := make([]string, len(targets))
for idx, target := range targets {
cleanTargets[idx] = strings.TrimSuffix(target, ".")
}

return &Endpoint{
DNSName: strings.TrimSuffix(dnsName, "."),
Targets: Targets{strings.TrimSuffix(target, ".")},
Targets: cleanTargets,
RecordType: recordType,
Labels: NewLabels(),
RecordTTL: ttl,
Expand Down
45 changes: 43 additions & 2 deletions endpoint/endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,57 @@ import (
)

func TestNewEndpoint(t *testing.T) {
e := NewEndpoint("example.org", "foo.com", "CNAME")
e := NewEndpoint("example.org", "CNAME", "foo.com")
if e.DNSName != "example.org" || e.Targets[0] != "foo.com" || e.RecordType != "CNAME" {
t.Error("endpoint is not initialized correctly")
}
if e.Labels == nil {
t.Error("Labels is not initialized")
}

w := NewEndpoint("example.org.", "load-balancer.com.", "")
w := NewEndpoint("example.org.", "", "load-balancer.com.")
if w.DNSName != "example.org" || w.Targets[0] != "load-balancer.com" || w.RecordType != "" {
t.Error("endpoint is not initialized correctly")
}
}

func TestTargetsSame(t *testing.T) {
tests := []Targets{
{""},
{"1.2.3.4"},
{"8.8.8.8", "8.8.4.4"},
}

for _, d := range tests {
if d.Same(d) != true {
t.Errorf("%#v should equal %#v", d, d)
}
}
}

func TestSameFailures(t *testing.T) {
tests := []struct {
a Targets
b Targets
}{
{
[]string{"1.2.3.4"},
[]string{"4.3.2.1"},
}, {
[]string{"1.2.3.4"},
[]string{"1.2.3.4", "4.3.2.1"},
}, {
[]string{"1.2.3.4", "4.3.2.1"},
[]string{"1.2.3.4"},
}, {
[]string{"1.2.3.4", "4.3.2.1"},
[]string{"8.8.8.8", "8.8.4.4"},
},
}

for _, d := range tests {
if d.a.Same(d.b) == true {
t.Errorf("%#v should not equal %#v", d.a, d.b)
}
}
}
20 changes: 13 additions & 7 deletions provider/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,17 @@ func (p *AWSProvider) Records() (endpoints []*endpoint.Endpoint, _ error) {
ttl = endpoint.TTL(*r.TTL)
}

for _, rr := range r.ResourceRecords {
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(wildcardUnescape(aws.StringValue(r.Name)), aws.StringValue(rr.Value), aws.StringValue(r.Type), ttl))
if len(r.ResourceRecords) > 0 {
targets := make([]string, len(r.ResourceRecords))
for idx, rr := range r.ResourceRecords {
targets[idx] = aws.StringValue(rr.Value)
}

endpoints = append(endpoints, endpoint.NewEndpointWithTTL(wildcardUnescape(aws.StringValue(r.Name)), aws.StringValue(r.Type), ttl, targets...))
}

if r.AliasTarget != nil {
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(wildcardUnescape(aws.StringValue(r.Name)), aws.StringValue(r.AliasTarget.DNSName), endpoint.RecordTypeCNAME, ttl))
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(wildcardUnescape(aws.StringValue(r.Name)), endpoint.RecordTypeCNAME, ttl, aws.StringValue(r.AliasTarget.DNSName)))
}
}

Expand Down Expand Up @@ -389,10 +394,11 @@ func newChange(action string, endpoint *endpoint.Endpoint) *route53.Change {
} else {
change.ResourceRecordSet.TTL = aws.Int64(int64(endpoint.RecordTTL))
}
change.ResourceRecordSet.ResourceRecords = []*route53.ResourceRecord{
{
Value: aws.String(endpoint.Targets[0]),
},
change.ResourceRecordSet.ResourceRecords = make([]*route53.ResourceRecord, len(endpoint.Targets))
for idx, val := range endpoint.Targets {
change.ResourceRecordSet.ResourceRecords[idx] = &route53.ResourceRecord{
Value: aws.String(val),
}
}
}

Expand Down
207 changes: 115 additions & 92 deletions provider/aws_test.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion provider/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func (p *AzureProvider) Records() (endpoints []*endpoint.Endpoint, _ error) {
ttl = endpoint.TTL(*recordSet.TTL)
}

ep := endpoint.NewEndpointWithTTL(name, target, recordType, endpoint.TTL(ttl))
ep := endpoint.NewEndpointWithTTL(name, recordType, endpoint.TTL(ttl), target)
log.Debugf(
"Found %s record for '%s' with target '%s'.",
ep.RecordType,
Expand Down
80 changes: 40 additions & 40 deletions provider/azure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ func (client *mockRecordsClient) Delete(resourceGroupName string, zoneName strin
client.deletedEndpoints,
endpoint.NewEndpoint(
formatAzureDNSName(relativeRecordSetName, zoneName),
"",
string(recordType),
"",
),
)
return autorest.Response{}, nil
Expand All @@ -145,9 +145,9 @@ func (client *mockRecordsClient) CreateOrUpdate(resourceGroupName string, zoneNa
client.updatedEndpoints,
endpoint.NewEndpointWithTTL(
formatAzureDNSName(relativeRecordSetName, zoneName),
extractAzureTarget(&parameters),
string(recordType),
ttl,
extractAzureTarget(&parameters),
),
)
return parameters, nil
Expand Down Expand Up @@ -197,11 +197,11 @@ func TestAzureRecord(t *testing.T) {
t.Fatal(err)
}
expected := []*endpoint.Endpoint{
endpoint.NewEndpoint("example.com", "123.123.123.122", endpoint.RecordTypeA),
endpoint.NewEndpoint("example.com", "heritage=external-dns,external-dns/owner=default", endpoint.RecordTypeTXT),
endpoint.NewEndpointWithTTL("nginx.example.com", "123.123.123.123", endpoint.RecordTypeA, 3600),
endpoint.NewEndpointWithTTL("nginx.example.com", "heritage=external-dns,external-dns/owner=default", endpoint.RecordTypeTXT, recordTTL),
endpoint.NewEndpointWithTTL("hack.example.com", "hack.azurewebsites.net", endpoint.RecordTypeCNAME, 10),
endpoint.NewEndpoint("example.com", endpoint.RecordTypeA, "123.123.123.122"),
endpoint.NewEndpoint("example.com", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"),
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeA, 3600, "123.123.123.123"),
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeTXT, recordTTL, "heritage=external-dns,external-dns/owner=default"),
endpoint.NewEndpointWithTTL("hack.example.com", endpoint.RecordTypeCNAME, 10, "hack.azurewebsites.net"),
}

validateAzureEndpoints(t, actual, expected)
Expand All @@ -214,23 +214,23 @@ func TestAzureApplyChanges(t *testing.T) {
testAzureApplyChangesInternal(t, false, &recordsClient)

validateAzureEndpoints(t, recordsClient.deletedEndpoints, []*endpoint.Endpoint{
endpoint.NewEndpoint("old.example.com", "", endpoint.RecordTypeA),
endpoint.NewEndpoint("oldcname.example.com", "", endpoint.RecordTypeCNAME),
endpoint.NewEndpoint("deleted.example.com", "", endpoint.RecordTypeA),
endpoint.NewEndpoint("deletedcname.example.com", "", endpoint.RecordTypeCNAME),
endpoint.NewEndpoint("old.example.com", endpoint.RecordTypeA, ""),
endpoint.NewEndpoint("oldcname.example.com", endpoint.RecordTypeCNAME, ""),
endpoint.NewEndpoint("deleted.example.com", endpoint.RecordTypeA, ""),
endpoint.NewEndpoint("deletedcname.example.com", endpoint.RecordTypeCNAME, ""),
})

validateAzureEndpoints(t, recordsClient.updatedEndpoints, []*endpoint.Endpoint{
endpoint.NewEndpointWithTTL("example.com", "1.2.3.4", endpoint.RecordTypeA, endpoint.TTL(recordTTL)),
endpoint.NewEndpointWithTTL("example.com", "tag", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL)),
endpoint.NewEndpointWithTTL("foo.example.com", "1.2.3.4", endpoint.RecordTypeA, endpoint.TTL(recordTTL)),
endpoint.NewEndpointWithTTL("foo.example.com", "tag", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL)),
endpoint.NewEndpointWithTTL("bar.example.com", "other.com", endpoint.RecordTypeCNAME, endpoint.TTL(recordTTL)),
endpoint.NewEndpointWithTTL("bar.example.com", "tag", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL)),
endpoint.NewEndpointWithTTL("other.com", "5.6.7.8", endpoint.RecordTypeA, endpoint.TTL(recordTTL)),
endpoint.NewEndpointWithTTL("other.com", "tag", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL)),
endpoint.NewEndpointWithTTL("new.example.com", "111.222.111.222", endpoint.RecordTypeA, 3600),
endpoint.NewEndpointWithTTL("newcname.example.com", "other.com", endpoint.RecordTypeCNAME, 10),
endpoint.NewEndpointWithTTL("example.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4"),
endpoint.NewEndpointWithTTL("example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4"),
endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
endpoint.NewEndpointWithTTL("bar.example.com", endpoint.RecordTypeCNAME, endpoint.TTL(recordTTL), "other.com"),
endpoint.NewEndpointWithTTL("bar.example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
endpoint.NewEndpointWithTTL("other.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "5.6.7.8"),
endpoint.NewEndpointWithTTL("other.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeA, 3600, "111.222.111.222"),
endpoint.NewEndpointWithTTL("newcname.example.com", endpoint.RecordTypeCNAME, 10, "other.com"),
})
}

Expand Down Expand Up @@ -262,33 +262,33 @@ func testAzureApplyChangesInternal(t *testing.T, dryRun bool, client RecordsClie
)

createRecords := []*endpoint.Endpoint{
endpoint.NewEndpoint("example.com", "1.2.3.4", endpoint.RecordTypeA),
endpoint.NewEndpoint("example.com", "tag", endpoint.RecordTypeTXT),
endpoint.NewEndpoint("foo.example.com", "1.2.3.4", endpoint.RecordTypeA),
endpoint.NewEndpoint("foo.example.com", "tag", endpoint.RecordTypeTXT),
endpoint.NewEndpoint("bar.example.com", "other.com", endpoint.RecordTypeCNAME),
endpoint.NewEndpoint("bar.example.com", "tag", endpoint.RecordTypeTXT),
endpoint.NewEndpoint("other.com", "5.6.7.8", endpoint.RecordTypeA),
endpoint.NewEndpoint("other.com", "tag", endpoint.RecordTypeTXT),
endpoint.NewEndpoint("nope.com", "4.4.4.4", endpoint.RecordTypeA),
endpoint.NewEndpoint("nope.com", "tag", endpoint.RecordTypeTXT),
endpoint.NewEndpoint("example.com", endpoint.RecordTypeA, "1.2.3.4"),
endpoint.NewEndpoint("example.com", endpoint.RecordTypeTXT, "tag"),
endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeA, "1.2.3.4"),
endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeTXT, "tag"),
endpoint.NewEndpoint("bar.example.com", endpoint.RecordTypeCNAME, "other.com"),
endpoint.NewEndpoint("bar.example.com", endpoint.RecordTypeTXT, "tag"),
endpoint.NewEndpoint("other.com", endpoint.RecordTypeA, "5.6.7.8"),
endpoint.NewEndpoint("other.com", endpoint.RecordTypeTXT, "tag"),
endpoint.NewEndpoint("nope.com", endpoint.RecordTypeA, "4.4.4.4"),
endpoint.NewEndpoint("nope.com", endpoint.RecordTypeTXT, "tag"),
}

currentRecords := []*endpoint.Endpoint{
endpoint.NewEndpoint("old.example.com", "121.212.121.212", endpoint.RecordTypeA),
endpoint.NewEndpoint("oldcname.example.com", "other.com", endpoint.RecordTypeCNAME),
endpoint.NewEndpoint("old.nope.com", "121.212.121.212", endpoint.RecordTypeA),
endpoint.NewEndpoint("old.example.com", endpoint.RecordTypeA, "121.212.121.212"),
endpoint.NewEndpoint("oldcname.example.com", endpoint.RecordTypeCNAME, "other.com"),
endpoint.NewEndpoint("old.nope.com", endpoint.RecordTypeA, "121.212.121.212"),
}
updatedRecords := []*endpoint.Endpoint{
endpoint.NewEndpointWithTTL("new.example.com", "111.222.111.222", endpoint.RecordTypeA, 3600),
endpoint.NewEndpointWithTTL("newcname.example.com", "other.com", endpoint.RecordTypeCNAME, 10),
endpoint.NewEndpoint("new.nope.com", "222.111.222.111", endpoint.RecordTypeA),
endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeA, 3600, "111.222.111.222"),
endpoint.NewEndpointWithTTL("newcname.example.com", endpoint.RecordTypeCNAME, 10, "other.com"),
endpoint.NewEndpoint("new.nope.com", endpoint.RecordTypeA, "222.111.222.111"),
}

deleteRecords := []*endpoint.Endpoint{
endpoint.NewEndpoint("deleted.example.com", "111.222.111.222", endpoint.RecordTypeA),
endpoint.NewEndpoint("deletedcname.example.com", "other.com", endpoint.RecordTypeCNAME),
endpoint.NewEndpoint("deleted.nope.com", "222.111.222.111", endpoint.RecordTypeA),
endpoint.NewEndpoint("deleted.example.com", endpoint.RecordTypeA, "111.222.111.222"),
endpoint.NewEndpoint("deletedcname.example.com", endpoint.RecordTypeCNAME, "other.com"),
endpoint.NewEndpoint("deleted.nope.com", endpoint.RecordTypeA, "222.111.222.111"),
}

changes := &plan.Changes{
Expand Down
2 changes: 1 addition & 1 deletion provider/cloudflare.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func (p *CloudFlareProvider) Records() ([]*endpoint.Endpoint, error) {

for _, r := range records {
if supportedRecordType(r.Type) {
endpoints = append(endpoints, endpoint.NewEndpoint(r.Name, r.Content, r.Type))
endpoints = append(endpoints, endpoint.NewEndpoint(r.Name, r.Type, r.Content))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion provider/designate.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ func (p designateProvider) Records() ([]*endpoint.Endpoint, error) {
return nil
}
for _, record := range recordSet.Records {
ep := endpoint.NewEndpoint(recordSet.Name, record, recordSet.Type)
ep := endpoint.NewEndpoint(recordSet.Name, recordSet.Type, record)
ep.Labels[designateRecordSetID] = recordSet.ID
ep.Labels[designateZoneID] = recordSet.ZoneID
ep.Labels[designateOriginalRecords] = strings.Join(recordSet.Records, "\000")
Expand Down
2 changes: 1 addition & 1 deletion provider/digital_ocean.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (p *DigitalOceanProvider) Records() ([]*endpoint.Endpoint, error) {
name = zone.Name
}

endpoints = append(endpoints, endpoint.NewEndpoint(name, r.Data, r.Type))
endpoints = append(endpoints, endpoint.NewEndpoint(name, r.Type, r.Data))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion provider/dnsimple.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func (p *dnsimpleProvider) Records() (endpoints []*endpoint.Endpoint, _ error) {
default:
continue
}
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(record.Name+"."+record.ZoneID, record.Content, record.Type, endpoint.TTL(record.TTL)))
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(record.Name+"."+record.ZoneID, record.Type, endpoint.TTL(record.TTL), record.Content))
}
page++
if page > records.Pagination.TotalPages {
Expand Down
16 changes: 8 additions & 8 deletions provider/dyn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ func TestDyn_endpointToRecord(t *testing.T) {
ep *endpoint.Endpoint
extractor func(*dynect.DataBlock) string
}{
{endpoint.NewEndpoint("address", "the-target", "A"), func(b *dynect.DataBlock) string { return b.Address }},
{endpoint.NewEndpoint("cname", "the-target", "CNAME"), func(b *dynect.DataBlock) string { return b.CName }},
{endpoint.NewEndpoint("text", "the-target", "TXT"), func(b *dynect.DataBlock) string { return b.TxtData }},
{endpoint.NewEndpoint("address", "A", "the-target"), func(b *dynect.DataBlock) string { return b.Address }},
{endpoint.NewEndpoint("cname", "CNAME", "the-target"), func(b *dynect.DataBlock) string { return b.CName }},
{endpoint.NewEndpoint("text", "TXT", "the-target"), func(b *dynect.DataBlock) string { return b.TxtData }},
}

for _, tc := range tests {
Expand All @@ -213,11 +213,11 @@ func TestDyn_buildLinkToRecord(t *testing.T) {
ep *endpoint.Endpoint
link string
}{
{endpoint.NewEndpoint("sub.the-target.example.com", "address", "A"), "ARecord/example.com/sub.the-target.example.com/"},
{endpoint.NewEndpoint("the-target.example.com", "cname", "CNAME"), "CNAMERecord/example.com/the-target.example.com/"},
{endpoint.NewEndpoint("the-target.example.com", "text", "TXT"), "TXTRecord/example.com/the-target.example.com/"},
{endpoint.NewEndpoint("the-target.google.com", "text", "TXT"), ""},
{endpoint.NewEndpoint("mail.example.com", "text", "TXT"), ""},
{endpoint.NewEndpoint("sub.the-target.example.com", "A", "address"), "ARecord/example.com/sub.the-target.example.com/"},
{endpoint.NewEndpoint("the-target.example.com", "CNAME", "cname"), "CNAMERecord/example.com/the-target.example.com/"},
{endpoint.NewEndpoint("the-target.example.com", "TXT", "text"), "TXTRecord/example.com/the-target.example.com/"},
{endpoint.NewEndpoint("the-target.google.com", "TXT", "text"), ""},
{endpoint.NewEndpoint("mail.example.com", "TXT", "text"), ""},
{nil, ""},
}

Expand Down
Loading