def test_markProxyForUpdate_sets_needsProxyUpdate_and_starts_process(self): listener = MagicMock() service = RegionControllerService(listener) mock_startProcessing = self.patch(service, "startProcessing") service.markProxyForUpdate(None, None) self.assertTrue(service.needsProxyUpdate) self.assertThat(mock_startProcessing, MockCalledOnceWith())
def test_rbacSync_syncs_on_changes(self): RBACLastSync.objects.create(resource_type="resource-pool", sync_id="a-b-c") RBACSync.objects.clear("resource-pool") _, resources = self.make_resource_pools() reasons = [ sync.source for sync in RBACSync.objects.changes("resource-pool") ] rbac_client = MagicMock() rbac_client.update_resources.return_value = "x-y-z" service = RegionControllerService(sentinel.listener) self.patch(service, "_getRBACClient").return_value = rbac_client service.rbacInit = True self.assertEqual(reasons, service._rbacSync()) self.assertThat( rbac_client.update_resources, MockCalledOnceWith( "resource-pool", updates=resources[1:], removals=set(), last_sync_id="a-b-c", ), ) self.assertFalse(RBACSync.objects.exists()) last_sync = RBACLastSync.objects.get() self.assertEqual(last_sync.resource_type, "resource-pool") self.assertEqual(last_sync.sync_id, "x-y-z")
def test_startProcessing_calls_start_when_looping_call_not_running(self): service = RegionControllerService(sentinel.listener) mock_start = self.patch(service.processing, "start") service.startProcessing() self.assertThat( mock_start, MockCalledOnceWith(0.1, now=False))
def test__check_serial_doesnt_raise_error_on_successful_serial_match(self): service = RegionControllerService(sentinel.listener) result_serial = random.randint(1, 1000) formatted_serial = '{0:10d}'.format(result_serial) dns_names = [factory.make_name('domain') for _ in range(3)] # Mock pause so test runs faster. self.patch(region_controller, "pause").return_value = succeed(None) mock_lookup = self.patch(service.dnsResolver, "lookupAuthority") mock_lookup.side_effect = [ # First pass no results. succeed(([], [], [])), succeed(([], [], [])), succeed(([], [], [])), # First domain valid result. succeed(([self.make_soa_result(result_serial)], [], [])), succeed(([], [], [])), succeed(([], [], [])), # Second domain wrong serial. succeed(([self.make_soa_result(result_serial - 1)], [], [])), succeed(([], [], [])), # Third domain correct serial. succeed(([], [], [])), succeed(([self.make_soa_result(result_serial)], [], [])), # Second domain correct serial. succeed(([self.make_soa_result(result_serial)], [], [])), ] # Error should not be raised. return service._checkSerial((formatted_serial, dns_names))
def test_startService_calls_markDNSForUpdate(self): listener = MagicMock() service = RegionControllerService(listener) mock_markDNSForUpdate = self.patch(service, "markDNSForUpdate") service.startService() yield service.processingDefer self.assertThat(mock_markDNSForUpdate, MockCalledOnceWith(None, None))
def test__rbacSync_syncs_all_on_conflict(self): RBACLastSync.objects.create( resource_type='resource-pool', sync_id='a-b-c') RBACSync.objects.clear('resource-pool') _, resources = self.make_resource_pools() reasons = [ sync.source for sync in RBACSync.objects.changes('resource-pool') ] rbac_client = MagicMock() rbac_client.update_resources.side_effect = [ SyncConflictError(), 'x-y-z', ] service = RegionControllerService(sentinel.listener) self.patch(service, '_getRBACClient').return_value = rbac_client service.rbacInit = True self.assertEquals(reasons, service._rbacSync()) self.assertThat( rbac_client.update_resources, MockCallsMatch( call( 'resource-pool', updates=resources[1:], removals=set(), last_sync_id='a-b-c'), call('resource-pool', updates=resources))) self.assertFalse(RBACSync.objects.exists()) last_sync = RBACLastSync.objects.get() self.assertEqual(last_sync.resource_type, 'resource-pool') self.assertEqual(last_sync.sync_id, 'x-y-z')
def test_process_doesnt_update_zones_when_nothing_to_process(self): service = RegionControllerService(sentinel.listener) service.needsDNSUpdate = False mock_dns_update_all_zones = self.patch(region_controller, "dns_update_all_zones") service.startProcessing() yield service.processingDefer self.assertThat(mock_dns_update_all_zones, MockNotCalled())
def test_stopService_calls_unregister_on_the_listener(self): listener = MagicMock() service = RegionControllerService(listener) service.stopService() self.assertThat( listener.unregister, MockCallsMatch(call("sys_dns", service.markDNSForUpdate), call("sys_proxy", service.markProxyForUpdate)))
def test_process_doesnt_proxy_update_config_when_nothing_to_process(self): service = RegionControllerService(sentinel.listener) service.needsProxyUpdate = False mock_proxy_update_config = self.patch(region_controller, "proxy_update_config") service.startProcessing() yield service.processingDefer self.assertThat(mock_proxy_update_config, MockNotCalled())
def test_startService_registers_with_postgres_listener(self): listener = MagicMock() service = RegionControllerService(listener) service.startService() yield service.processingDefer self.assertThat( listener.register, MockCallsMatch(call("sys_dns", service.markDNSForUpdate), call("sys_proxy", service.markProxyForUpdate)))
def test_process_updates_zones_logs_failure(self): service = RegionControllerService(sentinel.listener) service.needsDNSUpdate = True mock_dns_update_all_zones = self.patch(region_controller, "dns_update_all_zones") mock_dns_update_all_zones.side_effect = factory.make_exception() mock_err = self.patch(region_controller.log, "err") service.startProcessing() yield service.processingDefer self.assertThat(mock_dns_update_all_zones, MockCalledOnceWith()) self.assertThat(mock_err, MockCalledOnceWith(ANY, "Failed configuring DNS."))
def test__check_serial_handles_TimeoutError(self): service = RegionControllerService(sentinel.listener) result_serial = random.randint(1, 1000) formatted_serial = '{0:10d}'.format(result_serial) dns_names = [factory.make_name('domain') for _ in range(3)] # Mock pause so test runs faster. self.patch(region_controller, "pause").return_value = succeed(None) mock_lookup = self.patch(service.dnsResolver, "lookupAuthority") mock_lookup.side_effect = TimeoutError() # Error should not be raised. with ExpectedException(DNSReloadError): yield service._checkSerial((formatted_serial, dns_names))
def test_process_updates_proxy_logs_failure(self): service = RegionControllerService(sentinel.listener) service.needsProxyUpdate = True mock_proxy_update_config = self.patch(region_controller, "proxy_update_config") mock_proxy_update_config.return_value = fail(factory.make_exception()) mock_err = self.patch(region_controller.log, "err") service.startProcessing() yield service.processingDefer self.assertThat(mock_proxy_update_config, MockCalledOnceWith(reload_proxy=True)) self.assertThat(mock_err, MockCalledOnceWith(ANY, "Failed configuring proxy."))
def test_process_updates_zones(self): service = RegionControllerService(sentinel.listener) service.needsDNSUpdate = True mock_dns_update_all_zones = self.patch( region_controller, "dns_update_all_zones") mock_msg = self.patch( region_controller.log, "msg") service.startProcessing() yield service.processingDefer self.assertThat(mock_dns_update_all_zones, MockCalledOnceWith()) self.assertThat( mock_msg, MockCalledOnceWith("Successfully configured DNS."))
def test_process_updates_proxy(self): service = RegionControllerService(sentinel.listener) service.needsProxyUpdate = True mock_proxy_update_config = self.patch(region_controller, "proxy_update_config") mock_proxy_update_config.return_value = succeed(None) mock_msg = self.patch(region_controller.log, "msg") service.startProcessing() yield service.processingDefer self.assertThat(mock_proxy_update_config, MockCalledOnceWith(reload_proxy=True)) self.assertThat(mock_msg, MockCalledOnceWith("Successfully configured proxy."))
def test__rbacSync_syncs_on_init(self): RBACSync.objects.clear('resource-pool') _, resources = self.make_resource_pools() rbac_client = MagicMock() rbac_client.update_resources.return_value = 'x-y-z' service = RegionControllerService(sentinel.listener) self.patch(service, '_getRBACClient').return_value = rbac_client self.assertEquals([], service._rbacSync()) self.assertThat(rbac_client.update_resources, MockCalledOnceWith('resource-pool', updates=resources)) self.assertFalse(RBACSync.objects.exists()) last_sync = RBACLastSync.objects.get() self.assertEqual(last_sync.resource_type, 'resource-pool') self.assertEqual(last_sync.sync_id, 'x-y-z')
def test__rbacSync_update_sync_id(self): rbac_sync = RBACLastSync.objects.create( resource_type='resource-pool', sync_id='a-b-c') RBACSync.objects.clear('resource-pool') _, resources = self.make_resource_pools() rbac_client = MagicMock() rbac_client.update_resources.return_value = 'x-y-z' service = RegionControllerService(sentinel.listener) self.patch(service, '_getRBACClient').return_value = rbac_client service.rbacInit = True service._rbacSync() last_sync = RBACLastSync.objects.get() self.assertEqual(rbac_sync.id, last_sync.id) self.assertEqual(last_sync.resource_type, 'resource-pool') self.assertEqual(last_sync.sync_id, 'x-y-z')
def test_init_sets_properties(self): service = RegionControllerService(sentinel.listener) self.assertThat( service, MatchesStructure.byEquality(clock=reactor, processingDefer=None, needsDNSUpdate=False, postgresListener=sentinel.listener))
def test_process_updates_zones(self): service = RegionControllerService(sentinel.listener) service.needsDNSUpdate = True dns_result = (random.randint(1, 1000), [factory.make_name('domain') for _ in range(3)]) mock_dns_update_all_zones = self.patch(region_controller, "dns_update_all_zones") mock_dns_update_all_zones.return_value = dns_result mock_check_serial = self.patch(service, "_checkSerial") mock_check_serial.return_value = succeed(dns_result) mock_msg = self.patch(region_controller.log, "msg") service.startProcessing() yield service.processingDefer self.assertThat(mock_dns_update_all_zones, MockCalledOnceWith()) self.assertThat(mock_check_serial, MockCalledOnceWith(dns_result)) self.assertThat( mock_msg, MockCalledOnceWith("Reloaded DNS configuration; regiond started."))
def test_process_updates_zones_logs_reason_for_multiple_updates(self): # Create some fake serial updates with sources for the update. def _create_publications(): return [ DNSPublication.objects.create( source=factory.make_name('reason')) for _ in range(3) ] publications = yield deferToDatabase(_create_publications) service = RegionControllerService(sentinel.listener) service.needsDNSUpdate = True service.previousSerial = publications[0].serial dns_result = (publications[-1].serial, [factory.make_name('domain') for _ in range(3)]) mock_dns_update_all_zones = self.patch(region_controller, "dns_update_all_zones") mock_dns_update_all_zones.return_value = dns_result mock_check_serial = self.patch(service, "_checkSerial") mock_check_serial.return_value = succeed(dns_result) mock_msg = self.patch(region_controller.log, "msg") service.startProcessing() yield service.processingDefer expected_msg = "Reloaded DNS configuration: \n" expected_msg += '\n'.join( ' * %s' % publication.source for publication in reversed(publications[1:])) self.assertThat(mock_dns_update_all_zones, MockCalledOnceWith()) self.assertThat(mock_check_serial, MockCalledOnceWith(dns_result)) self.assertThat(mock_msg, MockCalledOnceWith(expected_msg))
def test_process_updates_zones_logs_reason_for_single_update(self): # Create some fake serial updates with sources for the update. def _create_publications(): return [ DNSPublication.objects.create( source=factory.make_name("reason")) for _ in range(2) ] publications = yield deferToDatabase(_create_publications) service = RegionControllerService(sentinel.listener) service.needsDNSUpdate = True service.previousSerial = publications[0].serial dns_result = ( publications[-1].serial, True, [factory.make_name("domain") for _ in range(3)], ) mock_dns_update_all_zones = self.patch(region_controller, "dns_update_all_zones") mock_dns_update_all_zones.return_value = dns_result mock_check_serial = self.patch(service, "_checkSerial") mock_check_serial.return_value = succeed(dns_result) mock_msg = self.patch(region_controller.log, "msg") service.startProcessing() yield service.processingDefer self.assertThat(mock_dns_update_all_zones, MockCalledOnceWith()) self.assertThat(mock_check_serial, MockCalledOnceWith(dns_result)) self.assertThat( mock_msg, MockCalledOnceWith("Reloaded DNS configuration; %s" % (publications[-1].source)), )
def test_rbacSync_syncs_on_full_change(self): _, resources = self.make_resource_pools() RBACSync.objects.clear("resource-pool") RBACSync.objects.clear("") RBACSync.objects.create(resource_type="", resource_name="", source="test") rbac_client = MagicMock() rbac_client.update_resources.return_value = "x-y-z" service = RegionControllerService(sentinel.listener) self.patch(service, "_getRBACClient").return_value = rbac_client self.assertEqual([], service._rbacSync()) self.assertThat( rbac_client.update_resources, MockCalledOnceWith("resource-pool", updates=resources), ) self.assertFalse(RBACSync.objects.exists()) last_sync = RBACLastSync.objects.get() self.assertEqual(last_sync.resource_type, "resource-pool") self.assertEqual(last_sync.sync_id, "x-y-z")
def test_process_updates_bind_and_proxy(self): service = RegionControllerService(sentinel.listener) service.needsDNSUpdate = True service.needsProxyUpdate = True mock_dns_update_all_zones = self.patch( region_controller, "dns_update_all_zones") mock_proxy_update_config = self.patch( region_controller, "proxy_update_config") mock_proxy_update_config.return_value = succeed(None) service.startProcessing() yield service.processingDefer self.assertThat( mock_dns_update_all_zones, MockCalledOnceWith()) self.assertThat( mock_proxy_update_config, MockCalledOnceWith(reload_proxy=True))
def test_process_updates_bind_and_proxy(self): service = RegionControllerService(sentinel.listener) service.needsDNSUpdate = True service.needsProxyUpdate = True dns_result = (random.randint(1, 1000), [factory.make_name('domain') for _ in range(3)]) mock_dns_update_all_zones = self.patch(region_controller, "dns_update_all_zones") mock_dns_update_all_zones.return_value = dns_result mock_check_serial = self.patch(service, "_checkSerial") mock_check_serial.return_value = succeed(dns_result) mock_proxy_update_config = self.patch(region_controller, "proxy_update_config") mock_proxy_update_config.return_value = succeed(None) service.startProcessing() yield service.processingDefer self.assertThat(mock_dns_update_all_zones, MockCalledOnceWith()) self.assertThat(mock_check_serial, MockCalledOnceWith(dns_result)) self.assertThat(mock_proxy_update_config, MockCalledOnceWith(reload_proxy=True))
def test__rbacSync_returns_None_and_clears_sync_when_no_client(self): RBACSync.objects.create(resource_type='resource-pool') service = RegionControllerService(sentinel.listener) self.assertIsNone(service._rbacSync()) self.assertFalse(RBACSync.objects.exists())
def test__rbacSync_returns_None_when_nothing_to_do(self): RBACSync.objects.clear('resource-pool') service = RegionControllerService(sentinel.listener) service.rbacInit = True self.assertIsNone(service._rbacSync())
def test_stopService_handles_canceling_processing(self): listener = MagicMock() service = RegionControllerService(listener) service.startProcessing() yield service.stopService() self.assertIsNone(service.processingDefer)
def test_startProcessing_doesnt_call_start_when_looping_call_running(self): service = RegionControllerService(sentinel.listener) mock_start = self.patch(service.processing, "start") service.processing.running = True service.startProcessing() self.assertThat(mock_start, MockNotCalled())
def make_service(self, listener): # Don't retry on failure or the tests will loop forever. return RegionControllerService(listener, retryOnFailure=False)
def test_process_stops_processing(self): service = RegionControllerService(sentinel.listener) service.needsDNSUpdate = False service.startProcessing() yield service.processingDefer self.assertIsNone(service.processingDefer)