mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 17:46:57 +02:00
fix(aws): correctly populate target health check on existing records
This commit is contained in:
parent
7dbd6b0fa9
commit
f21f45b15d
@ -151,8 +151,21 @@ func NewEndpointWithTTL(dnsName, recordType string, ttl TTL, targets ...string)
|
||||
}
|
||||
}
|
||||
|
||||
// WithProviderSpecific attaches a key/value pair to the Endpoint and returns the Endpoint.
|
||||
// This can be used to pass additional data through the stages of ExternalDNS's Endpoint processing.
|
||||
// The assumption is that most of the time this will be provider specific metadata that doesn't
|
||||
// warrant its own field on the Endpoint object itself. It differs from Labels in the fact that it's
|
||||
// not persisted in the Registry but only kept in memory during a single record synchronization.
|
||||
func (e *Endpoint) WithProviderSpecific(key, value string) *Endpoint {
|
||||
if e.ProviderSpecific == nil {
|
||||
e.ProviderSpecific = ProviderSpecific{}
|
||||
}
|
||||
e.ProviderSpecific[key] = value
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Endpoint) String() string {
|
||||
return fmt.Sprintf("%s %d IN %s %s", e.DNSName, e.RecordTTL, e.RecordType, e.Targets)
|
||||
return fmt.Sprintf("%s %d IN %s %s %s", e.DNSName, e.RecordTTL, e.RecordType, e.Targets, e.ProviderSpecific)
|
||||
}
|
||||
|
||||
// DNSEndpointSpec defines the desired state of DNSEndpoint
|
||||
|
@ -48,7 +48,8 @@ func (b byAllFields) Less(i, j int) bool {
|
||||
func SameEndpoint(a, b *endpoint.Endpoint) bool {
|
||||
return a.DNSName == b.DNSName && a.Targets.Same(b.Targets) && a.RecordType == b.RecordType &&
|
||||
a.Labels[endpoint.OwnerLabelKey] == b.Labels[endpoint.OwnerLabelKey] && a.RecordTTL == b.RecordTTL &&
|
||||
a.Labels[endpoint.ResourceLabelKey] == b.Labels[endpoint.ResourceLabelKey]
|
||||
a.Labels[endpoint.ResourceLabelKey] == b.Labels[endpoint.ResourceLabelKey] &&
|
||||
SameMap(a.ProviderSpecific, b.ProviderSpecific)
|
||||
}
|
||||
|
||||
// SameEndpoints compares two slices of endpoints regardless of order
|
||||
@ -79,3 +80,18 @@ func SamePlanChanges(a, b map[string][]*endpoint.Endpoint) bool {
|
||||
return SameEndpoints(a["Create"], b["Create"]) && SameEndpoints(a["Delete"], b["Delete"]) &&
|
||||
SameEndpoints(a["UpdateOld"], b["UpdateOld"]) && SameEndpoints(a["UpdateNew"], b["UpdateNew"])
|
||||
}
|
||||
|
||||
// SameMap verifies that two maps contain the same string/string key/value pairs
|
||||
func SameMap(a, b map[string]string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
for k, v := range a {
|
||||
if v != b[k] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -55,16 +55,22 @@ func ExampleSameEndpoints() {
|
||||
RecordType: "CNAME",
|
||||
RecordTTL: endpoint.TTL(60),
|
||||
},
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Targets: endpoint.Targets{"load-balancer.org"},
|
||||
ProviderSpecific: endpoint.ProviderSpecific{"foo": "bar"},
|
||||
},
|
||||
}
|
||||
sort.Sort(byAllFields(eps))
|
||||
for _, ep := range eps {
|
||||
fmt.Println(ep)
|
||||
}
|
||||
// Output:
|
||||
// abc.com 0 IN A 1.2.3.4
|
||||
// abc.com 0 IN TXT something
|
||||
// bbc.com 0 IN CNAME foo.com
|
||||
// cbc.com 60 IN CNAME foo.com
|
||||
// example.org 0 IN load-balancer.org
|
||||
// example.org 0 IN TXT load-balancer.org
|
||||
// abc.com 0 IN A 1.2.3.4 map[]
|
||||
// abc.com 0 IN TXT something map[]
|
||||
// bbc.com 0 IN CNAME foo.com map[]
|
||||
// cbc.com 60 IN CNAME foo.com map[]
|
||||
// example.org 0 IN load-balancer.org map[]
|
||||
// example.org 0 IN load-balancer.org map[foo:bar]
|
||||
// example.org 0 IN TXT load-balancer.org map[]
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ import (
|
||||
|
||||
const (
|
||||
recordTTL = 300
|
||||
// provider specific key that designates whether an AWS ALIAS record has the EvaluateTargetHealth
|
||||
// field set to true.
|
||||
providerSpecificEvaluateTargetHealth = "aws/evaluate-target-health"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -227,7 +230,10 @@ func (p *AWSProvider) Records() (endpoints []*endpoint.Endpoint, _ error) {
|
||||
}
|
||||
|
||||
if r.AliasTarget != nil {
|
||||
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(wildcardUnescape(aws.StringValue(r.Name)), endpoint.RecordTypeCNAME, ttl, aws.StringValue(r.AliasTarget.DNSName)))
|
||||
ep := endpoint.
|
||||
NewEndpointWithTTL(wildcardUnescape(aws.StringValue(r.Name)), endpoint.RecordTypeCNAME, ttl, aws.StringValue(r.AliasTarget.DNSName)).
|
||||
WithProviderSpecific(providerSpecificEvaluateTargetHealth, fmt.Sprintf("%t", aws.BoolValue(r.AliasTarget.EvaluateTargetHealth)))
|
||||
endpoints = append(endpoints, ep)
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,11 +365,16 @@ func (p *AWSProvider) newChange(action string, endpoint *endpoint.Endpoint) *rou
|
||||
}
|
||||
|
||||
if isAWSLoadBalancer(endpoint) {
|
||||
evalTargetHealth := p.evaluateTargetHealth
|
||||
if _, ok := endpoint.ProviderSpecific[providerSpecificEvaluateTargetHealth]; ok {
|
||||
evalTargetHealth = endpoint.ProviderSpecific[providerSpecificEvaluateTargetHealth] == "true"
|
||||
}
|
||||
|
||||
change.ResourceRecordSet.Type = aws.String(route53.RRTypeA)
|
||||
change.ResourceRecordSet.AliasTarget = &route53.AliasTarget{
|
||||
DNSName: aws.String(endpoint.Targets[0]),
|
||||
HostedZoneId: aws.String(canonicalHostedZone(endpoint.Targets[0])),
|
||||
EvaluateTargetHealth: aws.Bool(p.evaluateTargetHealth),
|
||||
EvaluateTargetHealth: aws.Bool(evalTargetHealth),
|
||||
}
|
||||
} else {
|
||||
change.ResourceRecordSet.Type = aws.String(endpoint.RecordType)
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/route53"
|
||||
@ -31,7 +32,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -249,12 +249,13 @@ func TestAWSZones(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAWSRecords(t *testing.T) {
|
||||
provider, _ := newAWSProvider(t, NewDomainFilter([]string{"ext-dns-test-2.teapot.zalan.do."}), NewZoneIDFilter([]string{}), NewZoneTypeFilter(""), defaultEvaluateTargetHealth, false, []*endpoint.Endpoint{
|
||||
provider, _ := newAWSProvider(t, NewDomainFilter([]string{"ext-dns-test-2.teapot.zalan.do."}), NewZoneIDFilter([]string{}), NewZoneTypeFilter(""), false, false, []*endpoint.Endpoint{
|
||||
endpoint.NewEndpointWithTTL("list-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4"),
|
||||
endpoint.NewEndpointWithTTL("list-test.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8"),
|
||||
endpoint.NewEndpointWithTTL("*.wildcard-test.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8"),
|
||||
endpoint.NewEndpoint("list-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com"),
|
||||
endpoint.NewEndpoint("*.wildcard-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com"),
|
||||
endpoint.NewEndpoint("list-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false"),
|
||||
endpoint.NewEndpoint("*.wildcard-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false"),
|
||||
endpoint.NewEndpoint("list-test-alias-evaluate.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true"),
|
||||
endpoint.NewEndpointWithTTL("list-test-multiple.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8", "8.8.4.4"),
|
||||
})
|
||||
|
||||
@ -265,8 +266,9 @@ func TestAWSRecords(t *testing.T) {
|
||||
endpoint.NewEndpointWithTTL("list-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4"),
|
||||
endpoint.NewEndpointWithTTL("list-test.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8"),
|
||||
endpoint.NewEndpointWithTTL("*.wildcard-test.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8"),
|
||||
endpoint.NewEndpoint("list-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com"),
|
||||
endpoint.NewEndpoint("*.wildcard-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com"),
|
||||
endpoint.NewEndpoint("list-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false"),
|
||||
endpoint.NewEndpoint("*.wildcard-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false"),
|
||||
endpoint.NewEndpoint("list-test-alias-evaluate.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true"),
|
||||
endpoint.NewEndpointWithTTL("list-test-multiple.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8", "8.8.4.4"),
|
||||
})
|
||||
}
|
||||
@ -336,12 +338,12 @@ func TestAWSDeleteRecords(t *testing.T) {
|
||||
endpoint.NewEndpointWithTTL("delete-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4"),
|
||||
endpoint.NewEndpointWithTTL("delete-test.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8"),
|
||||
endpoint.NewEndpointWithTTL("delete-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, endpoint.TTL(recordTTL), "baz.elb.amazonaws.com"),
|
||||
endpoint.NewEndpoint("delete-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com"),
|
||||
endpoint.NewEndpoint("delete-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com"),
|
||||
endpoint.NewEndpoint("delete-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false"),
|
||||
endpoint.NewEndpoint("delete-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true"),
|
||||
endpoint.NewEndpointWithTTL("delete-test-multiple.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8", "8.8.4.4"),
|
||||
}
|
||||
|
||||
provider, _ := newAWSProvider(t, NewDomainFilter([]string{"ext-dns-test-2.teapot.zalan.do."}), NewZoneIDFilter([]string{}), NewZoneTypeFilter(""), defaultEvaluateTargetHealth, false, originalEndpoints)
|
||||
provider, _ := newAWSProvider(t, NewDomainFilter([]string{"ext-dns-test-2.teapot.zalan.do."}), NewZoneIDFilter([]string{}), NewZoneTypeFilter(""), false, false, originalEndpoints)
|
||||
|
||||
require.NoError(t, provider.DeleteRecords(originalEndpoints))
|
||||
|
||||
@ -764,14 +766,22 @@ func TestAWSCreateRecordsWithCNAME(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAWSCreateRecordsWithALIAS(t *testing.T) {
|
||||
for _, evaluateTargetHealth := range []bool{
|
||||
true,
|
||||
false,
|
||||
for key, evaluateTargetHealth := range map[string]bool{
|
||||
"true": true,
|
||||
"false": false,
|
||||
"": false,
|
||||
} {
|
||||
provider, _ := newAWSProvider(t, NewDomainFilter([]string{"ext-dns-test-2.teapot.zalan.do."}), NewZoneIDFilter([]string{}), NewZoneTypeFilter(""), evaluateTargetHealth, false, []*endpoint.Endpoint{})
|
||||
provider, _ := newAWSProvider(t, NewDomainFilter([]string{"ext-dns-test-2.teapot.zalan.do."}), NewZoneIDFilter([]string{}), NewZoneTypeFilter(""), defaultEvaluateTargetHealth, false, []*endpoint.Endpoint{})
|
||||
|
||||
records := []*endpoint.Endpoint{
|
||||
{DNSName: "create-test.zone-1.ext-dns-test-2.teapot.zalan.do", Targets: endpoint.Targets{"foo.eu-central-1.elb.amazonaws.com"}, RecordType: endpoint.RecordTypeCNAME},
|
||||
{
|
||||
DNSName: "create-test.zone-1.ext-dns-test-2.teapot.zalan.do",
|
||||
Targets: endpoint.Targets{"foo.eu-central-1.elb.amazonaws.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
ProviderSpecific: endpoint.ProviderSpecific{
|
||||
providerSpecificEvaluateTargetHealth: key,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
require.NoError(t, provider.CreateRecords(records))
|
||||
|
Loading…
Reference in New Issue
Block a user