diff --git a/ceilometer/api/controllers/v2.py b/ceilometer/api/controllers/v2.py index f9210fdc4..914d022bf 100644 --- a/ceilometer/api/controllers/v2.py +++ b/ceilometer/api/controllers/v2.py @@ -45,6 +45,7 @@ from ceilometer.openstack.common import log from ceilometer.openstack.common import timeutils from ceilometer import sample from ceilometer import storage +from ceilometer import utils from ceilometer.api import acl @@ -270,8 +271,9 @@ def _flatten_metadata(metadata): """ if metadata: return dict((k, unicode(v)) - for k, v in metadata.iteritems() - if type(v) not in set([list, dict, set])) + for k, v in utils.recursive_keypairs(metadata, + separator='.') + if type(v) not in set([list, set])) return {} diff --git a/ceilometer/utils.py b/ceilometer/utils.py index bf87c1441..60a08e902 100644 --- a/ceilometer/utils.py +++ b/ceilometer/utils.py @@ -27,13 +27,13 @@ import decimal from ceilometer.openstack.common import timeutils -def recursive_keypairs(d): +def recursive_keypairs(d, separator=':'): """Generator that produces sequence of keypairs for nested dictionaries. """ for name, value in sorted(d.iteritems()): if isinstance(value, dict): for subname, subvalue in recursive_keypairs(value): - yield ('%s:%s' % (name, subname), subvalue) + yield ('%s%s%s' % (name, separator, subname), subvalue) elif isinstance(value, (tuple, list)): # When doing a pair of JSON encode/decode operations to the tuple, # the tuple would become list. So we have to generate the value as diff --git a/tests/api/v2/test_list_events_scenarios.py b/tests/api/v2/test_list_events_scenarios.py index 4743b1d8e..367d569fc 100644 --- a/tests/api/v2/test_list_events_scenarios.py +++ b/tests/api/v2/test_list_events_scenarios.py @@ -52,7 +52,7 @@ class TestListEvents(FunctionalTest, timestamp=datetime.datetime(2012, 7, 2, 10, 40), resource_metadata={'display_name': 'test-server', 'tag': 'self.counter', - 'ignored_dict': {'key': 'value'}, + 'dict_properties': {'key': 'value'}, 'ignored_list': ['not-returned'], }, source='test_source', @@ -169,6 +169,7 @@ class TestListEvents(FunctionalTest, self.assert_('resource_metadata' in sample) self.assertEqual( list(sorted(sample['resource_metadata'].iteritems())), - [('display_name', 'test-server'), + [('dict_properties.key', 'value'), + ('display_name', 'test-server'), ('tag', 'self.counter'), ]) diff --git a/tests/api/v2/test_list_meters_scenarios.py b/tests/api/v2/test_list_meters_scenarios.py index 4f21e7a8f..e24080577 100644 --- a/tests/api/v2/test_list_meters_scenarios.py +++ b/tests/api/v2/test_list_meters_scenarios.py @@ -142,10 +142,8 @@ class TestListMeters(FunctionalTest, self.assertEqual('resource-id4', data[0]['resource_id']) metadata = data[0]['resource_metadata'] self.assertIsNotNone(metadata) - # FIXME (flwang): Based on current implement, the metadata of - # dictionary type can't be shown in the output. See bug 1203699. - # Will add more asserts in the fix of 1203699. self.assertEqual('self.counter4', metadata['tag']) + self.assertEqual('prop_value', metadata['properties.prop_1']) def test_list_meters_metadata_query(self): data = self.get_json('/meters/meter.test', diff --git a/tests/api/v2/test_list_resources_scenarios.py b/tests/api/v2/test_list_resources_scenarios.py index 2cf1c8fdb..a20c85d83 100644 --- a/tests/api/v2/test_list_resources_scenarios.py +++ b/tests/api/v2/test_list_resources_scenarios.py @@ -411,7 +411,7 @@ class TestListResources(FunctionalTest, timestamp=datetime.datetime(2012, 7, 2, 10, 40), resource_metadata={'display_name': 'test-server', 'tag': 'self.counter', - 'ignored_dict': {'key': 'value'}, + 'dict_properties': {'key': 'value'}, 'ignored_list': ['not-returned'], }, source='test', @@ -425,10 +425,11 @@ class TestListResources(FunctionalTest, data = self.get_json('/resources') metadata = data[0]['metadata'] self.assertEqual( - list(sorted(metadata.iteritems())), - [('display_name', 'test-server'), - ('tag', 'self.counter'), - ]) + [(u'dict_properties.key', u'value'), + (u'display_name', u'test-server'), + (u'tag', u'self.counter') + ], + list(sorted(metadata.iteritems()))) def test_resource_meter_links(self): counter1 = sample.Sample( diff --git a/tests/test_utils.py b/tests/test_utils.py index f551c2e24..36ff228bb 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -53,3 +53,17 @@ class TestUtils(tests_base.TestCase): ('b', 'B'), ('nested:a', 'A'), ('nested:b', 'B')]) + + def test_recursive_keypairs_with_separator(self): + data = {'a': 'A', + 'b': 'B', + 'nested': {'a': 'A', + 'b': 'B', + }, + } + separator = '.' + pairs = list(utils.recursive_keypairs(data, separator)) + self.assertEqual(pairs, [('a', 'A'), + ('b', 'B'), + ('nested.a', 'A'), + ('nested.b', 'B')])