]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
heat engine : add Resource update_template_diff method
authorSteven Hardy <shardy@redhat.com>
Mon, 28 Jan 2013 16:52:23 +0000 (16:52 +0000)
committerSteven Hardy <shardy@redhat.com>
Thu, 31 Jan 2013 09:56:28 +0000 (09:56 +0000)
Add method to top-level Resource class update_template_diff()
which allows us to determine the difference between old/new
templates for a resource update, and also raise an error
if the changed keys are not in the list of those defined
as supported for update by the resource

ref blueprint instance-update-stack

Change-Id: Ibef07a0cecbc15f7f1d6c2c663743e3af8023057
Signed-off-by: Steven Hardy <shardy@redhat.com>
heat/engine/resource.py
heat/tests/test_resource.py

index c8cd53d1b6fdbfebaa47780ee8dcfe2003a066a9..f8ea86b2b7186fb4e1821183452b8bf294464660 100644 (file)
@@ -101,6 +101,10 @@ class Resource(object):
 
     metadata = Metadata()
 
+    # Resource implementation set this to the subset of template keys
+    # which are supported for handle_update, used by update_template_diff
+    update_allowed_keys = ()
+
     def __new__(cls, name, json, stack):
         '''Create a new Resource of the appropriate class for its type.'''
 
@@ -174,6 +178,32 @@ class Resource(object):
             template = self.t.get(section, default)
         return self.stack.resolve_runtime_data(template)
 
+    def update_template_diff(self, json_snippet=None):
+        '''
+        Returns the difference between json_template and self.t
+        If something has been removed in json_snippet which exists
+        in self.t we set it to None.  If any keys have changed which
+        are not in update_allowed_keys, raises NotImplementedError
+        '''
+        update_allowed_set = set(self.update_allowed_keys)
+
+        # Create a set containing the keys in both current and update template
+        current_snippet = self.parsed_template()
+        template_keys = set(current_snippet.keys())
+        template_keys.update(set(json_snippet.keys()))
+
+        # Create a set of keys which differ (or are missing/added)
+        changed_keys_set = set([k for k in template_keys
+                               if current_snippet.get(k, None) !=
+                               json_snippet.get(k, None)])
+
+        if not changed_keys_set.issubset(update_allowed_set):
+            badkeys = changed_keys_set - update_allowed_set
+            raise NotImplementedError("Cannot update keys %s for %s" %
+                                      (badkeys, self.name))
+
+        return dict((k, json_snippet.get(k, None)) for k in changed_keys_set)
+
     def __str__(self):
         return '%s "%s"' % (self.__class__.__name__, self.name)
 
index eee6754f659126347c689d69d5838a4e723158d8..71531b8ec5b7bb6ceb6edb4bb4806ab295f10bc3 100644 (file)
@@ -115,6 +115,44 @@ class ResourceTest(unittest.TestCase):
 
         self.assertNotEqual(res1, res2)
 
+    def test_update_template_diff_empty(self):
+        tmpl = {'Type': 'Foo'}
+        update_snippet = {}
+        res = resource.GenericResource('test_resource', tmpl, self.stack)
+        self.assertRaises(NotImplementedError, res.update_template_diff,
+                          update_snippet)
+
+    def test_update_template_diff_changed_notallowed(self):
+        tmpl = {'Type': 'Foo'}
+        update_snippet = {'Type': 'Bar'}
+        res = resource.GenericResource('test_resource', tmpl, self.stack)
+        self.assertRaises(NotImplementedError, res.update_template_diff,
+                          update_snippet)
+
+    def test_update_template_diff_changed_modified(self):
+        tmpl = {'Type': 'Foo', 'Metadata': {'foo': 123}}
+        update_snippet = {'Type': 'Foo', 'Metadata': {'foo': 456}}
+        res = resource.GenericResource('test_resource', tmpl, self.stack)
+        res.update_allowed_keys = ['Metadata']
+        diff = res.update_template_diff(json_snippet=update_snippet)
+        self.assertEqual(diff, {'Metadata': {'foo': 456}})
+
+    def test_update_template_diff_changed_add(self):
+        tmpl = {'Type': 'Foo'}
+        update_snippet = {'Type': 'Foo', 'Metadata': {'foo': 123}}
+        res = resource.GenericResource('test_resource', tmpl, self.stack)
+        res.update_allowed_keys = ['Metadata']
+        diff = res.update_template_diff(json_snippet=update_snippet)
+        self.assertEqual(diff, {'Metadata': {'foo': 123}})
+
+    def test_update_template_diff_changed_remove(self):
+        tmpl = {'Type': 'Foo', 'Metadata': {'foo': 123}}
+        update_snippet = {'Type': 'Foo'}
+        res = resource.GenericResource('test_resource', tmpl, self.stack)
+        res.update_allowed_keys = ['Metadata']
+        diff = res.update_template_diff(json_snippet=update_snippet)
+        self.assertEqual(diff, {'Metadata': None})
+
 
 @attr(tag=['unit', 'resource'])
 @attr(speed='fast')