Add unregister and reset to DictRegistry and use
unregister allows us to unregister things, so that applying configuration changes will affect the reporting. Change-Id: I35932c95784060349c60a11b523bf6897fb80090
This commit is contained in:
parent
735f0ac4ad
commit
fe616bf41b
cloudinit
@ -1,3 +1,7 @@
|
|||||||
|
# Copyright 2015 Canonical Ltd.
|
||||||
|
# This file is part of cloud-init. See LICENCE file for license information.
|
||||||
|
#
|
||||||
|
# vi: ts=4 expandtab
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
|
||||||
@ -5,6 +9,9 @@ class DictRegistry(object):
|
|||||||
"""A simple registry for a mapping of objects."""
|
"""A simple registry for a mapping of objects."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
self._items = {}
|
self._items = {}
|
||||||
|
|
||||||
def register_item(self, key, item):
|
def register_item(self, key, item):
|
||||||
@ -14,6 +21,13 @@ class DictRegistry(object):
|
|||||||
'Item already registered with key {0}'.format(key))
|
'Item already registered with key {0}'.format(key))
|
||||||
self._items[key] = item
|
self._items[key] = item
|
||||||
|
|
||||||
|
def unregister_item(self, key, force=True):
|
||||||
|
"""Remove item from the registry."""
|
||||||
|
if key in self._items:
|
||||||
|
del self._items[key]
|
||||||
|
elif not force:
|
||||||
|
raise KeyError("%s: key not present to unregister" % key)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def registered_items(self):
|
def registered_items(self):
|
||||||
"""All the items that have been registered.
|
"""All the items that have been registered.
|
||||||
|
@ -20,8 +20,6 @@ DEFAULT_CONFIG = {
|
|||||||
'logging': {'type': 'log'},
|
'logging': {'type': 'log'},
|
||||||
}
|
}
|
||||||
|
|
||||||
instantiated_handler_registry = DictRegistry()
|
|
||||||
|
|
||||||
|
|
||||||
class _nameset(set):
|
class _nameset(set):
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
@ -46,6 +44,11 @@ class ReportingEvent(object):
|
|||||||
return '{0}: {1}: {2}'.format(
|
return '{0}: {1}: {2}'.format(
|
||||||
self.event_type, self.name, self.description)
|
self.event_type, self.name, self.description)
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
"""The event represented as a dictionary."""
|
||||||
|
return {'name': self.name, 'description': self.description,
|
||||||
|
'event_type': self.event_type}
|
||||||
|
|
||||||
|
|
||||||
class FinishReportingEvent(ReportingEvent):
|
class FinishReportingEvent(ReportingEvent):
|
||||||
|
|
||||||
@ -60,9 +63,26 @@ class FinishReportingEvent(ReportingEvent):
|
|||||||
return '{0}: {1}: {2}: {3}'.format(
|
return '{0}: {1}: {2}: {3}'.format(
|
||||||
self.event_type, self.name, self.result, self.description)
|
self.event_type, self.name, self.result, self.description)
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
"""The event represented as json friendly."""
|
||||||
|
data = super(FinishReportingEvent, self).as_dict()
|
||||||
|
data['result'] = self.result
|
||||||
|
return data
|
||||||
|
|
||||||
def add_configuration(config):
|
|
||||||
|
def update_configuration(config):
|
||||||
|
"""Update the instanciated_handler_registry.
|
||||||
|
|
||||||
|
:param config:
|
||||||
|
The dictionary containing changes to apply. If a key is given
|
||||||
|
with a False-ish value, the registered handler matching that name
|
||||||
|
will be unregistered.
|
||||||
|
"""
|
||||||
for handler_name, handler_config in config.items():
|
for handler_name, handler_config in config.items():
|
||||||
|
if not handler_config:
|
||||||
|
instantiated_handler_registry.unregister_item(
|
||||||
|
handler_name, force=True)
|
||||||
|
continue
|
||||||
handler_config = handler_config.copy()
|
handler_config = handler_config.copy()
|
||||||
cls = available_handlers.registered_items[handler_config.pop('type')]
|
cls = available_handlers.registered_items[handler_config.pop('type')]
|
||||||
instance = cls(**handler_config)
|
instance = cls(**handler_config)
|
||||||
@ -214,4 +234,5 @@ class ReportEventStack(object):
|
|||||||
report_finish_event(self.fullname, msg, result)
|
report_finish_event(self.fullname, msg, result)
|
||||||
|
|
||||||
|
|
||||||
add_configuration(DEFAULT_CONFIG)
|
instantiated_handler_registry = DictRegistry()
|
||||||
|
update_configuration(DEFAULT_CONFIG)
|
||||||
|
@ -96,6 +96,23 @@ class TestReportingEvent(TestCase):
|
|||||||
[event_type, name, description])
|
[event_type, name, description])
|
||||||
self.assertEqual(expected_string_representation, event.as_string())
|
self.assertEqual(expected_string_representation, event.as_string())
|
||||||
|
|
||||||
|
def test_as_dict(self):
|
||||||
|
event_type, name, desc = 'test_type', 'test_name', 'test_desc'
|
||||||
|
event = reporting.ReportingEvent(event_type, name, desc)
|
||||||
|
self.assertEqual(
|
||||||
|
{'event_type': event_type, 'name': name, 'description': desc},
|
||||||
|
event.as_dict())
|
||||||
|
|
||||||
|
|
||||||
|
class TestFinishReportingEvent(TestCase):
|
||||||
|
def test_as_has_result(self):
|
||||||
|
result = reporting.status.SUCCESS
|
||||||
|
name, desc = 'test_name', 'test_desc'
|
||||||
|
event = reporting.FinishReportingEvent(name, desc, result)
|
||||||
|
ret = event.as_dict()
|
||||||
|
self.assertTrue('result' in ret)
|
||||||
|
self.assertEqual(ret['result'], result)
|
||||||
|
|
||||||
|
|
||||||
class TestBaseReportingHandler(TestCase):
|
class TestBaseReportingHandler(TestCase):
|
||||||
|
|
||||||
@ -148,7 +165,7 @@ class TestReportingConfiguration(TestCase):
|
|||||||
@mock.patch.object(reporting, 'instantiated_handler_registry')
|
@mock.patch.object(reporting, 'instantiated_handler_registry')
|
||||||
def test_empty_configuration_doesnt_add_handlers(
|
def test_empty_configuration_doesnt_add_handlers(
|
||||||
self, instantiated_handler_registry):
|
self, instantiated_handler_registry):
|
||||||
reporting.add_configuration({})
|
reporting.update_configuration({})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
0, instantiated_handler_registry.register_item.call_count)
|
0, instantiated_handler_registry.register_item.call_count)
|
||||||
|
|
||||||
@ -160,7 +177,7 @@ class TestReportingConfiguration(TestCase):
|
|||||||
handler_cls = mock.Mock()
|
handler_cls = mock.Mock()
|
||||||
available_handlers.registered_items = {handler_type_name: handler_cls}
|
available_handlers.registered_items = {handler_type_name: handler_cls}
|
||||||
handler_name = 'my_test_handler'
|
handler_name = 'my_test_handler'
|
||||||
reporting.add_configuration(
|
reporting.update_configuration(
|
||||||
{handler_name: {'type': handler_type_name}})
|
{handler_name: {'type': handler_type_name}})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
{handler_name: handler_cls.return_value},
|
{handler_name: handler_cls.return_value},
|
||||||
@ -178,7 +195,7 @@ class TestReportingConfiguration(TestCase):
|
|||||||
handler_config = extra_kwargs.copy()
|
handler_config = extra_kwargs.copy()
|
||||||
handler_config.update({'type': handler_type_name})
|
handler_config.update({'type': handler_type_name})
|
||||||
handler_name = 'my_test_handler'
|
handler_name = 'my_test_handler'
|
||||||
reporting.add_configuration({handler_name: handler_config})
|
reporting.update_configuration({handler_name: handler_config})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
handler_cls.return_value,
|
handler_cls.return_value,
|
||||||
reporting.instantiated_handler_registry.registered_items[
|
reporting.instantiated_handler_registry.registered_items[
|
||||||
@ -195,9 +212,25 @@ class TestReportingConfiguration(TestCase):
|
|||||||
available_handlers.registered_items = {handler_type_name: handler_cls}
|
available_handlers.registered_items = {handler_type_name: handler_cls}
|
||||||
handler_config = {'type': handler_type_name, 'foo': 'bar'}
|
handler_config = {'type': handler_type_name, 'foo': 'bar'}
|
||||||
expected_handler_config = handler_config.copy()
|
expected_handler_config = handler_config.copy()
|
||||||
reporting.add_configuration({'my_test_handler': handler_config})
|
reporting.update_configuration({'my_test_handler': handler_config})
|
||||||
self.assertEqual(expected_handler_config, handler_config)
|
self.assertEqual(expected_handler_config, handler_config)
|
||||||
|
|
||||||
|
@mock.patch.object(
|
||||||
|
reporting, 'instantiated_handler_registry', reporting.DictRegistry())
|
||||||
|
@mock.patch.object(reporting, 'available_handlers')
|
||||||
|
def test_handlers_removed_if_falseish_specified(self, available_handlers):
|
||||||
|
handler_type_name = 'test_handler'
|
||||||
|
handler_cls = mock.Mock()
|
||||||
|
available_handlers.registered_items = {handler_type_name: handler_cls}
|
||||||
|
handler_name = 'my_test_handler'
|
||||||
|
reporting.update_configuration(
|
||||||
|
{handler_name: {'type': handler_type_name}})
|
||||||
|
self.assertEqual(
|
||||||
|
1, len(reporting.instantiated_handler_registry.registered_items))
|
||||||
|
reporting.update_configuration({handler_name: None})
|
||||||
|
self.assertEqual(
|
||||||
|
0, len(reporting.instantiated_handler_registry.registered_items))
|
||||||
|
|
||||||
|
|
||||||
class TestReportingEventStack(TestCase):
|
class TestReportingEventStack(TestCase):
|
||||||
@mock.patch('cloudinit.reporting.report_finish_event')
|
@mock.patch('cloudinit.reporting.report_finish_event')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user