Use a registry to configure reporting handlers.

Also ensure that the LogHandler is registered by default.

Change-Id: Ib9e306a0aa45ab6f5c9b543782b5dd7019b72cf1
This commit is contained in:
Daniel Watkins 2015-07-17 13:09:32 +01:00
parent 91a5942fb9
commit b5f5a16704
2 changed files with 39 additions and 21 deletions

View File

@ -12,6 +12,8 @@ report events in a structured manner.
import abc import abc
import logging import logging
from cloudinit.registry import DictRegistry
FINISH_EVENT_TYPE = 'finish' FINISH_EVENT_TYPE = 'finish'
START_EVENT_TYPE = 'start' START_EVENT_TYPE = 'start'
@ -63,7 +65,8 @@ class LogHandler(ReportingHandler):
logger.info(event.as_string()) logger.info(event.as_string())
HANDLERS = [LogHandler()] handler_registry = DictRegistry()
handler_registry.register_item('_logging', LogHandler())
def report_event(event): def report_event(event):
@ -76,7 +79,7 @@ def report_event(event):
The type of the event; this should be a constant from the The type of the event; this should be a constant from the
reporting module. reporting module.
""" """
for handler in HANDLERS: for _, handler in handler_registry.registered_items.items():
handler.publish_event(event) handler.publish_event(event)

View File

@ -10,17 +10,22 @@ from cloudinit.tests import TestCase
from cloudinit.tests.util import mock from cloudinit.tests.util import mock
def _fake_registry():
return mock.Mock(registered_items={'a': mock.MagicMock(),
'b': mock.MagicMock()})
class TestReportStartEvent(unittest.TestCase): class TestReportStartEvent(unittest.TestCase):
@mock.patch('cloudinit.reporting.HANDLERS', @mock.patch('cloudinit.reporting.handler_registry',
new_callable=lambda: [mock.MagicMock(), mock.MagicMock()]) new_callable=_fake_registry)
def test_report_start_event_passes_something_with_as_string_to_handlers( def test_report_start_event_passes_something_with_as_string_to_handlers(
self, HANDLERS): self, handler_registry):
event_name, event_description = 'my_test_event', 'my description' event_name, event_description = 'my_test_event', 'my description'
reporting.report_start_event(event_name, event_description) reporting.report_start_event(event_name, event_description)
expected_string_representation = ': '.join( expected_string_representation = ': '.join(
['start', event_name, event_description]) ['start', event_name, event_description])
for handler in HANDLERS: for _, handler in handler_registry.registered_items.items():
self.assertEqual(1, handler.publish_event.call_count) self.assertEqual(1, handler.publish_event.call_count)
event = handler.publish_event.call_args[0][0] event = handler.publish_event.call_args[0][0]
self.assertEqual(expected_string_representation, event.as_string()) self.assertEqual(expected_string_representation, event.as_string())
@ -36,42 +41,42 @@ class TestReportFinishEvent(unittest.TestCase):
def assertHandlersPassedObjectWithAsString( def assertHandlersPassedObjectWithAsString(
self, handlers, expected_as_string): self, handlers, expected_as_string):
for handler in handlers: for _, handler in handlers.items():
self.assertEqual(1, handler.publish_event.call_count) self.assertEqual(1, handler.publish_event.call_count)
event = handler.publish_event.call_args[0][0] event = handler.publish_event.call_args[0][0]
self.assertEqual(expected_as_string, event.as_string()) self.assertEqual(expected_as_string, event.as_string())
@mock.patch('cloudinit.reporting.HANDLERS', @mock.patch('cloudinit.reporting.handler_registry',
new_callable=lambda: [mock.MagicMock(), mock.MagicMock()]) new_callable=_fake_registry)
def test_report_finish_event_passes_something_with_as_string_to_handlers( def test_report_finish_event_passes_something_with_as_string_to_handlers(
self, HANDLERS): self, handler_registry):
event_name, event_description = self._report_finish_event() event_name, event_description = self._report_finish_event()
expected_string_representation = ': '.join( expected_string_representation = ': '.join(
['finish', event_name, event_description]) ['finish', event_name, event_description])
self.assertHandlersPassedObjectWithAsString( self.assertHandlersPassedObjectWithAsString(
HANDLERS, expected_string_representation) handler_registry.registered_items, expected_string_representation)
@mock.patch('cloudinit.reporting.HANDLERS', @mock.patch('cloudinit.reporting.handler_registry',
new_callable=lambda: [mock.MagicMock(), mock.MagicMock()]) new_callable=_fake_registry)
def test_reporting_successful_finish_has_sensible_string_repr(self, def test_reporting_successful_finish_has_sensible_string_repr(
HANDLERS): self, handler_registry):
event_name, event_description = self._report_finish_event( event_name, event_description = self._report_finish_event(
successful=True) successful=True)
expected_string_representation = ': '.join( expected_string_representation = ': '.join(
['finish', event_name, 'success', event_description]) ['finish', event_name, 'success', event_description])
self.assertHandlersPassedObjectWithAsString( self.assertHandlersPassedObjectWithAsString(
HANDLERS, expected_string_representation) handler_registry.registered_items, expected_string_representation)
@mock.patch('cloudinit.reporting.HANDLERS', @mock.patch('cloudinit.reporting.handler_registry',
new_callable=lambda: [mock.MagicMock(), mock.MagicMock()]) new_callable=_fake_registry)
def test_reporting_unsuccessful_finish_has_sensible_string_repr(self, def test_reporting_unsuccessful_finish_has_sensible_string_repr(
HANDLERS): self, handler_registry):
event_name, event_description = self._report_finish_event( event_name, event_description = self._report_finish_event(
successful=False) successful=False)
expected_string_representation = ': '.join( expected_string_representation = ': '.join(
['finish', event_name, 'fail', event_description]) ['finish', event_name, 'fail', event_description])
self.assertHandlersPassedObjectWithAsString( self.assertHandlersPassedObjectWithAsString(
HANDLERS, expected_string_representation) handler_registry.registered_items, expected_string_representation)
class TestReportingEvent(unittest.TestCase): class TestReportingEvent(unittest.TestCase):
@ -115,3 +120,13 @@ class TestLogHandler(TestCase):
reporting.LogHandler().publish_event(event) reporting.LogHandler().publish_event(event)
self.assertIn(event.as_string(), self.assertIn(event.as_string(),
getLogger.return_value.info.call_args[0][0]) getLogger.return_value.info.call_args[0][0])
class TestDefaultRegisteredHandler(TestCase):
def test_log_handler_registered_by_default(self):
for _, item in reporting.handler_registry.registered_items.items():
if isinstance(item, reporting.LogHandler):
break
else:
self.fail('No reporting LogHandler registered by default.')