summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngus Salkeld <asalkeld@mirantis.com>2014-10-10 12:00:37 +1000
committerZane Bitter <zbitter@redhat.com>2014-10-10 20:15:11 -0400
commit5aa66555209eb5a59abdb189b0a5d1224e73b566 (patch)
treeca8249a78b4270b4fa019dd4c472a15dbd2e0472
parent6e1ad898d887514267e3a429c291b2a067ea7e03 (diff)
downloadheat-5aa66555209eb5a59abdb189b0a5d1224e73b566.tar.gz
Make sure that the properties are stored on updates
Previously properties_data was only stored on creation, now this is getting passed to the update mechanism too. Later we can look at reworking this into a single mechanism. Closes-bug: #1377681 Change-Id: If3d476f34b9e61a3c99f63ba33734a875353c8fc (cherry picked from commit d32370233eaf2a5c32888f269bd1dc5e0e787467)
-rw-r--r--heat/engine/resource.py14
-rw-r--r--heat/tests/generic_resource.py4
-rw-r--r--heat/tests/test_neutron_autoscaling.py9
-rw-r--r--heat/tests/test_parser.py65
-rw-r--r--heat/tests/test_properties.py12
5 files changed, 97 insertions, 7 deletions
diff --git a/heat/engine/resource.py b/heat/engine/resource.py
index b08222cc3..ccf0e6996 100644
--- a/heat/engine/resource.py
+++ b/heat/engine/resource.py
@@ -903,12 +903,14 @@ class Resource(object):
if self.id is not None:
try:
rs = db_api.resource_get(self.context, self.id)
- rs.update_and_save({'action': self.action,
- 'status': self.status,
- 'status_reason': reason,
- 'stack_id': self.stack.id,
- 'updated_at': self.updated_time,
- 'nova_instance': self.resource_id})
+ rs.update_and_save({
+ 'action': self.action,
+ 'status': self.status,
+ 'status_reason': reason,
+ 'stack_id': self.stack.id,
+ 'updated_at': self.updated_time,
+ 'properties_data': self._stored_properties_data,
+ 'nova_instance': self.resource_id})
except Exception as ex:
LOG.error(_('DB error %s') % ex)
diff --git a/heat/tests/generic_resource.py b/heat/tests/generic_resource.py
index 130e0577d..8e102d711 100644
--- a/heat/tests/generic_resource.py
+++ b/heat/tests/generic_resource.py
@@ -60,11 +60,13 @@ class ResWithComplexPropsAndAttrs(GenericResource):
properties_schema = {'a_string': {'Type': 'String'},
'a_list': {'Type': 'List'},
- 'a_map': {'Type': 'Map'}}
+ 'a_map': {'Type': 'Map'},
+ 'an_int': {'Type': 'Integer'}}
attributes_schema = {'list': attributes.Schema('A list'),
'map': attributes.Schema('A map'),
'string': attributes.Schema('A string')}
+ update_allowed_properties = ('an_int',)
def _resolve_attribute(self, name):
try:
diff --git a/heat/tests/test_neutron_autoscaling.py b/heat/tests/test_neutron_autoscaling.py
index 4a266c4d6..6105287ed 100644
--- a/heat/tests/test_neutron_autoscaling.py
+++ b/heat/tests/test_neutron_autoscaling.py
@@ -122,6 +122,7 @@ class AutoScalingTest(HeatTestCase):
self.m.StubOutWithMock(neutronclient.Client, 'show_pool')
self.m.StubOutWithMock(neutronclient.Client, 'show_vip')
self.m.StubOutWithMock(neutronclient.Client, 'create_member')
+ self.m.StubOutWithMock(neutronclient.Client, 'delete_member')
self.m.StubOutWithMock(neutronclient.Client, 'list_members')
self.m.StubOutWithMock(nova.NovaClientPlugin, 'server_to_ipaddress')
@@ -309,6 +310,8 @@ class AutoScalingTest(HeatTestCase):
nova.NovaClientPlugin.server_to_ipaddress(
mox.IgnoreArg()).AndReturn('1.2.3.5')
+ neutronclient.Client.delete_member(mox.IgnoreArg()).AndReturn(None)
+
neutronclient.Client.create_member(memberb_block).\
AndReturn(memberb_ret_block)
@@ -318,6 +321,12 @@ class AutoScalingTest(HeatTestCase):
neutronclient.Client.create_member(memberc_block).\
AndReturn(memberc_ret_block)
+ nova.NovaClientPlugin.server_to_ipaddress(
+ mox.IgnoreArg()).AndReturn('1.2.3.4')
+
+ neutronclient.Client.create_member(membera_block).\
+ AndReturn(membera_ret_block)
+
self.m.ReplayAll()
# Start of stack create
diff --git a/heat/tests/test_parser.py b/heat/tests/test_parser.py
index 1c84a8206..4db1ce585 100644
--- a/heat/tests/test_parser.py
+++ b/heat/tests/test_parser.py
@@ -924,6 +924,8 @@ class StackTest(HeatTestCase):
generic_rsrc.ResourceWithProps)
resource._register_class('ResourceWithComplexAttributesType',
generic_rsrc.ResourceWithComplexAttributes)
+ resource._register_class('ResWithComplexPropsAndAttrs',
+ generic_rsrc.ResWithComplexPropsAndAttrs)
def test_stack_reads_tenant(self):
stack = parser.Stack(self.ctx, 'test_stack', self.tmpl,
@@ -2180,6 +2182,69 @@ class StackTest(HeatTestCase):
self.m.VerifyAll()
+ def test_update_modify_ok_replace_int(self):
+ # create
+ #========
+ tmpl = {'heat_template_version': '2013-05-23',
+ 'resources': {'AResource': {
+ 'type': 'ResWithComplexPropsAndAttrs',
+ 'properties': {'an_int': 1}}}}
+
+ self.stack = parser.Stack(self.ctx, 'update_test_stack',
+ template.Template(tmpl))
+ self.stack.store()
+ stack_id = self.stack.id
+ self.stack.create()
+ self.assertEqual((parser.Stack.CREATE, parser.Stack.COMPLETE),
+ self.stack.state)
+
+ value1 = 2
+ prop_diff1 = {'an_int': value1}
+ value2 = 1
+ prop_diff2 = {'an_int': value2}
+
+ self.m.StubOutWithMock(generic_rsrc.ResWithComplexPropsAndAttrs,
+ 'handle_update')
+ generic_rsrc.ResWithComplexPropsAndAttrs.handle_update(
+ IgnoreArg(), IgnoreArg(), prop_diff1)
+ generic_rsrc.ResWithComplexPropsAndAttrs.handle_update(
+ IgnoreArg(), IgnoreArg(), prop_diff2)
+
+ self.m.ReplayAll()
+
+ # update 1
+ #==========
+
+ self.stack = parser.Stack.load(self.ctx, stack_id=stack_id)
+ tmpl2 = {'heat_template_version': '2013-05-23',
+ 'resources': {'AResource': {
+ 'type': 'ResWithComplexPropsAndAttrs',
+ 'properties': {'an_int': value1}}}}
+ updated_stack = parser.Stack(self.ctx, 'updated_stack',
+ template.Template(tmpl2))
+
+ self.stack.update(updated_stack)
+ self.assertEqual((parser.Stack.UPDATE, parser.Stack.COMPLETE),
+ self.stack.state)
+
+ # update 2
+ #==========
+ # reload the previous stack
+ self.stack = parser.Stack.load(self.ctx, stack_id=stack_id)
+ tmpl3 = {'heat_template_version': '2013-05-23',
+ 'resources': {'AResource': {
+ 'type': 'ResWithComplexPropsAndAttrs',
+ 'properties': {'an_int': value2}}}}
+
+ updated_stack = parser.Stack(self.ctx, 'updated_stack',
+ template.Template(tmpl3))
+
+ self.stack.update(updated_stack)
+ self.assertEqual((parser.Stack.UPDATE, parser.Stack.COMPLETE),
+ self.stack.state)
+
+ self.m.VerifyAll()
+
def test_update_modify_param_ok_replace(self):
tmpl = {
'HeatTemplateFormatVersion': '2012-12-12',
diff --git a/heat/tests/test_properties.py b/heat/tests/test_properties.py
index 751186287..c3ba54992 100644
--- a/heat/tests/test_properties.py
+++ b/heat/tests/test_properties.py
@@ -1471,6 +1471,18 @@ class PropertiesTest(testtools.TestCase):
self.assertEqual(expected,
dict((n, dict(s)) for n, s in props_schemata.items()))
+ def test_compare_same(self):
+ schema = {'foo': {'Type': 'Integer'}}
+ props_a = properties.Properties(schema, {'foo': 1})
+ props_b = properties.Properties(schema, {'foo': 1})
+ self.assertFalse(props_a != props_b)
+
+ def test_compare_different(self):
+ schema = {'foo': {'Type': 'Integer'}}
+ props_a = properties.Properties(schema, {'foo': 0})
+ props_b = properties.Properties(schema, {'foo': 1})
+ self.assertTrue(props_a != props_b)
+
class PropertiesValidationTest(testtools.TestCase):
def test_required(self):