From e4ded57bd4092642a89ebb1b6f3fb2aae180da2c Mon Sep 17 00:00:00 2001 From: Steven Hardy Date: Mon, 4 Feb 2013 14:09:04 +0000 Subject: [PATCH] heat engine : Resource add function to compare properties Add update_template_diff_properties to make comparison of pre/post update resource properties easier Change-Id: Ic37d37ae510a62739d4cc4219cfd69479a87767d Signed-off-by: Steven Hardy --- heat/engine/resource.py | 32 +++++++++++++++++++++++++++++ heat/tests/test_resource.py | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/heat/engine/resource.py b/heat/engine/resource.py index eb086716e3..e6a5ee6030 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -105,6 +105,10 @@ class Resource(object): # which are supported for handle_update, used by update_template_diff update_allowed_keys = () + # Resource implementation set this to the subset of resource properties + # supported for handle_update, used by update_template_diff_properties + update_allowed_properties = () + def __new__(cls, name, json, stack): '''Create a new Resource of the appropriate class for its type.''' @@ -204,6 +208,34 @@ class Resource(object): return dict((k, json_snippet.get(k)) for k in changed_keys_set) + def update_template_diff_properties(self, json_snippet=None): + ''' + Returns the changed Properties between json_template and self.t + If a property has been removed in json_snippet which exists + in self.t we set it to None. If any properties have changed which + are not in update_allowed_properties, raises NotImplementedError + ''' + update_allowed_set = set(self.update_allowed_properties) + + # Create a set containing the keys in both current and update template + current_properties = self.parsed_template().get('Properties', {}) + template_properties = set(current_properties.keys()) + updated_properties = json_snippet.get('Properties', {}) + template_properties.update(set(updated_properties.keys())) + + # Create a set of keys which differ (or are missing/added) + changed_properties_set = set(k for k in template_properties + if current_properties.get(k) != + updated_properties.get(k)) + + if not changed_properties_set.issubset(update_allowed_set): + badkeys = changed_properties_set - update_allowed_set + raise NotImplementedError("Cannot update properties %s for %s" % + (badkeys, self.name)) + + return dict((k, updated_properties.get(k)) + for k in changed_properties_set) + def __str__(self): return '%s "%s"' % (self.__class__.__name__, self.name) diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py index eac55c2d22..830ec68345 100644 --- a/heat/tests/test_resource.py +++ b/heat/tests/test_resource.py @@ -153,6 +153,46 @@ class ResourceTest(unittest.TestCase): diff = res.update_template_diff(json_snippet=update_snippet) self.assertEqual(diff, {'Metadata': None}) + def test_update_template_diff_properties_none(self): + tmpl = {'Type': 'Foo'} + update_snippet = {'Type': 'Foo'} + res = resource.GenericResource('test_resource', tmpl, self.stack) + diff = res.update_template_diff_properties(json_snippet=update_snippet) + self.assertEqual(diff, {}) + + def test_update_template_diff_properties_added(self): + tmpl = {'Type': 'Foo'} + update_snippet = {'Type': 'Foo', 'Properties': {'Bar': 123}} + res = resource.GenericResource('test_resource', tmpl, self.stack) + res.update_allowed_properties = ('Bar',) + diff = res.update_template_diff_properties(json_snippet=update_snippet) + self.assertEqual(diff, {'Bar': 123}) + + def test_update_template_diff_properties_removed(self): + tmpl = {'Type': 'Foo', 'Properties': {'Bar': 123}} + update_snippet = {'Type': 'Foo', 'Properties': {}} + res = resource.GenericResource('test_resource', tmpl, self.stack) + res.update_allowed_properties = ('Bar',) + diff = res.update_template_diff_properties(json_snippet=update_snippet) + self.assertEqual(diff, {'Bar': None}) + + def test_update_template_diff_properties_changed(self): + tmpl = {'Type': 'Foo', 'Properties': {'Bar': 123}} + update_snippet = {'Type': 'Foo', 'Properties': {'Bar': 456}} + res = resource.GenericResource('test_resource', tmpl, self.stack) + res.update_allowed_properties = ('Bar',) + diff = res.update_template_diff_properties(json_snippet=update_snippet) + self.assertEqual(diff, {'Bar': 456}) + + def test_update_template_diff_properties_notallowed(self): + tmpl = {'Type': 'Foo', 'Properties': {'Bar': 123}} + update_snippet = {'Type': 'Foo', 'Properties': {'Bar': 456}} + res = resource.GenericResource('test_resource', tmpl, self.stack) + res.update_allowed_properties = ('Cat',) + self.assertRaises(NotImplementedError, + res.update_template_diff_properties, + update_snippet) + @attr(tag=['unit', 'resource']) @attr(speed='fast')