Merge "Add a map event trait plugin"
This commit is contained in:
commit
b03fea8f0b
@ -217,3 +217,58 @@ class TimedeltaPlugin(TraitPluginBase):
|
||||
)
|
||||
return [None]
|
||||
return [abs((end_time - start_time).total_seconds())]
|
||||
|
||||
|
||||
class MapTraitPlugin(TraitPluginBase):
|
||||
"""A trait plugin for mapping one set of values to another."""
|
||||
|
||||
def __init__(self, values=None, default=None, case_sensitive=True, **kw):
|
||||
"""Setup map trait.
|
||||
|
||||
:param values: (dict[Any, Any]) Mapping of values to their
|
||||
desired target values.
|
||||
:param default: (Any) Value to set if no mapping for a value is found.
|
||||
:param case_sensitive: (bool) Perform case-sensitive string lookups.
|
||||
"""
|
||||
if not values:
|
||||
raise ValueError(("The 'values' parameter is required "
|
||||
"for the map trait plugin"))
|
||||
if not isinstance(values, dict):
|
||||
raise ValueError(("The 'values' parameter needs to be a dict "
|
||||
"for the map trait plugin"))
|
||||
self.case_sensitive = case_sensitive
|
||||
if not self.case_sensitive:
|
||||
self.values = {(k.casefold()
|
||||
if isinstance(k, str)
|
||||
else k): v
|
||||
for k, v in values.items()}
|
||||
else:
|
||||
self.values = dict(values)
|
||||
self.default = default
|
||||
super(MapTraitPlugin, self).__init__(**kw)
|
||||
|
||||
def trait_values(self, match_list):
|
||||
mapped_values = []
|
||||
for match in match_list:
|
||||
key = match[1]
|
||||
folded_key = (
|
||||
key.casefold()
|
||||
if not self.case_sensitive and isinstance(key, str)
|
||||
else key)
|
||||
try:
|
||||
value = self.values[folded_key]
|
||||
except KeyError:
|
||||
LOG.warning(
|
||||
('Unknown value %s found when mapping %s, '
|
||||
'mapping to default value of %s'),
|
||||
repr(key),
|
||||
match[0],
|
||||
repr(self.default))
|
||||
value = self.default
|
||||
else:
|
||||
LOG.debug('Value %s for %s mapped to value %s',
|
||||
repr(key),
|
||||
match[0],
|
||||
repr(value))
|
||||
mapped_values.append(value)
|
||||
return mapped_values
|
||||
|
@ -113,3 +113,47 @@ class TestBitfieldPlugin(base.BaseTestCase):
|
||||
plugin = self.pclass(**self.params)
|
||||
value = plugin.trait_values(match_list)
|
||||
self.assertEqual(0x412, value[0])
|
||||
|
||||
|
||||
class TestMapTraitPlugin(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMapTraitPlugin, self).setUp()
|
||||
self.pclass = trait_plugins.MapTraitPlugin
|
||||
self.params = dict(values={'ACTIVE': 1, 'ERROR': 2, 3: 4},
|
||||
default=-1)
|
||||
|
||||
def test_map(self):
|
||||
match_list = [('payload.foo', 'ACTIVE'),
|
||||
('payload.bar', 'ERROR'),
|
||||
('thingy.boink', 3),
|
||||
('thingy.invalid', 999)]
|
||||
plugin = self.pclass(**self.params)
|
||||
value = plugin.trait_values(match_list)
|
||||
self.assertEqual([1, 2, 4, -1], value)
|
||||
|
||||
def test_case_sensitive(self):
|
||||
match_list = [('payload.foo', 'ACTIVE'),
|
||||
('payload.bar', 'error'),
|
||||
('thingy.boink', 3),
|
||||
('thingy.invalid', 999)]
|
||||
plugin = self.pclass(case_sensitive=True, **self.params)
|
||||
value = plugin.trait_values(match_list)
|
||||
self.assertEqual([1, -1, 4, -1], value)
|
||||
|
||||
def test_case_insensitive(self):
|
||||
match_list = [('payload.foo', 'active'),
|
||||
('payload.bar', 'ErRoR'),
|
||||
('thingy.boink', 3),
|
||||
('thingy.invalid', 999)]
|
||||
plugin = self.pclass(case_sensitive=False, **self.params)
|
||||
value = plugin.trait_values(match_list)
|
||||
self.assertEqual([1, 2, 4, -1], value)
|
||||
|
||||
def test_values_undefined(self):
|
||||
self.assertRaises(ValueError, self.pclass)
|
||||
|
||||
def test_values_invalid(self):
|
||||
self.assertRaises(
|
||||
ValueError,
|
||||
lambda: self.pclass(values=[('ACTIVE', 1), ('ERROR', 2), (3, 4)]))
|
||||
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
A ``map`` event trait plugin has been added.
|
||||
This allows notification meter attributes to be created
|
||||
by mapping one set of values from an attribute to another
|
||||
set of values defined in the meter definition.
|
||||
Additional options are also available for controlling
|
||||
how to handle edge cases, such as unknown values and
|
||||
case sensitivity.
|
@ -173,6 +173,7 @@ ceilometer.event.trait_plugin =
|
||||
split = ceilometer.event.trait_plugins:SplitterTraitPlugin
|
||||
bitfield = ceilometer.event.trait_plugins:BitfieldTraitPlugin
|
||||
timedelta = ceilometer.event.trait_plugins:TimedeltaPlugin
|
||||
map = ceilometer.event.trait_plugins:MapTraitPlugin
|
||||
|
||||
console_scripts =
|
||||
ceilometer-polling = ceilometer.cmd.polling:main
|
||||
|
Loading…
x
Reference in New Issue
Block a user