mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 17:46:57 +02:00
feat(aws): add support for geoproximity routing (#5347)
* feat(aws): add support for geoproximity routing * remove the invalid test * make some changes based on review comments * fix linting errors * make changes based on review feedback * add more tests to get better coverage * update docs * make the linter happy * address review feedback This commit addresses the review feedback by making the following changes: - use a more object-oriented approach for geoProximity handling - change log levels to warnings instead of errors - add more test cases for geoProximity * fix linting error * use shorter annotation names
This commit is contained in:
parent
dfb64ae813
commit
d79dd835af
@ -894,6 +894,11 @@ For any given DNS name, only **one** of the following routing policies can be us
|
|||||||
- `external-dns.alpha.kubernetes.io/aws-geolocation-continent-code`
|
- `external-dns.alpha.kubernetes.io/aws-geolocation-continent-code`
|
||||||
- `external-dns.alpha.kubernetes.io/aws-geolocation-country-code`
|
- `external-dns.alpha.kubernetes.io/aws-geolocation-country-code`
|
||||||
- `external-dns.alpha.kubernetes.io/aws-geolocation-subdivision-code`
|
- `external-dns.alpha.kubernetes.io/aws-geolocation-subdivision-code`
|
||||||
|
- Geoproximity routing:
|
||||||
|
- `external-dns.alpha.kubernetes.io/aws-geoproximity-region`
|
||||||
|
- `external-dns.alpha.kubernetes.io/aws-geoproximity-local-zone-group`
|
||||||
|
- `external-dns.alpha.kubernetes.io/aws-geoproximity-coordinates`
|
||||||
|
- `external-dns.alpha.kubernetes.io/aws-geoproximity-bias`
|
||||||
- Multi-value answer:`external-dns.alpha.kubernetes.io/aws-multi-value-answer`
|
- Multi-value answer:`external-dns.alpha.kubernetes.io/aws-multi-value-answer`
|
||||||
|
|
||||||
### Associating DNS records with healthchecks
|
### Associating DNS records with healthchecks
|
||||||
|
@ -53,19 +53,27 @@ const (
|
|||||||
// providerSpecificEvaluateTargetHealth specifies whether an AWS ALIAS record
|
// providerSpecificEvaluateTargetHealth specifies whether an AWS ALIAS record
|
||||||
// has the EvaluateTargetHealth field set to true. Present iff the endpoint
|
// has the EvaluateTargetHealth field set to true. Present iff the endpoint
|
||||||
// has a `providerSpecificAlias` value of `true`.
|
// has a `providerSpecificAlias` value of `true`.
|
||||||
providerSpecificEvaluateTargetHealth = "aws/evaluate-target-health"
|
providerSpecificEvaluateTargetHealth = "aws/evaluate-target-health"
|
||||||
providerSpecificWeight = "aws/weight"
|
providerSpecificWeight = "aws/weight"
|
||||||
providerSpecificRegion = "aws/region"
|
providerSpecificRegion = "aws/region"
|
||||||
providerSpecificFailover = "aws/failover"
|
providerSpecificFailover = "aws/failover"
|
||||||
providerSpecificGeolocationContinentCode = "aws/geolocation-continent-code"
|
providerSpecificGeolocationContinentCode = "aws/geolocation-continent-code"
|
||||||
providerSpecificGeolocationCountryCode = "aws/geolocation-country-code"
|
providerSpecificGeolocationCountryCode = "aws/geolocation-country-code"
|
||||||
providerSpecificGeolocationSubdivisionCode = "aws/geolocation-subdivision-code"
|
providerSpecificGeolocationSubdivisionCode = "aws/geolocation-subdivision-code"
|
||||||
providerSpecificMultiValueAnswer = "aws/multi-value-answer"
|
providerSpecificGeoProximityLocationAWSRegion = "aws/geoproximity-region"
|
||||||
providerSpecificHealthCheckID = "aws/health-check-id"
|
providerSpecificGeoProximityLocationBias = "aws/geoproximity-bias"
|
||||||
sameZoneAlias = "same-zone"
|
providerSpecificGeoProximityLocationCoordinates = "aws/geoproximity-coordinates"
|
||||||
|
providerSpecificGeoProximityLocationLocalZoneGroup = "aws/geoproximity-local-zone-group"
|
||||||
|
providerSpecificMultiValueAnswer = "aws/multi-value-answer"
|
||||||
|
providerSpecificHealthCheckID = "aws/health-check-id"
|
||||||
|
sameZoneAlias = "same-zone"
|
||||||
// Currently supported up to 10 health checks or hosted zones.
|
// Currently supported up to 10 health checks or hosted zones.
|
||||||
// https://docs.aws.amazon.com/Route53/latest/APIReference/API_ListTagsForResources.html#API_ListTagsForResources_RequestSyntax
|
// https://docs.aws.amazon.com/Route53/latest/APIReference/API_ListTagsForResources.html#API_ListTagsForResources_RequestSyntax
|
||||||
batchSize = 10
|
batchSize = 10
|
||||||
|
minLatitude = -90.0
|
||||||
|
maxLatitude = 90.0
|
||||||
|
minLongitude = -180.0
|
||||||
|
maxLongitude = 180.0
|
||||||
)
|
)
|
||||||
|
|
||||||
// see elb: https://docs.aws.amazon.com/general/latest/gr/elb.html
|
// see elb: https://docs.aws.amazon.com/general/latest/gr/elb.html
|
||||||
@ -231,6 +239,12 @@ type profiledZone struct {
|
|||||||
zone *route53types.HostedZone
|
zone *route53types.HostedZone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type geoProximity struct {
|
||||||
|
location *route53types.GeoProximityLocation
|
||||||
|
endpoint *endpoint.Endpoint
|
||||||
|
isSet bool
|
||||||
|
}
|
||||||
|
|
||||||
func (cs Route53Changes) Route53Changes() []route53types.Change {
|
func (cs Route53Changes) Route53Changes() []route53types.Change {
|
||||||
var ret []route53types.Change
|
var ret []route53types.Change
|
||||||
for _, c := range cs {
|
for _, c := range cs {
|
||||||
@ -542,6 +556,8 @@ func (p *AWSProvider) records(ctx context.Context, zones map[string]*profiledZon
|
|||||||
ep.WithProviderSpecific(providerSpecificGeolocationSubdivisionCode, *r.GeoLocation.SubdivisionCode)
|
ep.WithProviderSpecific(providerSpecificGeolocationSubdivisionCode, *r.GeoLocation.SubdivisionCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case r.GeoProximityLocation != nil:
|
||||||
|
handleGeoProximityLocationRecord(&r, ep)
|
||||||
default:
|
default:
|
||||||
// one of the above needs to be set, otherwise SetIdentifier doesn't make sense
|
// one of the above needs to be set, otherwise SetIdentifier doesn't make sense
|
||||||
}
|
}
|
||||||
@ -560,6 +576,25 @@ func (p *AWSProvider) records(ctx context.Context, zones map[string]*profiledZon
|
|||||||
return endpoints, nil
|
return endpoints, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleGeoProximityLocationRecord(r *route53types.ResourceRecordSet, ep *endpoint.Endpoint) {
|
||||||
|
if region := aws.ToString(r.GeoProximityLocation.AWSRegion); region != "" {
|
||||||
|
ep.WithProviderSpecific(providerSpecificGeoProximityLocationAWSRegion, region)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bias := r.GeoProximityLocation.Bias; bias != nil {
|
||||||
|
ep.WithProviderSpecific(providerSpecificGeoProximityLocationBias, fmt.Sprintf("%d", aws.ToInt32(bias)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if coords := r.GeoProximityLocation.Coordinates; coords != nil {
|
||||||
|
coordinates := fmt.Sprintf("%s,%s", aws.ToString(coords.Latitude), aws.ToString(coords.Longitude))
|
||||||
|
ep.WithProviderSpecific(providerSpecificGeoProximityLocationCoordinates, coordinates)
|
||||||
|
}
|
||||||
|
|
||||||
|
if localZoneGroup := aws.ToString(r.GeoProximityLocation.LocalZoneGroup); localZoneGroup != "" {
|
||||||
|
ep.WithProviderSpecific(providerSpecificGeoProximityLocationLocalZoneGroup, localZoneGroup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Identify if old and new endpoints require DELETE/CREATE instead of UPDATE.
|
// Identify if old and new endpoints require DELETE/CREATE instead of UPDATE.
|
||||||
func (p *AWSProvider) requiresDeleteCreate(old *endpoint.Endpoint, newE *endpoint.Endpoint) bool {
|
func (p *AWSProvider) requiresDeleteCreate(old *endpoint.Endpoint, newE *endpoint.Endpoint) bool {
|
||||||
// a change of a record type
|
// a change of a record type
|
||||||
@ -832,12 +867,32 @@ func (p *AWSProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]*endpoi
|
|||||||
} else {
|
} else {
|
||||||
ep.DeleteProviderSpecificProperty(providerSpecificEvaluateTargetHealth)
|
ep.DeleteProviderSpecificProperty(providerSpecificEvaluateTargetHealth)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adjustGeoProximityLocationEndpoint(ep)
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints = append(endpoints, aliasCnameAaaaEndpoints...)
|
endpoints = append(endpoints, aliasCnameAaaaEndpoints...)
|
||||||
return endpoints, nil
|
return endpoints, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the endpoint is using geoproximity, set the bias to 0 if not set
|
||||||
|
// this is needed to avoid unnecessary Upserts if the desired endpoint doesn't specify a bias
|
||||||
|
func adjustGeoProximityLocationEndpoint(ep *endpoint.Endpoint) {
|
||||||
|
if ep.SetIdentifier == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, ok1 := ep.GetProviderSpecificProperty(providerSpecificGeoProximityLocationAWSRegion)
|
||||||
|
_, ok2 := ep.GetProviderSpecificProperty(providerSpecificGeoProximityLocationLocalZoneGroup)
|
||||||
|
_, ok3 := ep.GetProviderSpecificProperty(providerSpecificGeoProximityLocationCoordinates)
|
||||||
|
|
||||||
|
if ok1 || ok2 || ok3 {
|
||||||
|
// check if ep has bias property and if not, set it to 0
|
||||||
|
if _, ok := ep.GetProviderSpecificProperty(providerSpecificGeoProximityLocationBias); !ok {
|
||||||
|
ep.SetProviderSpecificProperty(providerSpecificGeoProximityLocationBias, "0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// newChange returns a route53 Change
|
// newChange returns a route53 Change
|
||||||
// returned Change is based on the given record by the given action, e.g.
|
// returned Change is based on the given record by the given action, e.g.
|
||||||
// action=ChangeActionCreate returns a change for creation of the record and
|
// action=ChangeActionCreate returns a change for creation of the record and
|
||||||
@ -926,6 +981,8 @@ func (p *AWSProvider) newChange(action route53types.ChangeAction, ep *endpoint.E
|
|||||||
if useGeolocation {
|
if useGeolocation {
|
||||||
change.ResourceRecordSet.GeoLocation = geolocation
|
change.ResourceRecordSet.GeoLocation = geolocation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withChangeForGeoProximityEndpoint(change, ep)
|
||||||
}
|
}
|
||||||
|
|
||||||
if prop, ok := ep.GetProviderSpecificProperty(providerSpecificHealthCheckID); ok {
|
if prop, ok := ep.GetProviderSpecificProperty(providerSpecificHealthCheckID); ok {
|
||||||
@ -939,6 +996,99 @@ func (p *AWSProvider) newChange(action route53types.ChangeAction, ep *endpoint.E
|
|||||||
return change
|
return change
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newGeoProximity(ep *endpoint.Endpoint) *geoProximity {
|
||||||
|
return &geoProximity{
|
||||||
|
location: &route53types.GeoProximityLocation{},
|
||||||
|
endpoint: ep,
|
||||||
|
isSet: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gp *geoProximity) withAWSRegion() *geoProximity {
|
||||||
|
if prop, ok := gp.endpoint.GetProviderSpecificProperty(providerSpecificGeoProximityLocationAWSRegion); ok {
|
||||||
|
gp.location.AWSRegion = aws.String(prop)
|
||||||
|
gp.isSet = true
|
||||||
|
}
|
||||||
|
return gp
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a method to set the local zone group for the geoproximity location
|
||||||
|
func (gp *geoProximity) withLocalZoneGroup() *geoProximity {
|
||||||
|
if prop, ok := gp.endpoint.GetProviderSpecificProperty(providerSpecificGeoProximityLocationLocalZoneGroup); ok {
|
||||||
|
gp.location.LocalZoneGroup = aws.String(prop)
|
||||||
|
gp.isSet = true
|
||||||
|
}
|
||||||
|
return gp
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a method to set the bias for the geoproximity location
|
||||||
|
func (gp *geoProximity) withBias() *geoProximity {
|
||||||
|
if prop, ok := gp.endpoint.GetProviderSpecificProperty(providerSpecificGeoProximityLocationBias); ok {
|
||||||
|
bias, err := strconv.ParseInt(prop, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed parsing value of %s: %s: %v; using bias of 0", providerSpecificGeoProximityLocationBias, prop, err)
|
||||||
|
bias = 0
|
||||||
|
}
|
||||||
|
gp.location.Bias = aws.Int32(int32(bias))
|
||||||
|
gp.isSet = true
|
||||||
|
}
|
||||||
|
return gp
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateCoordinates checks if the given latitude and longitude are valid.
|
||||||
|
func validateCoordinates(lat, long string) error {
|
||||||
|
latitude, err := strconv.ParseFloat(lat, 64)
|
||||||
|
if err != nil || latitude < minLatitude || latitude > maxLatitude {
|
||||||
|
return fmt.Errorf("invalid latitude: must be a number between %f and %f", minLatitude, maxLatitude)
|
||||||
|
}
|
||||||
|
|
||||||
|
longitude, err := strconv.ParseFloat(long, 64)
|
||||||
|
if err != nil || longitude < minLongitude || longitude > maxLongitude {
|
||||||
|
return fmt.Errorf("invalid longitude: must be a number between %f and %f", minLongitude, maxLongitude)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gp *geoProximity) withCoordinates() *geoProximity {
|
||||||
|
if prop, ok := gp.endpoint.GetProviderSpecificProperty(providerSpecificGeoProximityLocationCoordinates); ok {
|
||||||
|
coordinates := strings.Split(prop, ",")
|
||||||
|
if len(coordinates) == 2 {
|
||||||
|
latitude := coordinates[0]
|
||||||
|
longitude := coordinates[1]
|
||||||
|
if err := validateCoordinates(latitude, longitude); err != nil {
|
||||||
|
log.Warnf("Invalid coordinates %s for name=%s setIdentifier=%s; %v", prop, gp.endpoint.DNSName, gp.endpoint.SetIdentifier, err)
|
||||||
|
} else {
|
||||||
|
gp.location.Coordinates = &route53types.Coordinates{
|
||||||
|
Latitude: aws.String(latitude),
|
||||||
|
Longitude: aws.String(longitude),
|
||||||
|
}
|
||||||
|
gp.isSet = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warnf("Invalid coordinates format for %s: %s; expected format 'latitude,longitude'", providerSpecificGeoProximityLocationCoordinates, prop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gp *geoProximity) build() *route53types.GeoProximityLocation {
|
||||||
|
if gp.isSet {
|
||||||
|
return gp.location
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func withChangeForGeoProximityEndpoint(change *Route53Change, ep *endpoint.Endpoint) {
|
||||||
|
geoProx := newGeoProximity(ep).
|
||||||
|
withAWSRegion().
|
||||||
|
withCoordinates().
|
||||||
|
withLocalZoneGroup().
|
||||||
|
withBias()
|
||||||
|
|
||||||
|
change.ResourceRecordSet.GeoProximityLocation = geoProx.build()
|
||||||
|
}
|
||||||
|
|
||||||
// searches for `changes` that are contained in `queue` and returns the `changes` separated by whether they were found in the queue (`foundChanges`) or not (`notFoundChanges`)
|
// searches for `changes` that are contained in `queue` and returns the `changes` separated by whether they were found in the queue (`foundChanges`) or not (`notFoundChanges`)
|
||||||
func findChangesInQueue(changes Route53Changes, queue Route53Changes) (Route53Changes, Route53Changes) {
|
func findChangesInQueue(changes Route53Changes, queue Route53Changes) (Route53Changes, Route53Changes) {
|
||||||
if queue == nil {
|
if queue == nil {
|
||||||
|
@ -583,6 +583,42 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
SubdivisionCode: aws.String("NY"),
|
SubdivisionCode: aws.String("NY"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("geoproximitylocation-region.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
|
Type: route53types.RRTypeA,
|
||||||
|
TTL: aws.Int64(defaultTTL),
|
||||||
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
|
SetIdentifier: aws.String("test-set-1"),
|
||||||
|
GeoProximityLocation: &route53types.GeoProximityLocation{
|
||||||
|
AWSRegion: aws.String("us-west-2"),
|
||||||
|
Bias: aws.Int32(10),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("geoproximitylocation-localzone.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
|
Type: route53types.RRTypeA,
|
||||||
|
TTL: aws.Int64(defaultTTL),
|
||||||
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
|
SetIdentifier: aws.String("test-set-1"),
|
||||||
|
GeoProximityLocation: &route53types.GeoProximityLocation{
|
||||||
|
LocalZoneGroup: aws.String("usw2-pdx1-az1"),
|
||||||
|
Bias: aws.Int32(10),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("geoproximitylocation-coordinates.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
|
Type: route53types.RRTypeA,
|
||||||
|
TTL: aws.Int64(defaultTTL),
|
||||||
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
|
SetIdentifier: aws.String("test-set-1"),
|
||||||
|
GeoProximityLocation: &route53types.GeoProximityLocation{
|
||||||
|
Coordinates: &route53types.Coordinates{
|
||||||
|
Latitude: aws.String("90"),
|
||||||
|
Longitude: aws.String("90"),
|
||||||
|
},
|
||||||
|
Bias: aws.Int32(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
@ -636,6 +672,9 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
endpoint.NewEndpointWithTTL("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeolocationContinentCode, "EU"),
|
endpoint.NewEndpointWithTTL("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeolocationContinentCode, "EU"),
|
||||||
endpoint.NewEndpointWithTTL("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificGeolocationCountryCode, "DE"),
|
endpoint.NewEndpointWithTTL("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificGeolocationCountryCode, "DE"),
|
||||||
endpoint.NewEndpointWithTTL("geolocation-subdivision-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeolocationSubdivisionCode, "NY"),
|
endpoint.NewEndpointWithTTL("geolocation-subdivision-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeolocationSubdivisionCode, "NY"),
|
||||||
|
endpoint.NewEndpointWithTTL("geoproximitylocation-region.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeoProximityLocationAWSRegion, "us-west-2").WithProviderSpecific(providerSpecificGeoProximityLocationBias, "10"),
|
||||||
|
endpoint.NewEndpointWithTTL("geoproximitylocation-localzone.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeoProximityLocationLocalZoneGroup, "usw2-pdx1-az1").WithProviderSpecific(providerSpecificGeoProximityLocationBias, "10"),
|
||||||
|
endpoint.NewEndpointWithTTL("geoproximitylocation-coordinates.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeoProximityLocationCoordinates, "90,90").WithProviderSpecific(providerSpecificGeoProximityLocationBias, "0"),
|
||||||
endpoint.NewEndpointWithTTL("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, endpoint.TTL(defaultTTL), "foo.example.com").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificWeight, "10").WithProviderSpecific(providerSpecificHealthCheckID, "foo-bar-healthcheck-id").WithProviderSpecific(providerSpecificAlias, "false"),
|
endpoint.NewEndpointWithTTL("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, endpoint.TTL(defaultTTL), "foo.example.com").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificWeight, "10").WithProviderSpecific(providerSpecificHealthCheckID, "foo-bar-healthcheck-id").WithProviderSpecific(providerSpecificAlias, "false"),
|
||||||
endpoint.NewEndpointWithTTL("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificWeight, "20").WithProviderSpecific(providerSpecificHealthCheckID, "abc-def-healthcheck-id"),
|
endpoint.NewEndpointWithTTL("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificWeight, "20").WithProviderSpecific(providerSpecificHealthCheckID, "abc-def-healthcheck-id"),
|
||||||
endpoint.NewEndpointWithTTL("mail.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeMX, endpoint.TTL(defaultTTL), "10 mailhost1.example.com", "20 mailhost2.example.com"),
|
endpoint.NewEndpointWithTTL("mail.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeMX, endpoint.TTL(defaultTTL), "10 mailhost1.example.com", "20 mailhost2.example.com"),
|
||||||
@ -670,6 +709,7 @@ func TestAWSAdjustEndpoints(t *testing.T) {
|
|||||||
endpoint.NewEndpoint("cname-test-elb-no-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "false"),
|
endpoint.NewEndpoint("cname-test-elb-no-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "false"),
|
||||||
endpoint.NewEndpoint("cname-test-elb-no-eth.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false"), // eth = evaluate target health
|
endpoint.NewEndpoint("cname-test-elb-no-eth.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false"), // eth = evaluate target health
|
||||||
endpoint.NewEndpoint("cname-test-elb-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true"),
|
endpoint.NewEndpoint("cname-test-elb-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true"),
|
||||||
|
endpoint.NewEndpoint("a-test-geoproximity-no-bias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "8.8.8.8").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeoProximityLocationAWSRegion, "us-west-2"),
|
||||||
}
|
}
|
||||||
|
|
||||||
records, err := provider.AdjustEndpoints(records)
|
records, err := provider.AdjustEndpoints(records)
|
||||||
@ -687,6 +727,7 @@ func TestAWSAdjustEndpoints(t *testing.T) {
|
|||||||
endpoint.NewEndpoint("cname-test-elb-no-eth.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false"), // eth = evaluate target health
|
endpoint.NewEndpoint("cname-test-elb-no-eth.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false"), // eth = evaluate target health
|
||||||
endpoint.NewEndpoint("cname-test-elb-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true"),
|
endpoint.NewEndpoint("cname-test-elb-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true"),
|
||||||
endpoint.NewEndpoint("cname-test-elb-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true"),
|
endpoint.NewEndpoint("cname-test-elb-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true"),
|
||||||
|
endpoint.NewEndpoint("a-test-geoproximity-no-bias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "8.8.8.8").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeoProximityLocationAWSRegion, "us-west-2").WithProviderSpecific(providerSpecificGeoProximityLocationBias, "0"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,6 +886,27 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
TTL: aws.Int64(defaultTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}, {Value: aws.String("2606:4700:4700::1001")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}, {Value: aws.String("2606:4700:4700::1001")}},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("delete-test-geoproximity.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
|
Type: route53types.RRTypeA,
|
||||||
|
TTL: aws.Int64(defaultTTL),
|
||||||
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
|
SetIdentifier: aws.String("geoproximity-delete"),
|
||||||
|
GeoProximityLocation: &route53types.GeoProximityLocation{
|
||||||
|
AWSRegion: aws.String("us-west-2"),
|
||||||
|
Bias: aws.Int32(10),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("update-test-geoproximity.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
|
Type: route53types.RRTypeA,
|
||||||
|
TTL: aws.Int64(defaultTTL),
|
||||||
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
|
SetIdentifier: aws.String("geoproximity-update"),
|
||||||
|
GeoProximityLocation: &route53types.GeoProximityLocation{
|
||||||
|
LocalZoneGroup: aws.String("usw2-lax1-az2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
@ -915,6 +977,13 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
endpoint.NewEndpoint("create-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "8.8.8.8", "8.8.4.4"),
|
endpoint.NewEndpoint("create-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "8.8.8.8", "8.8.4.4"),
|
||||||
endpoint.NewEndpoint("create-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "2606:4700:4700::1111", "2606:4700:4700::1001"),
|
endpoint.NewEndpoint("create-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "2606:4700:4700::1111", "2606:4700:4700::1001"),
|
||||||
endpoint.NewEndpoint("create-test-mx.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeMX, "10 mailhost1.foo.elb.amazonaws.com"),
|
endpoint.NewEndpoint("create-test-mx.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeMX, "10 mailhost1.foo.elb.amazonaws.com"),
|
||||||
|
endpoint.NewEndpoint("create-test-geoproximity-region.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "8.8.8.8").
|
||||||
|
WithSetIdentifier("geoproximity-region").
|
||||||
|
WithProviderSpecific(providerSpecificGeoProximityLocationAWSRegion, "us-west-2").
|
||||||
|
WithProviderSpecific(providerSpecificGeoProximityLocationBias, "10"),
|
||||||
|
endpoint.NewEndpoint("create-test-geoproximity-coordinates.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "8.8.8.8").
|
||||||
|
WithSetIdentifier("geoproximity-coordinates").
|
||||||
|
WithProviderSpecific(providerSpecificGeoProximityLocationCoordinates, "60,60"),
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRecords := []*endpoint.Endpoint{
|
currentRecords := []*endpoint.Endpoint{
|
||||||
@ -930,6 +999,9 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
endpoint.NewEndpoint("update-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "bar.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpoint("update-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "bar.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpoint("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "8.8.8.8", "8.8.4.4"),
|
endpoint.NewEndpoint("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "8.8.8.8", "8.8.4.4"),
|
||||||
endpoint.NewEndpoint("update-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "2606:4700:4700::1111", "2606:4700:4700::1001"),
|
endpoint.NewEndpoint("update-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "2606:4700:4700::1111", "2606:4700:4700::1001"),
|
||||||
|
endpoint.NewEndpoint("update-test-geoproximity.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").
|
||||||
|
WithSetIdentifier("geoproximity-update").
|
||||||
|
WithProviderSpecific(providerSpecificGeoProximityLocationLocalZoneGroup, "usw2-lax1-az2"),
|
||||||
endpoint.NewEndpoint("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").WithSetIdentifier("weighted-to-simple").WithProviderSpecific(providerSpecificWeight, "10"),
|
endpoint.NewEndpoint("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").WithSetIdentifier("weighted-to-simple").WithProviderSpecific(providerSpecificWeight, "10"),
|
||||||
endpoint.NewEndpoint("simple-to-weighted.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4"),
|
endpoint.NewEndpoint("simple-to-weighted.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4"),
|
||||||
endpoint.NewEndpoint("policy-change.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").WithSetIdentifier("policy-change").WithProviderSpecific(providerSpecificWeight, "10"),
|
endpoint.NewEndpoint("policy-change.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").WithSetIdentifier("policy-change").WithProviderSpecific(providerSpecificWeight, "10"),
|
||||||
@ -951,6 +1023,9 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
endpoint.NewEndpoint("update-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "baz.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpoint("update-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "baz.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpoint("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4", "4.3.2.1"),
|
endpoint.NewEndpoint("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4", "4.3.2.1"),
|
||||||
endpoint.NewEndpoint("update-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "2606:4700:4700::1001", "2606:4700:4700::1111"),
|
endpoint.NewEndpoint("update-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "2606:4700:4700::1001", "2606:4700:4700::1111"),
|
||||||
|
endpoint.NewEndpoint("update-test-geoproximity.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").
|
||||||
|
WithSetIdentifier("geoproximity-update").
|
||||||
|
WithProviderSpecific(providerSpecificGeoProximityLocationLocalZoneGroup, "usw2-phx2-az1"),
|
||||||
endpoint.NewEndpoint("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4"),
|
endpoint.NewEndpoint("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4"),
|
||||||
endpoint.NewEndpoint("simple-to-weighted.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").WithSetIdentifier("simple-to-weighted").WithProviderSpecific(providerSpecificWeight, "10"),
|
endpoint.NewEndpoint("simple-to-weighted.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").WithSetIdentifier("simple-to-weighted").WithProviderSpecific(providerSpecificWeight, "10"),
|
||||||
endpoint.NewEndpoint("policy-change.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").WithSetIdentifier("policy-change").WithProviderSpecific(providerSpecificRegion, "us-east-1"),
|
endpoint.NewEndpoint("policy-change.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").WithSetIdentifier("policy-change").WithProviderSpecific(providerSpecificRegion, "us-east-1"),
|
||||||
@ -969,6 +1044,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
endpoint.NewEndpoint("delete-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "qux.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpoint("delete-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "qux.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpoint("delete-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4", "4.3.2.1"),
|
endpoint.NewEndpoint("delete-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4", "4.3.2.1"),
|
||||||
endpoint.NewEndpoint("delete-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "2606:4700:4700::1111", "2606:4700:4700::1001"),
|
endpoint.NewEndpoint("delete-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, "2606:4700:4700::1111", "2606:4700:4700::1001"),
|
||||||
|
endpoint.NewEndpoint("delete-test-geoproximity.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, "1.2.3.4").WithSetIdentifier("geoproximity-delete").WithProviderSpecific(providerSpecificGeoProximityLocationAWSRegion, "us-west-2").WithProviderSpecific(providerSpecificGeoProximityLocationBias, "10"),
|
||||||
endpoint.NewEndpoint("delete-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeMX, "30 mailhost1.foo.elb.amazonaws.com"),
|
endpoint.NewEndpoint("delete-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeMX, "30 mailhost1.foo.elb.amazonaws.com"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,6 +1194,40 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
TTL: aws.Int64(defaultTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mailhost1.foo.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mailhost1.foo.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("create-test-geoproximity-region.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
|
Type: route53types.RRTypeA,
|
||||||
|
TTL: aws.Int64(defaultTTL),
|
||||||
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
||||||
|
SetIdentifier: aws.String("geoproximity-region"),
|
||||||
|
GeoProximityLocation: &route53types.GeoProximityLocation{
|
||||||
|
AWSRegion: aws.String("us-west-2"),
|
||||||
|
Bias: aws.Int32(10),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("update-test-geoproximity.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
|
Type: route53types.RRTypeA,
|
||||||
|
TTL: aws.Int64(defaultTTL),
|
||||||
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
|
SetIdentifier: aws.String("geoproximity-update"),
|
||||||
|
GeoProximityLocation: &route53types.GeoProximityLocation{
|
||||||
|
LocalZoneGroup: aws.String("usw2-phx2-az1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("create-test-geoproximity-coordinates.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
|
Type: route53types.RRTypeA,
|
||||||
|
TTL: aws.Int64(defaultTTL),
|
||||||
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
||||||
|
SetIdentifier: aws.String("geoproximity-coordinates"),
|
||||||
|
GeoProximityLocation: &route53types.GeoProximityLocation{
|
||||||
|
Coordinates: &route53types.Coordinates{
|
||||||
|
Latitude: aws.String("60"),
|
||||||
|
Longitude: aws.String("60"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
validateRecords(t, listAWSRecords(t, provider.clients[defaultAWSProfile], "/hostedzone/zone-2.ext-dns-test-2.teapot.zalan.do."), []route53types.ResourceRecordSet{
|
validateRecords(t, listAWSRecords(t, provider.clients[defaultAWSProfile], "/hostedzone/zone-2.ext-dns-test-2.teapot.zalan.do."), []route53types.ResourceRecordSet{
|
||||||
{
|
{
|
||||||
@ -1902,7 +2012,7 @@ func validateEndpoints(t *testing.T, provider *AWSProvider, endpoints []*endpoin
|
|||||||
|
|
||||||
normalized, err := provider.AdjustEndpoints(endpoints)
|
normalized, err := provider.AdjustEndpoints(endpoints)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, testutils.SameEndpoints(normalized, expected), "actual and normalized endpoints don't match. %+v:%+v", endpoints, normalized)
|
assert.True(t, testutils.SameEndpoints(normalized, expected), "normalized and expected endpoints don't match. %+v:%+v", normalized, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateAWSZones(t *testing.T, zones map[string]*route53types.HostedZone, expected map[string]*route53types.HostedZone) {
|
func validateAWSZones(t *testing.T, zones map[string]*route53types.HostedZone, expected map[string]*route53types.HostedZone) {
|
||||||
@ -2370,3 +2480,340 @@ func TestConvertOctalToAscii(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGeoProximityWithAWSRegion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
region string
|
||||||
|
hasRegion bool
|
||||||
|
expectedSet bool
|
||||||
|
expectedRegion string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid AWS region",
|
||||||
|
region: "us-west-2",
|
||||||
|
hasRegion: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedRegion: "us-west-2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "another valid AWS region",
|
||||||
|
region: "eu-central-1",
|
||||||
|
hasRegion: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedRegion: "eu-central-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty region string",
|
||||||
|
region: "",
|
||||||
|
hasRegion: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedRegion: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no region property set",
|
||||||
|
region: "",
|
||||||
|
hasRegion: false,
|
||||||
|
expectedSet: false,
|
||||||
|
expectedRegion: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "region with special characters",
|
||||||
|
region: "us-gov-west-1",
|
||||||
|
hasRegion: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedRegion: "us-gov-west-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "region with numbers",
|
||||||
|
region: "ap-southeast-3",
|
||||||
|
hasRegion: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedRegion: "ap-southeast-3",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
ep := &endpoint.Endpoint{
|
||||||
|
DNSName: "test.example.com",
|
||||||
|
SetIdentifier: "test-set",
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.hasRegion {
|
||||||
|
ep.SetProviderSpecificProperty(providerSpecificGeoProximityLocationAWSRegion, tt.region)
|
||||||
|
}
|
||||||
|
|
||||||
|
gp := newGeoProximity(ep)
|
||||||
|
result := gp.withAWSRegion()
|
||||||
|
|
||||||
|
assert.Equal(t, tt.expectedSet, result.isSet)
|
||||||
|
|
||||||
|
if tt.expectedSet {
|
||||||
|
assert.NotNil(t, result.location.AWSRegion)
|
||||||
|
assert.Equal(t, tt.expectedRegion, *result.location.AWSRegion)
|
||||||
|
} else {
|
||||||
|
assert.Nil(t, result.location.AWSRegion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the method returns the same instance for chaining
|
||||||
|
assert.Equal(t, gp, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGeoProximityWithLocalZoneGroup(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
localZoneGroup string
|
||||||
|
hasLocalZoneGroup bool
|
||||||
|
expectedSet bool
|
||||||
|
expectedLocalZoneGroup string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid local zone group",
|
||||||
|
localZoneGroup: "usw2-lax1-az1",
|
||||||
|
hasLocalZoneGroup: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedLocalZoneGroup: "usw2-lax1-az1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty local zone group",
|
||||||
|
localZoneGroup: "",
|
||||||
|
hasLocalZoneGroup: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedLocalZoneGroup: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no local zone group property",
|
||||||
|
localZoneGroup: "",
|
||||||
|
hasLocalZoneGroup: false,
|
||||||
|
expectedSet: false,
|
||||||
|
expectedLocalZoneGroup: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
ep := &endpoint.Endpoint{
|
||||||
|
DNSName: "test.example.com",
|
||||||
|
SetIdentifier: "test-set",
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.hasLocalZoneGroup {
|
||||||
|
ep.SetProviderSpecificProperty(providerSpecificGeoProximityLocationLocalZoneGroup, tt.localZoneGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
gp := newGeoProximity(ep)
|
||||||
|
result := gp.withLocalZoneGroup()
|
||||||
|
|
||||||
|
assert.Equal(t, tt.expectedSet, result.isSet)
|
||||||
|
|
||||||
|
if tt.expectedSet {
|
||||||
|
assert.NotNil(t, result.location.LocalZoneGroup)
|
||||||
|
assert.Equal(t, tt.expectedLocalZoneGroup, *result.location.LocalZoneGroup)
|
||||||
|
} else {
|
||||||
|
assert.Nil(t, result.location.LocalZoneGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify method returns same instance for chaining
|
||||||
|
assert.Equal(t, gp, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGeoProximityWithCoordinates(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
coordinates string
|
||||||
|
expectedSet bool
|
||||||
|
expectedLat string
|
||||||
|
expectedLong string
|
||||||
|
shouldHaveCoords bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid coordinates",
|
||||||
|
coordinates: "45.0,90.0",
|
||||||
|
expectedSet: true,
|
||||||
|
expectedLat: "45.0",
|
||||||
|
expectedLong: "90.0",
|
||||||
|
shouldHaveCoords: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "edge case min coordinates",
|
||||||
|
coordinates: "-90.0,-180.0",
|
||||||
|
expectedSet: true,
|
||||||
|
expectedLat: "-90.0",
|
||||||
|
expectedLong: "-180.0",
|
||||||
|
shouldHaveCoords: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "edge case max coordinates",
|
||||||
|
coordinates: "90.0,180.0",
|
||||||
|
expectedSet: true,
|
||||||
|
expectedLat: "90.0",
|
||||||
|
expectedLong: "180.0",
|
||||||
|
shouldHaveCoords: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid latitude too high",
|
||||||
|
coordinates: "91.0,90.0",
|
||||||
|
expectedSet: false,
|
||||||
|
shouldHaveCoords: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid longitude too low",
|
||||||
|
coordinates: "45.0,-181.0",
|
||||||
|
expectedSet: false,
|
||||||
|
shouldHaveCoords: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid format - single value",
|
||||||
|
coordinates: "45.0",
|
||||||
|
expectedSet: false,
|
||||||
|
shouldHaveCoords: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid format - three values",
|
||||||
|
coordinates: "45.0,90.0,10.0",
|
||||||
|
expectedSet: false,
|
||||||
|
shouldHaveCoords: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid format - non-numeric",
|
||||||
|
coordinates: "abc,def",
|
||||||
|
expectedSet: false,
|
||||||
|
shouldHaveCoords: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no coordinates property",
|
||||||
|
coordinates: "",
|
||||||
|
expectedSet: false,
|
||||||
|
shouldHaveCoords: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
ep := &endpoint.Endpoint{}
|
||||||
|
if tt.coordinates != "" {
|
||||||
|
ep.SetProviderSpecificProperty(providerSpecificGeoProximityLocationCoordinates, tt.coordinates)
|
||||||
|
}
|
||||||
|
|
||||||
|
gp := newGeoProximity(ep)
|
||||||
|
result := gp.withCoordinates()
|
||||||
|
|
||||||
|
assert.Equal(t, tt.expectedSet, result.isSet)
|
||||||
|
|
||||||
|
if tt.shouldHaveCoords {
|
||||||
|
assert.NotNil(t, result.location.Coordinates)
|
||||||
|
assert.Equal(t, tt.expectedLat, *result.location.Coordinates.Latitude)
|
||||||
|
assert.Equal(t, tt.expectedLong, *result.location.Coordinates.Longitude)
|
||||||
|
} else {
|
||||||
|
assert.Nil(t, result.location.Coordinates)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGeoProximityWithBias(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
bias string
|
||||||
|
hasBias bool
|
||||||
|
expectedSet bool
|
||||||
|
expectedBias int32
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid positive bias",
|
||||||
|
bias: "10",
|
||||||
|
hasBias: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedBias: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid negative bias",
|
||||||
|
bias: "-5",
|
||||||
|
hasBias: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedBias: -5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "zero bias",
|
||||||
|
bias: "0",
|
||||||
|
hasBias: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedBias: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "large positive bias",
|
||||||
|
bias: "99",
|
||||||
|
hasBias: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedBias: 99,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "large negative bias",
|
||||||
|
bias: "-99",
|
||||||
|
hasBias: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedBias: -99,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid bias - non-numeric",
|
||||||
|
bias: "abc",
|
||||||
|
hasBias: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedBias: 0, // defaults to 0 on error
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid bias - float",
|
||||||
|
bias: "10.5",
|
||||||
|
hasBias: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedBias: 0, // defaults to 0 on error
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty bias string",
|
||||||
|
bias: "",
|
||||||
|
hasBias: true,
|
||||||
|
expectedSet: true,
|
||||||
|
expectedBias: 0, // defaults to 0 on error
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no bias property",
|
||||||
|
bias: "",
|
||||||
|
hasBias: false,
|
||||||
|
expectedSet: false,
|
||||||
|
expectedBias: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
ep := &endpoint.Endpoint{
|
||||||
|
DNSName: "test.example.com",
|
||||||
|
SetIdentifier: "test-set",
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.hasBias {
|
||||||
|
ep.SetProviderSpecificProperty(providerSpecificGeoProximityLocationBias, tt.bias)
|
||||||
|
}
|
||||||
|
|
||||||
|
gp := newGeoProximity(ep)
|
||||||
|
result := gp.withBias()
|
||||||
|
|
||||||
|
assert.Equal(t, tt.expectedSet, result.isSet)
|
||||||
|
|
||||||
|
if tt.expectedSet {
|
||||||
|
assert.NotNil(t, result.location.Bias)
|
||||||
|
assert.Equal(t, tt.expectedBias, *result.location.Bias)
|
||||||
|
} else {
|
||||||
|
assert.Nil(t, result.location.Bias)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify method returns same instance for chaining
|
||||||
|
assert.Equal(t, gp, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user