Browse Source

Merge pull request #326 from jrunkel/add-route53-interval-option

Add healthcheck option 'request_interval' for Route53 provider
pull/580/head
Ross McFarland 6 years ago
committed by GitHub
parent
commit
594c5a01fd
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 26 deletions
  1. +2
    -0
      docs/dynamic_records.md
  2. +2
    -0
      docs/geo_records.md
  3. +28
    -6
      octodns/provider/route53.py
  4. +64
    -20
      tests/test_octodns_provider_route53.py

+ 2
- 0
docs/dynamic_records.md View File

@ -110,6 +110,7 @@ test:
| Key | Description | Default | | Key | Description | Default |
|--|--|--| |--|--|--|
| measure_latency | Show latency in AWS console | true | | measure_latency | Show latency in AWS console | true |
| request_interval | Healthcheck interval [10\|30] seconds | 10 |
```yaml ```yaml
@ -123,4 +124,5 @@ test:
route53: route53:
healthcheck: healthcheck:
measure_latency: false measure_latency: false
request_interval: 30
``` ```

+ 2
- 0
docs/geo_records.md View File

@ -86,6 +86,7 @@ test:
| Key | Description | Default | | Key | Description | Default |
|--|--|--| |--|--|--|
| measure_latency | Show latency in AWS console | true | | measure_latency | Show latency in AWS console | true |
| request_interval | Healthcheck interval [10\|30] seconds | 10 |
```yaml ```yaml
--- ---
@ -98,4 +99,5 @@ test:
route53: route53:
healthcheck: healthcheck:
measure_latency: false measure_latency: false
request_interval: 30
``` ```

+ 28
- 6
octodns/provider/route53.py View File

@ -512,6 +512,10 @@ class _Route53GeoRecord(_Route53Record):
self.values) self.values)
class Route53ProviderException(Exception):
pass
def _mod_keyer(mod): def _mod_keyer(mod):
rrset = mod['ResourceRecordSet'] rrset = mod['ResourceRecordSet']
@ -1031,8 +1035,20 @@ class Route53Provider(BaseProvider):
.get('healthcheck', {}) \ .get('healthcheck', {}) \
.get('measure_latency', True) .get('measure_latency', True)
def _healthcheck_request_interval(self, record):
interval = record._octodns.get('route53', {}) \
.get('healthcheck', {}) \
.get('request_interval', 10)
if (interval in [10, 30]):
return interval
else:
raise Route53ProviderException(
'route53.healthcheck.request_interval '
'parameter must be either 10 or 30.')
def _health_check_equivalent(self, host, path, protocol, port, def _health_check_equivalent(self, host, path, protocol, port,
measure_latency, health_check, value=None):
measure_latency, request_interval,
health_check, value=None):
config = health_check['HealthCheckConfig'] config = health_check['HealthCheckConfig']
# So interestingly Route53 normalizes IPAddress which will cause us to # So interestingly Route53 normalizes IPAddress which will cause us to
@ -1050,9 +1066,10 @@ class Route53Provider(BaseProvider):
None) None)
resource_path = config.get('ResourcePath', None) resource_path = config.get('ResourcePath', None)
return host == fully_qualified_domain_name and \ return host == fully_qualified_domain_name and \
path == resource_path and protocol == config['Type'] \
and port == config['Port'] and \
path == resource_path and protocol == config['Type'] and \
port == config['Port'] and \
measure_latency == config['MeasureLatency'] and \ measure_latency == config['MeasureLatency'] and \
request_interval == config['RequestInterval'] and \
value == config_ip_address value == config_ip_address
def get_health_check_id(self, record, value, create): def get_health_check_id(self, record, value, create):
@ -1077,6 +1094,7 @@ class Route53Provider(BaseProvider):
healthcheck_protocol = record.healthcheck_protocol healthcheck_protocol = record.healthcheck_protocol
healthcheck_port = record.healthcheck_port healthcheck_port = record.healthcheck_port
healthcheck_latency = self._healthcheck_measure_latency(record) healthcheck_latency = self._healthcheck_measure_latency(record)
healthcheck_interval = self._healthcheck_request_interval(record)
# we're looking for a healthcheck with the current version & our record # we're looking for a healthcheck with the current version & our record
# type, we'll ignore anything else # type, we'll ignore anything else
@ -1091,6 +1109,7 @@ class Route53Provider(BaseProvider):
healthcheck_protocol, healthcheck_protocol,
healthcheck_port, healthcheck_port,
healthcheck_latency, healthcheck_latency,
healthcheck_interval,
health_check, health_check,
value=value): value=value):
# this is the health check we're looking for # this is the health check we're looking for
@ -1108,7 +1127,7 @@ class Route53Provider(BaseProvider):
'FailureThreshold': 6, 'FailureThreshold': 6,
'MeasureLatency': healthcheck_latency, 'MeasureLatency': healthcheck_latency,
'Port': healthcheck_port, 'Port': healthcheck_port,
'RequestInterval': 10,
'RequestInterval': healthcheck_interval,
'Type': healthcheck_protocol, 'Type': healthcheck_protocol,
} }
if healthcheck_protocol != 'TCP': if healthcheck_protocol != 'TCP':
@ -1143,9 +1162,10 @@ class Route53Provider(BaseProvider):
self._health_checks[id] = health_check self._health_checks[id] = health_check
self.log.info('get_health_check_id: created id=%s, host=%s, ' self.log.info('get_health_check_id: created id=%s, host=%s, '
'path=%s, protocol=%s, port=%d, measure_latency=%r, ' 'path=%s, protocol=%s, port=%d, measure_latency=%r, '
'value=%s', id, healthcheck_host, healthcheck_path,
'request_interval=%d, value=%s',
id, healthcheck_host, healthcheck_path,
healthcheck_protocol, healthcheck_port, healthcheck_protocol, healthcheck_port,
healthcheck_latency, value)
healthcheck_latency, healthcheck_interval, value)
return id return id
def _gc_health_checks(self, record, new): def _gc_health_checks(self, record, new):
@ -1238,6 +1258,7 @@ class Route53Provider(BaseProvider):
healthcheck_protocol = record.healthcheck_protocol healthcheck_protocol = record.healthcheck_protocol
healthcheck_port = record.healthcheck_port healthcheck_port = record.healthcheck_port
healthcheck_latency = self._healthcheck_measure_latency(record) healthcheck_latency = self._healthcheck_measure_latency(record)
healthcheck_interval = self._healthcheck_request_interval(record)
try: try:
health_check_id = rrset['HealthCheckId'] health_check_id = rrset['HealthCheckId']
@ -1249,6 +1270,7 @@ class Route53Provider(BaseProvider):
healthcheck_protocol, healthcheck_protocol,
healthcheck_port, healthcheck_port,
healthcheck_latency, healthcheck_latency,
healthcheck_interval,
health_check): health_check):
# it has the right health check # it has the right health check
return False return False


+ 64
- 20
tests/test_octodns_provider_route53.py View File

@ -12,9 +12,9 @@ from unittest import TestCase
from mock import patch from mock import patch
from octodns.record import Create, Delete, Record, Update from octodns.record import Create, Delete, Record, Update
from octodns.provider.route53 import Route53Provider, _Route53GeoDefault, \
_Route53DynamicValue, _Route53GeoRecord, _Route53Record, _mod_keyer, \
_octal_replace
from octodns.provider.route53 import Route53Provider, _Route53DynamicValue, \
_Route53GeoDefault, _Route53GeoRecord, Route53ProviderException, \
_Route53Record, _mod_keyer, _octal_replace
from octodns.zone import Zone from octodns.zone import Zone
from helpers import GeoProvider from helpers import GeoProvider
@ -304,6 +304,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}, { }, {
@ -317,6 +318,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 42, 'HealthCheckVersion': 42,
}, { }, {
@ -330,6 +332,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}, { }, {
@ -343,6 +346,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}, { }, {
@ -357,6 +361,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}] }]
@ -1023,6 +1028,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}, { }, {
@ -1036,6 +1042,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}] }]
@ -1059,6 +1066,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}] }]
@ -1108,6 +1116,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}, { }, {
@ -1121,6 +1130,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}] }]
@ -1242,9 +1252,9 @@ class TestRoute53Provider(TestCase):
self.assertEquals('42', id) self.assertEquals('42', id)
stubber.assert_no_pending_responses() stubber.assert_no_pending_responses()
def test_health_check_measure_latency(self):
def test_health_check_provider_options(self):
provider, stubber = self._get_stubbed_provider() provider, stubber = self._get_stubbed_provider()
record_true = Record.new(self.expected, 'a', {
record = Record.new(self.expected, 'a', {
'ttl': 61, 'ttl': 61,
'type': 'A', 'type': 'A',
'value': '1.2.3.4', 'value': '1.2.3.4',
@ -1253,23 +1263,28 @@ class TestRoute53Provider(TestCase):
}, },
'route53': { 'route53': {
'healthcheck': { 'healthcheck': {
'measure_latency': True
'measure_latency': True,
'request_interval': 10,
} }
} }
} }
}) })
measure_latency = provider._healthcheck_measure_latency(record_true)
self.assertTrue(measure_latency)
latency = provider._healthcheck_measure_latency(record)
interval = provider._healthcheck_request_interval(record)
self.assertTrue(latency)
self.assertEquals(10, interval)
record_default = Record.new(self.expected, 'a', { record_default = Record.new(self.expected, 'a', {
'ttl': 61, 'ttl': 61,
'type': 'A', 'type': 'A',
'value': '1.2.3.4', 'value': '1.2.3.4',
}) })
measure_latency = provider._healthcheck_measure_latency(record_default)
self.assertTrue(measure_latency)
latency = provider._healthcheck_measure_latency(record_default)
interval = provider._healthcheck_request_interval(record_default)
self.assertTrue(latency)
self.assertEquals(10, interval)
record_false = Record.new(self.expected, 'a', {
record = Record.new(self.expected, 'a', {
'ttl': 61, 'ttl': 61,
'type': 'A', 'type': 'A',
'value': '1.2.3.4', 'value': '1.2.3.4',
@ -1278,15 +1293,35 @@ class TestRoute53Provider(TestCase):
}, },
'route53': { 'route53': {
'healthcheck': { 'healthcheck': {
'measure_latency': False
'measure_latency': False,
'request_interval': 30,
} }
} }
} }
}) })
measure_latency = provider._healthcheck_measure_latency(record_false)
self.assertFalse(measure_latency)
latency = provider._healthcheck_measure_latency(record)
interval = provider._healthcheck_request_interval(record)
self.assertFalse(latency)
self.assertEquals(30, interval)
def test_create_health_checks_measure_latency(self):
record_invalid = Record.new(self.expected, 'a', {
'ttl': 61,
'type': 'A',
'value': '1.2.3.4',
'octodns': {
'healthcheck': {
},
'route53': {
'healthcheck': {
'request_interval': 20,
}
}
}
})
with self.assertRaises(Route53ProviderException):
interval = provider._healthcheck_request_interval(record_invalid)
def test_create_health_checks_provider_options(self):
provider, stubber = self._get_stubbed_provider() provider, stubber = self._get_stubbed_provider()
health_check_config = { health_check_config = {
@ -1296,7 +1331,7 @@ class TestRoute53Provider(TestCase):
'IPAddress': '1.2.3.4', 'IPAddress': '1.2.3.4',
'MeasureLatency': False, 'MeasureLatency': False,
'Port': 443, 'Port': 443,
'RequestInterval': 10,
'RequestInterval': 30,
'ResourcePath': '/_dns', 'ResourcePath': '/_dns',
'Type': 'HTTPS' 'Type': 'HTTPS'
} }
@ -1335,7 +1370,8 @@ class TestRoute53Provider(TestCase):
}, },
'route53': { 'route53': {
'healthcheck': { 'healthcheck': {
'measure_latency': False
'measure_latency': False,
'request_interval': 30
} }
} }
} }
@ -1344,7 +1380,9 @@ class TestRoute53Provider(TestCase):
value = record.geo['AF'].values[0] value = record.geo['AF'].values[0]
id = provider.get_health_check_id(record, value, True) id = provider.get_health_check_id(record, value, True)
ml = provider.health_checks[id]['HealthCheckConfig']['MeasureLatency'] ml = provider.health_checks[id]['HealthCheckConfig']['MeasureLatency']
self.assertEqual(False, ml)
ri = provider.health_checks[id]['HealthCheckConfig']['RequestInterval']
self.assertFalse(ml)
self.assertEquals(30, ri)
def test_health_check_gc(self): def test_health_check_gc(self):
provider, stubber = self._get_stubbed_provider() provider, stubber = self._get_stubbed_provider()
@ -1436,6 +1474,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}, { }, {
@ -1449,6 +1488,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}, { }, {
@ -1462,6 +1502,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}] }]
@ -1639,6 +1680,7 @@ class TestRoute53Provider(TestCase):
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True, 'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}], }],
@ -1742,7 +1784,8 @@ class TestRoute53Provider(TestCase):
'ResourcePath': '/_dns', 'ResourcePath': '/_dns',
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True
'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}], }],
@ -1890,7 +1933,8 @@ class TestRoute53Provider(TestCase):
'ResourcePath': '/_dns', 'ResourcePath': '/_dns',
'Type': 'HTTPS', 'Type': 'HTTPS',
'Port': 443, 'Port': 443,
'MeasureLatency': True
'MeasureLatency': True,
'RequestInterval': 10,
}, },
'HealthCheckVersion': 2, 'HealthCheckVersion': 2,
}], }],


Loading…
Cancel
Save