diff --git a/docs/dynamic_records.md b/docs/dynamic_records.md index 706173a..a992eda 100644 --- a/docs/dynamic_records.md +++ b/docs/dynamic_records.md @@ -110,6 +110,7 @@ test: | Key | Description | Default | |--|--|--| | measure_latency | Show latency in AWS console | true | +| request_interval | Healthcheck interval [10\|30] seconds | 10 | ```yaml @@ -123,4 +124,5 @@ test: route53: healthcheck: measure_latency: false + request_interval: 30 ``` diff --git a/docs/geo_records.md b/docs/geo_records.md index e365f57..ba99260 100644 --- a/docs/geo_records.md +++ b/docs/geo_records.md @@ -86,6 +86,7 @@ test: | Key | Description | Default | |--|--|--| | measure_latency | Show latency in AWS console | true | +| request_interval | Healthcheck interval [10\|30] seconds | 10 | ```yaml --- @@ -98,4 +99,5 @@ test: route53: healthcheck: measure_latency: false + request_interval: 30 ``` diff --git a/octodns/provider/route53.py b/octodns/provider/route53.py index 8e9ee4f..0d5bab9 100644 --- a/octodns/provider/route53.py +++ b/octodns/provider/route53.py @@ -512,6 +512,10 @@ class _Route53GeoRecord(_Route53Record): self.values) +class Route53ProviderException(Exception): + pass + + def _mod_keyer(mod): rrset = mod['ResourceRecordSet'] @@ -1031,8 +1035,20 @@ class Route53Provider(BaseProvider): .get('healthcheck', {}) \ .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, - measure_latency, health_check, value=None): + measure_latency, request_interval, + health_check, value=None): config = health_check['HealthCheckConfig'] # So interestingly Route53 normalizes IPAddress which will cause us to @@ -1050,9 +1066,10 @@ class Route53Provider(BaseProvider): None) resource_path = config.get('ResourcePath', None) 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 \ + request_interval == config['RequestInterval'] and \ value == config_ip_address def get_health_check_id(self, record, value, create): @@ -1077,6 +1094,7 @@ class Route53Provider(BaseProvider): healthcheck_protocol = record.healthcheck_protocol healthcheck_port = record.healthcheck_port 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 # type, we'll ignore anything else @@ -1091,6 +1109,7 @@ class Route53Provider(BaseProvider): healthcheck_protocol, healthcheck_port, healthcheck_latency, + healthcheck_interval, health_check, value=value): # this is the health check we're looking for @@ -1108,7 +1127,7 @@ class Route53Provider(BaseProvider): 'FailureThreshold': 6, 'MeasureLatency': healthcheck_latency, 'Port': healthcheck_port, - 'RequestInterval': 10, + 'RequestInterval': healthcheck_interval, 'Type': healthcheck_protocol, } if healthcheck_protocol != 'TCP': @@ -1143,9 +1162,10 @@ class Route53Provider(BaseProvider): self._health_checks[id] = health_check self.log.info('get_health_check_id: created id=%s, host=%s, ' '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_latency, value) + healthcheck_latency, healthcheck_interval, value) return id def _gc_health_checks(self, record, new): @@ -1238,6 +1258,7 @@ class Route53Provider(BaseProvider): healthcheck_protocol = record.healthcheck_protocol healthcheck_port = record.healthcheck_port healthcheck_latency = self._healthcheck_measure_latency(record) + healthcheck_interval = self._healthcheck_request_interval(record) try: health_check_id = rrset['HealthCheckId'] @@ -1249,6 +1270,7 @@ class Route53Provider(BaseProvider): healthcheck_protocol, healthcheck_port, healthcheck_latency, + healthcheck_interval, health_check): # it has the right health check return False diff --git a/tests/test_octodns_provider_route53.py b/tests/test_octodns_provider_route53.py index 543a506..a2b61e7 100644 --- a/tests/test_octodns_provider_route53.py +++ b/tests/test_octodns_provider_route53.py @@ -12,9 +12,9 @@ from unittest import TestCase from mock import patch 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 helpers import GeoProvider @@ -304,6 +304,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }, { @@ -317,6 +318,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 42, }, { @@ -330,6 +332,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }, { @@ -343,6 +346,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }, { @@ -357,6 +361,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }] @@ -1023,6 +1028,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }, { @@ -1036,6 +1042,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }] @@ -1059,6 +1066,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }] @@ -1108,6 +1116,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }, { @@ -1121,6 +1130,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }] @@ -1242,9 +1252,9 @@ class TestRoute53Provider(TestCase): self.assertEquals('42', id) 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() - record_true = Record.new(self.expected, 'a', { + record = Record.new(self.expected, 'a', { 'ttl': 61, 'type': 'A', 'value': '1.2.3.4', @@ -1253,23 +1263,28 @@ class TestRoute53Provider(TestCase): }, 'route53': { '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', { 'ttl': 61, 'type': 'A', '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, 'type': 'A', 'value': '1.2.3.4', @@ -1278,15 +1293,35 @@ class TestRoute53Provider(TestCase): }, 'route53': { '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() health_check_config = { @@ -1296,7 +1331,7 @@ class TestRoute53Provider(TestCase): 'IPAddress': '1.2.3.4', 'MeasureLatency': False, 'Port': 443, - 'RequestInterval': 10, + 'RequestInterval': 30, 'ResourcePath': '/_dns', 'Type': 'HTTPS' } @@ -1335,7 +1370,8 @@ class TestRoute53Provider(TestCase): }, 'route53': { 'healthcheck': { - 'measure_latency': False + 'measure_latency': False, + 'request_interval': 30 } } } @@ -1344,7 +1380,9 @@ class TestRoute53Provider(TestCase): value = record.geo['AF'].values[0] id = provider.get_health_check_id(record, value, True) 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): provider, stubber = self._get_stubbed_provider() @@ -1436,6 +1474,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }, { @@ -1449,6 +1488,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }, { @@ -1462,6 +1502,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }] @@ -1639,6 +1680,7 @@ class TestRoute53Provider(TestCase): 'Type': 'HTTPS', 'Port': 443, 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }], @@ -1742,7 +1784,8 @@ class TestRoute53Provider(TestCase): 'ResourcePath': '/_dns', 'Type': 'HTTPS', 'Port': 443, - 'MeasureLatency': True + 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }], @@ -1890,7 +1933,8 @@ class TestRoute53Provider(TestCase): 'ResourcePath': '/_dns', 'Type': 'HTTPS', 'Port': 443, - 'MeasureLatency': True + 'MeasureLatency': True, + 'RequestInterval': 10, }, 'HealthCheckVersion': 2, }],