def test_notification_endpoint_readonly(self): """Checks if conf is readonly.""" with self.assertRaises(AttributeError) as cm: conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') endpoint = K2hr3NotificationEndpoint(conf) new_conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') endpoint.conf = new_conf the_exception = cm.exception self.assertEqual("can't set attribute", '{}'.format(the_exception))
def test_payload_to_params_error_no_instance_id(self): """Checks if _payload_to_params() works correctly. The payload has no instance_id. """ # Ensure the __call_r3api is not called. self.patcher_call_r3api = patch.object( K2hr3NotificationEndpoint, '_K2hr3NotificationEndpoint__call_r3api') self.mock_method = self.patcher_call_r3api.start() self.mock_method.return_value = HANDLED self.addCleanup(self.patcher_call_r3api.stop) # input --- payload payload = { "invalid_named": "12345678-1234-5678-1234-567812345678", } # __call_r3api is mocked! no http request will send. conf = K2hr3Conf(conf_file_path) endpoint = K2hr3NotificationEndpoint(conf) result = endpoint.info(context={}, publisher_id='', event_type='', payload=payload, metadata={}) self.mock_method.mock_call_r3api.assert_not_called() # Ensucre the result of info is HANDLED. self.assertEqual(result, HANDLED)
def test_k2hr3_conf_assert_parse_config_called(self): """Asserts _parse_config method called from constructor.""" with patch.object(K2hr3Conf, '_parse_config', return_value=True) as mock_method: K2hr3Conf(conf_file_path) mock_method.assert_called_once_with()
def test_notification_endpoint_info_requeue_test_on_exception(self): """Checks if info works correctly. NotificationEndpoint::__call_r3api returns REQUEUE in this case. NotificationEndpoint::info() --> NotificationEndpoint::__call_r3api() --> _K2hr3UserAgent::send() # we mock this method. """ # _K2hr3UserAgent::send() is expected to raise _K2hr3UserAgentError. _K2hr3UserAgent.send = MagicMock( side_effect=_K2hr3UserAgentError('send error')) conf = K2hr3Conf(conf_file_path) conf.k2hr3.requeue_on_error = True # overwrites it True. endpoint = K2hr3NotificationEndpoint(conf) json_file_path = Path( os.sep.join( [here, '..', 'tools', 'data', 'notifications_neutron.json'])).resolve() with json_file_path.open() as fp: data = json.load(fp) result = endpoint.info(data['ctxt'], data['publisher_id'], data['event_type'], data['payload'], data['metadata']) # Ensure the__call_r3api is not called. self.assertEqual(result, REQUEUE)
def test_k2hr3_conf_construct_init_error(self): """Initialization error.""" with self.assertRaises(K2hr3ConfError) as cm: K2hr3Conf(broken_conf_file_path) the_exception = cm.exception self.assertRegex(the_exception.msg, '^parse error,.*')
def test_k2hr3_conf_construct_path_is_none(self): """Checks if the __init__'s path is None.""" with self.assertRaises(K2hr3ConfError) as cm: K2hr3Conf(None) the_exception = cm.exception self.assertEqual(the_exception.msg, 'Path expected, not NoneType')
def test_k2hr3_conf_oslo_messaging_notifications_metadata(self): """Asserts metadata in oslo_messaging_notifications group. The metadata is an optional NotificationFilter. """ conf = K2hr3Conf(conf_file_path) self.assertEqual(None, conf.oslo_messaging_notifications.metadata)
def test_k2hr3_conf_oslo_messaging_notifications_payload(self): """Asserts payload in oslo_messaging_notifications group. The payload is an optional NotificationFilter. """ conf = K2hr3Conf(conf_file_path) self.assertEqual(None, conf.oslo_messaging_notifications.payload)
def test_neutron_payload_to_params(self): """Checks if _payload_to_params() works correctly. The payload pattern is a neutron notification message. """ # input --- payload payload = { "port": { "device_id": "12345678-1234-5678-1234-567812345678", "fixed_ips": [{ "ip_address": "127.0.0.1", }, { "ip_address": "127.0.0.2", }] } } # output --- params expect_params = { 'cuk': '12345678-1234-5678-1234-567812345678', 'ips': ['127.0.0.1', '127.0.0.2'] } conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') endpoint = K2hr3NotificationEndpoint(conf) result = endpoint.info( context={}, publisher_id='', event_type='', payload=payload, metadata={}) # Ensure values are as expected at runtime. self.mock_method.assert_called_once_with(expect_params) # Ensucre the result of info is HANDLED. self.assertEqual(result, HANDLED)
def test_k2hr3_conf_oslo_messaging_notifications_context(self): """Asserts context in oslo_messaging_notifications group. The context is an optional NotificationFilter. """ conf = K2hr3Conf(conf_file_path) self.assertEqual(None, conf.oslo_messaging_notifications.context)
def test_nova_compute_payload_to_params(self): """Checks if _payload_to_params() works correctly. The payload pattern is a nova compute notification message. """ # input --- payload payload = { "nova_object.data": { "uuid": "12345678-1234-5678-1234-567812345678" }, "nova_object.version": "1.7" } # output --- params expect_params = {'cuk': '12345678-1234-5678-1234-567812345678'} conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') endpoint = K2hr3NotificationEndpoint(conf) result = endpoint.info( context={}, publisher_id='', event_type='', payload=payload, metadata={}) # Ensure values are as expected at runtime. self.mock_method.assert_called_once_with(expect_params) # Ensucre the result of info is HANDLED. self.assertEqual(result, HANDLED)
def test_k2hr3_conf_oslo_messaging_notifications_payload(self): """Asserts payload in oslo_messaging_notifications group. The payload is an optional NotificationFilter. """ conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') self.assertEqual(None, conf.oslo_messaging_notifications.payload)
def test_compute_payload_to_params(self): """Checks if _payload_to_params() works correctly. The payload pattern is a compute notification message. """ # Ensure values are as expected at runtime. self.patcher_call_r3api = patch.object( K2hr3NotificationEndpoint, '_K2hr3NotificationEndpoint__call_r3api') self.mock_method = self.patcher_call_r3api.start() self.mock_method.return_value = HANDLED self.addCleanup(self.patcher_call_r3api.stop) # input --- payload payload = { "instance_id": "12345678-1234-5678-1234-567812345678", } # output --- params expect_params = {'cuk': '12345678-1234-5678-1234-567812345678'} conf = K2hr3Conf(conf_file_path) endpoint = K2hr3NotificationEndpoint(conf) result = endpoint.info(context={}, publisher_id='', event_type='', payload=payload, metadata={}) self.mock_method.assert_called_once_with(expect_params) # Ensucre the result of info is HANDLED. self.assertEqual(result, HANDLED)
def test_k2hr3_conf_oslo_messaging_notifications_publisher_id(self): """Asserts publisher_id in oslo_messaging_notifications group. The publisher_id and the event_type are very important filter for this system. """ conf = K2hr3Conf(conf_file_path) self.assertEqual(r'^network.*$', conf.oslo_messaging_notifications.publisher_id)
def test_k2hr3_conf_oslo_messaging_notifications_event_type(self): """Asserts event_type in oslo_messaging_notifications group. The publisher_id and the event_type are very important filter for this system. """ conf = K2hr3Conf(conf_file_path) self.assertEqual(r'^port\.delete\.end$', conf.oslo_messaging_notifications.event_type)
def test_k2hr3_conf_assert_parse_config_called(self): """Asserts _parse_config method called from constructor.""" path = src_dir + '/etc/k2hr3_osnl.conf.sample' with patch.object(K2hr3Conf, '_parse_config', return_value=True) as mock_method: K2hr3Conf(path) mock_method.assert_called_once_with()
def setUp(self): """Sets up a test case.""" self._conf = K2hr3Conf(conf_file_path) self.patcher_call_send_agent = patch.object(_K2hr3UserAgent, '_send_internal') self.mock_method_agent = self.patcher_call_send_agent.start() self.mock_method_agent.return_value = True self.addCleanup(self.patcher_call_send_agent.stop)
def test_k2hr3_conf_construct_parse_error(self): """Checks if the __init__'s path is not a config file.""" path = os.path.abspath(__file__) with self.assertRaises(K2hr3ConfError) as cm: K2hr3Conf(path) the_exception = cm.exception self.assertRegex(the_exception.msg, '^parse error, Failed to parse {}.*'.format(path))
def test_k2hr3_conf_construct_path_is_dir(self): """Checks if the __init__'s path is a directory.""" path = Path('/tmp') with self.assertRaises(K2hr3ConfError) as cm: K2hr3Conf(path) the_exception = cm.exception self.assertEqual(the_exception.msg, 'path must be a regular file, not {}'.format(path))
def test_k2hr3_conf_construct_parse_error(self): """Checks if the __init__'s path is not a config file.""" path = Path(here) with self.assertRaises(K2hr3ConfError) as cm: K2hr3Conf(path) the_exception = cm.exception self.assertRegex(the_exception.msg, '^path must be a regular file, not {}.*'.format(path))
def test_k2hr3_conf_construct_path_is_not_readable(self): """Checks if the __init__'s path is not readable.""" path = '/etc/sudoers' with self.assertRaises(K2hr3ConfError) as cm: K2hr3Conf(path) the_exception = cm.exception self.assertEqual( the_exception.msg, 'path must be a readable regular file, not [Errno 13] Permission denied: \'{}\'' .format(path))
def main() -> int: """Runs a oslo_messaging notification listener for k2hr3. You can configure the listener by the config file. Simple usage: $ k2hr3_osnl -c etc/k2hr3_osnl.config :returns: 0 if success, otherwise 1. :rtype: int """ parser = argparse.ArgumentParser( description='An oslo.messaging notification listener for k2hr3.') parser.add_argument('-c', '--config-file', dest='config_file', default='/etc/k2hr3/k2hr3_osnl.conf', help='config file path') parser.add_argument( '-d', dest='debug_level', choices=('debug', 'info', 'warn', 'error', 'critical'), help='debug level. default: defined in the config_file') parser.add_argument( '-l', dest='libs_debug_level', choices=('debug', 'info', 'warn', 'error', 'critical'), help='dependent libraries loglevel. default: defined in the config_file' ) parser.add_argument( '-f', dest='log_file', help='log file path. default: defined in the config_file') parser.add_argument('-v', action='version', version='%(prog)s ' + __version__) args = parser.parse_args() try: conf = K2hr3Conf(Path(args.config_file)) _configure_logger(args, conf) # logger configured by args and conf. endpoints = [K2hr3NotificationEndpoint(conf)] sys.exit(listen(endpoints)) except K2hr3Error as error: LOG.error('K2hr3Error error, %s', error) raise K2hr3Error("K2hr3 RuntimeError") from error except Exception as error: LOG.error('Unknown error, %s', error) raise RuntimeError("Unknown RuntimeError") from error
def test_k2hr3_osnl_listen(self): """Executes the k2hr3_osnl main function.""" sys.argv[0] = 'me' sys.argv[1] = '-c' sys.argv.append(str(conf_file_path)) # Ensure k2hr3_osnl.listen called. with patch.object(oslo_messaging.get_notification_listener, 'start', return_value=None, side_effect=Exception('skip listening')): conf = K2hr3Conf(conf_file_path) endpoint = K2hr3NotificationEndpoint(conf) with self.assertRaises(Exception): k2hr3_osnl.listen(endpoint)
def test_notification_endpoint_info_r3api_failed(self): """Checks if info works correctly. NotificationEndpoint::info returns HANDLED if __call_r3api returns HANDLED. __call_r3api internally callses _K2hr3UserAgent::send() to call the R3 API. We mock the method to return False without having access to the API. """ conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') endpoint = K2hr3NotificationEndpoint(conf) _K2hr3UserAgent.send = MagicMock(return_value=False) with open(src_dir + '/tools/data/notifications_neutron.json') as fp: data = json.load(fp) result = endpoint.info(data['ctxt'], data['publisher_id'], data['event_type'], data['payload'], data['metadata']) self.assertEqual(result, HANDLED)
def test_notification_endpoint_call_r3api_exception_raise(self): """Checks if call_r3api works correctly. __call_r3api calls the _K2hr3UserAgent::send() to call the R3 API. We mock _K2hr3UserAgent::send() to throws an unknown exception. Then the function raises the exception again. K2hr3NotificationEndpoint::info() method will catch all exceptions then it returns HANDLED to the dispatcher. """ conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') _K2hr3UserAgent.send = MagicMock(side_effect=Exception('error')) endpoint = K2hr3NotificationEndpoint(conf) with open(src_dir + '/tools/data/notifications_neutron.json') as fp: data = json.load(fp) result = endpoint.info(data['ctxt'], data['publisher_id'], data['event_type'], data['payload'], data['metadata']) self.assertEqual(result, HANDLED)
def test_notification_endpoint_info_call_r3api_exception(self): """Checks if info works correctly. NotificationEndpoint::info returns HANDLED if the __call_r3api method throws other than K2hr3NotificationEndpointError excetion. """ payload = { "instance_id": "12345678-1234-5678-1234-567812345678", } with patch.object(K2hr3NotificationEndpoint, '_K2hr3NotificationEndpoint__call_r3api', side_effect=Exception('__call_r3api error')): conf = K2hr3Conf(conf_file_path) endpoint = K2hr3NotificationEndpoint(conf) result = endpoint.info(context={}, publisher_id='', event_type='', payload=payload, metadata={}) # Ensucre the result of info is HANDLED. self.assertEqual(result, HANDLED)
def test_notification_endpoint_info_r3api_failed_requeue(self): """Checks if info works correctly. NotificationEndpoint::info returns HANDLED if __call_r3api returns HANDLED. __call_r3api internally callses _K2hr3UserAgent::send() to call the R3 API. We mock the method to return False without having access to the API. """ # Expected return_value is REQUEUE in this case. self.mock_method.return_value = REQUEUE conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') conf.k2hr3.requeue_on_error = True endpoint = K2hr3NotificationEndpoint(conf) _K2hr3UserAgent.send = MagicMock(return_value=False) with open(src_dir + '/tools/data/notifications_neutron.json') as fp: data = json.load(fp) result = endpoint.info(data['ctxt'], data['publisher_id'], data['event_type'], data['payload'], data['metadata']) self.assertEqual(result, REQUEUE) # Reset it. Default return_value is HANDLED. self.mock_method.return_value = HANDLED
def test_notification_endpoint_info__payload_to_params_exception(self): """Checks if info works correctly. NotificationEndpoint::info returns HANDLED if the _payload_to_params method throws other than K2hr3NotificationEndpointError excetion. """ payload = { "instance_id": "12345678-1234-5678-1234-567812345678", } with patch.object( K2hr3NotificationEndpoint, '_payload_to_params', side_effect=Exception('_payload_to_params error')): conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') endpoint = K2hr3NotificationEndpoint(conf) result = endpoint.info( context={}, publisher_id='', event_type='', payload=payload, metadata={}) # Ensucre the result of info is HANDLED. self.assertEqual(result, HANDLED)
def test_notification_endpoint_call_r3api_requeue_on_exception(self): """Checks if call_r3api works correctly. __call_r3api calls the _K2hr3UserAgent::send() to call the R3 API. We mock _K2hr3UserAgent::send() to throws a _K2hr3UserAgentError. If requeue_on_error is true, then the function returns HANDLED. """ # Expected return_value is REQUEUE in this case. self.mock_method.return_value = REQUEUE conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') conf.k2hr3.requeue_on_error = True _K2hr3UserAgent.send = MagicMock( side_effect=_K2hr3UserAgentError('error')) endpoint = K2hr3NotificationEndpoint(conf) with open(src_dir + '/tools/data/notifications_neutron.json') as fp: data = json.load(fp) result = endpoint.info(data['ctxt'], data['publisher_id'], data['event_type'], data['payload'], data['metadata']) self.assertEqual(result, REQUEUE) # Reset it. Default return_value is HANDLED. self.mock_method.return_value = HANDLED
def test_payload_to_params_error_no_instance_id(self): """Checks if _payload_to_params() works correctly. The payload has no instance_id. """ # input --- payload payload = { "invalid_named": "12345678-1234-5678-1234-567812345678", } # __call_r3api is mocked! no http request will send. conf = K2hr3Conf(src_dir + '/etc/k2hr3_osnl.conf.sample') endpoint = K2hr3NotificationEndpoint(conf) result = endpoint.info( context={}, publisher_id='', event_type='', payload=payload, metadata={}) # Ensure the__call_r3api is not called. self.mock_method.mock_call_r3api.assert_not_called() # Ensucre the result of info is HANDLED. self.assertEqual(result, HANDLED)