|
|
|
@ -80,9 +80,11 @@ class _Route53Record(EqualityTupleMixin): |
|
|
|
# be served out according to their weights |
|
|
|
for i, value in enumerate(pool.data['values']): |
|
|
|
weight = value['weight'] |
|
|
|
status = value['status'] |
|
|
|
value = value['value'] |
|
|
|
ret.add(_Route53DynamicValue(provider, record, pool_name, |
|
|
|
value, weight, i, creating)) |
|
|
|
value, weight, status, i, |
|
|
|
creating)) |
|
|
|
|
|
|
|
# Rules |
|
|
|
for i, rule in enumerate(record.dynamic.rules): |
|
|
|
@ -345,19 +347,21 @@ class _Route53DynamicRule(_Route53Record): |
|
|
|
|
|
|
|
class _Route53DynamicValue(_Route53Record): |
|
|
|
|
|
|
|
def __init__(self, provider, record, pool_name, value, weight, index, |
|
|
|
creating): |
|
|
|
def __init__(self, provider, record, pool_name, value, weight, status, |
|
|
|
index, creating): |
|
|
|
fqdn_override = f'_octodns-{pool_name}-value.{record.fqdn}' |
|
|
|
super(_Route53DynamicValue, self).__init__(provider, record, creating, |
|
|
|
fqdn_override=fqdn_override) |
|
|
|
|
|
|
|
self.pool_name = pool_name |
|
|
|
self.status = status |
|
|
|
self.index = index |
|
|
|
value_convert = getattr(self, f'_value_convert_{record._type}') |
|
|
|
self.value = value_convert(value, record) |
|
|
|
self.weight = weight |
|
|
|
|
|
|
|
self.health_check_id = provider.get_health_check_id(record, self.value, |
|
|
|
self.status, |
|
|
|
creating) |
|
|
|
|
|
|
|
@property |
|
|
|
@ -433,7 +437,7 @@ class _Route53GeoRecord(_Route53Record): |
|
|
|
|
|
|
|
value = geo.values[0] |
|
|
|
self.health_check_id = provider.get_health_check_id(record, value, |
|
|
|
creating) |
|
|
|
'obey', creating) |
|
|
|
|
|
|
|
def mod(self, action, existing_rrsets): |
|
|
|
geo = self.geo |
|
|
|
@ -599,6 +603,7 @@ class Route53Provider(BaseProvider): |
|
|
|
''' |
|
|
|
SUPPORTS_GEO = True |
|
|
|
SUPPORTS_DYNAMIC = True |
|
|
|
SUPPORTS_POOL_VALUE_STATUS = True |
|
|
|
SUPPORTS = set(('A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', |
|
|
|
'SPF', 'SRV', 'TXT')) |
|
|
|
|
|
|
|
@ -914,7 +919,25 @@ class Route53Provider(BaseProvider): |
|
|
|
# it's ignored only used to make sure the value is unique |
|
|
|
pool_name = rrset['SetIdentifier'][:-4] |
|
|
|
value = rrset['ResourceRecords'][0]['Value'] |
|
|
|
try: |
|
|
|
health_check_id = rrset.get('HealthCheckId', None) |
|
|
|
health_check = self.health_checks[health_check_id] |
|
|
|
health_check_config = health_check['HealthCheckConfig'] |
|
|
|
if health_check_config['Disabled']: |
|
|
|
if health_check_config['Inverted']: |
|
|
|
# disabled and inverted means down |
|
|
|
status = 'down' |
|
|
|
else: |
|
|
|
# disabled means always up |
|
|
|
status = 'up' |
|
|
|
else: |
|
|
|
# otherwise obey |
|
|
|
status = 'obey' |
|
|
|
except KeyError: |
|
|
|
# No healthcheck implies status is always up |
|
|
|
status = 'up' |
|
|
|
pools[pool_name]['values'].append({ |
|
|
|
'status': status, |
|
|
|
'value': value, |
|
|
|
'weight': rrset['Weight'], |
|
|
|
}) |
|
|
|
@ -1092,7 +1115,8 @@ class Route53Provider(BaseProvider): |
|
|
|
|
|
|
|
def _health_check_equivalent(self, host, path, protocol, port, |
|
|
|
measure_latency, request_interval, |
|
|
|
health_check, value=None): |
|
|
|
health_check, value=None, disabled=None, |
|
|
|
inverted=None): |
|
|
|
config = health_check['HealthCheckConfig'] |
|
|
|
|
|
|
|
# So interestingly Route53 normalizes IPv6 addresses to a funky, but |
|
|
|
@ -1115,16 +1139,18 @@ class Route53Provider(BaseProvider): |
|
|
|
port == config['Port'] and \ |
|
|
|
measure_latency == config['MeasureLatency'] and \ |
|
|
|
request_interval == config['RequestInterval'] and \ |
|
|
|
(disabled is None or disabled == config['Disabled']) and \ |
|
|
|
(inverted is None or inverted == config['Inverted']) and \ |
|
|
|
value == config_ip_address |
|
|
|
|
|
|
|
def get_health_check_id(self, record, value, create): |
|
|
|
def get_health_check_id(self, record, value, status, create): |
|
|
|
# fqdn & the first value are special, we use them to match up health |
|
|
|
# checks to their records. Route53 health checks check a single ip and |
|
|
|
# we're going to assume that ips are interchangeable to avoid |
|
|
|
# health-checking each one independently |
|
|
|
fqdn = record.fqdn |
|
|
|
self.log.debug('get_health_check_id: fqdn=%s, type=%s, value=%s', |
|
|
|
fqdn, record._type, value) |
|
|
|
self.log.debug('get_health_check_id: fqdn=%s, type=%s, value=%s, ' |
|
|
|
'status=%s', fqdn, record._type, value, status) |
|
|
|
|
|
|
|
try: |
|
|
|
ip_address(str(value)) |
|
|
|
@ -1140,6 +1166,15 @@ class Route53Provider(BaseProvider): |
|
|
|
healthcheck_port = record.healthcheck_port |
|
|
|
healthcheck_latency = self._healthcheck_measure_latency(record) |
|
|
|
healthcheck_interval = self._healthcheck_request_interval(record) |
|
|
|
if status == 'up': |
|
|
|
healthcheck_disabled = True |
|
|
|
healthcheck_inverted = False |
|
|
|
elif status == 'down': |
|
|
|
healthcheck_disabled = True |
|
|
|
healthcheck_inverted = True |
|
|
|
else: |
|
|
|
healthcheck_disabled = False |
|
|
|
healthcheck_inverted = False |
|
|
|
|
|
|
|
# we're looking for a healthcheck with the current version & our record |
|
|
|
# type, we'll ignore anything else |
|
|
|
@ -1156,7 +1191,9 @@ class Route53Provider(BaseProvider): |
|
|
|
healthcheck_latency, |
|
|
|
healthcheck_interval, |
|
|
|
health_check, |
|
|
|
value=value): |
|
|
|
value=value, |
|
|
|
disabled=healthcheck_disabled, |
|
|
|
inverted=healthcheck_inverted): |
|
|
|
# this is the health check we're looking for |
|
|
|
self.log.debug('get_health_check_id: found match id=%s', id) |
|
|
|
return id |
|
|
|
@ -1168,6 +1205,8 @@ class Route53Provider(BaseProvider): |
|
|
|
|
|
|
|
# no existing matches, we need to create a new health check |
|
|
|
config = { |
|
|
|
'Disabled': healthcheck_disabled, |
|
|
|
'Inverted': healthcheck_inverted, |
|
|
|
'EnableSNI': healthcheck_protocol == 'HTTPS', |
|
|
|
'FailureThreshold': 6, |
|
|
|
'MeasureLatency': healthcheck_latency, |
|
|
|
|