def test_handling_delete(self): handler = CleanupResourceHandler(route53_client=mock.Mock(), monitor_interval=0) record_set_accessor = mock.Mock() record_set_accessor.delete = mock.Mock(return_value=True) # True = Deleted exists_count = 0 def exists_side_effect(*args): nonlocal exists_count exists_count += 1 return True if exists_count < 3 else False record_set_accessor.exists = mock.Mock(side_effect=exists_side_effect) handler.record_set_accessor = record_set_accessor event = { 'RequestType': 'Delete', 'ResourceProperties': { 'ServiceToken': 'Something', 'HostedZoneId': 'ZONE', 'RecordName': 'something.mydomain.com' } } # WHEN handler.handle_event(event, {}) # THEN expected_locator = Route53RecordSetLocator(hosted_zone_id='ZONE', record_name='something.mydomain.com') record_set_accessor.delete.assert_called_with(locator=expected_locator) record_set_accessor.exists.assert_called() self.assertEqual(record_set_accessor.exists.call_count, 3)
def test_deleting_records(self): # GIVEN route53_client = self.get_route53_client_mock() locator = Route53RecordSetLocator(hosted_zone_id='foo', record_name='foo.myexample.com') record_set = Route53RecordSetAccessor(route53_client) # Set up the mock with a record. record_set.update(locator, ipv4s={'1.1.1.1'}) # WHEN record_set.update(locator, ipv4s=set()) # THEN route53_client.change_resource_record_sets.assert_called_with( HostedZoneId='foo', ChangeBatch={ 'Comment': 'Automatic', 'Changes': [{ 'Action': 'DELETE', 'ResourceRecordSet': { 'Name': 'foo.myexample.com.', 'Type': 'A', 'ResourceRecords': [ { 'Value': '1.1.1.1' }, ], 'TTL': 60 } }] })
def test_update_record_sets(self): # GIVEN ddb_record = DdbRecord( key=DdbRecordKey(cluster_arn='a', service_name='b')) ord1 = [ Route53RecordSetLocator('a', 'b'), Route53RecordSetLocator('a', 'c'), ] ord2 = [ Route53RecordSetLocator('a', 'b'), ] # WHEN update_ddb_record(ddb_record, RecordUpdate(record_sets_added=ord1)) update_ddb_record(ddb_record, RecordUpdate(record_sets_removed=ord2)) # THEN self.assertEqual(len(ddb_record.record_sets), 1) self.assertTrue( Route53RecordSetLocator('a', 'c') in ddb_record.record_sets)
def test_creating_empty_records(self): # GIVEN route53_client = self.get_route53_client_mock() locator = Route53RecordSetLocator(hosted_zone_id='foo', record_name='foo.myexample.com') merger = Route53RecordSetAccessor(route53_client) # WHEN merger.update(locator, ipv4s=set()) # THEN route53_client.change_resource_record_sets.assert_not_called()
def test_checks_not_exists(self): # GIVEN route53_client = self.get_route53_client_mock() locator = Route53RecordSetLocator(hosted_zone_id='foo', record_name='foo.myexample.com') record_set = Route53RecordSetAccessor(route53_client) # WHEN exists = record_set.exists(locator) # THEN self.assertTrue(not exists)
def test_deleting_no_records_with_frontend(self): # GIVEN route53_client = self.get_route53_client_mock() locator = Route53RecordSetLocator(hosted_zone_id='foo', record_name='foo.myexample.com') record_set = Route53RecordSetAccessor(route53_client) # WHEN record_set.delete(locator) # THEN self.assertEqual(route53_client.list_resource_record_sets.call_count, 1) route53_client.change_resource_record_sets.assert_not_called()
def on_delete(self, resource_properties: CleanupResourceProperties): locator = Route53RecordSetLocator( hosted_zone_id=resource_properties.HostedZoneId, record_name=resource_properties.RecordName) deleted = self.record_set_accessor.delete(locator=locator) if deleted: logging.info(f'Monitoring for the record deletion') for interval_number in range(1, 10): if not self.record_set_accessor.exists(locator): logging.info(f'The record has been deleted') return else: logging.info(f'The record still exists') if self.monitor_interval > 0: time.sleep(self.monitor_interval)
def test_find_locator_record_set_ignores_irrelevant_records(self): # GIVEN locator = Route53RecordSetLocator( hosted_zone_id='foo', record_name='test-record.myexample.com') record_sets = [{ 'Name': 'u-record.myexample.com.', 'Type': 'A', 'TTL': 60, 'ResourceRecords': [{ 'Value': '1.1.1.1' }] }] # WHEN result = find_locator_record_set(locator, 'A', record_sets) # THEN self.assertIsNone(result)
def test_find_locator_record_set_finds_it(self): # GIVEN locator = Route53RecordSetLocator( hosted_zone_id='foo', record_name='test-record.myexample.com') matching_record = { 'Name': 'test-record.myexample.com.', 'Type': 'A', 'TTL': 60, 'ResourceRecords': [{ 'Value': '1.1.1.1' }] } record_sets = [matching_record] # WHEN result = find_locator_record_set(locator, 'A', record_sets) # THEN self.assertEqual(result, matching_record)
def __init__(self, ec2_client, route53_client, dynamodb_resource, environ): self.ec2_client = ec2_client self.route53_client = route53_client hosted_zone_id = environ['HOSTED_ZONE_ID'] record_name = environ['RECORD_NAME'] records_table = environ['RECORDS_TABLE'] cluster_arn = environ['CLUSTER_ARN'] self.service_name = environ['SERVICE_NAME'] self.records_table_key = DdbRecordKey(cluster_arn=cluster_arn, service_name=self.service_name) self.records_table_accessor = RecordsTableAccessor( table_client=dynamodb_resource.Table(records_table)) self.record_set_locator = Route53RecordSetLocator( hosted_zone_id=hosted_zone_id, record_name=record_name) self.record_set_accessor = Route53RecordSetAccessor( route53_client=self.route53_client)
def decode_record_set(self, data) -> Route53RecordSetLocator: hosted_zone_id = data[self.ATTR_RECORD_SET_ZONE] record_name = data[self.ATTR_RECORD_SET_NAME] return Route53RecordSetLocator(hosted_zone_id=hosted_zone_id, record_name=record_name)