Merge "Convergence: Check resource class before updating"
This commit is contained in:
@@ -41,7 +41,6 @@ from heat.engine import resources
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import scheduler
|
||||
from heat.engine import support
|
||||
from heat.engine import template
|
||||
from heat.objects import resource as resource_objects
|
||||
from heat.objects import resource_data as resource_data_objects
|
||||
from heat.objects import stack as stack_objects
|
||||
@@ -920,8 +919,13 @@ class Resource(object):
|
||||
)
|
||||
|
||||
with self.lock(engine_id):
|
||||
new_temp = template.Template.load(self.context, template_id)
|
||||
new_res_def = new_temp.resource_definitions(new_stack)[self.name]
|
||||
new_res_def = new_stack.t.resource_definitions(
|
||||
new_stack)[self.name]
|
||||
new_res_type = new_stack.env.registry.get_class_to_instantiate(
|
||||
new_res_def.resource_type, resource_name=self.name)
|
||||
if type(self) is not new_res_type:
|
||||
raise exception.UpdateReplace(self.name)
|
||||
|
||||
action_rollback = self.stack.action == self.stack.ROLLBACK
|
||||
status_in_progress = self.stack.status == self.stack.IN_PROGRESS
|
||||
if action_rollback and status_in_progress and self.replaced_by:
|
||||
|
||||
@@ -1743,9 +1743,15 @@ class ResourceTest(common.HeatTestCase):
|
||||
return_value=None)
|
||||
@mock.patch.object(resource.scheduler.TaskRunner, '__call__')
|
||||
def test_update_convergence(self, mock_call, mock_init):
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res',
|
||||
'ResourceWithPropsType')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
tmpl = template.Template({
|
||||
'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Resources': {
|
||||
'test_res': {'Type': 'ResourceWithPropsType'}
|
||||
}}, env=self.env)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
tmpl)
|
||||
stack.converge_stack(stack.t, action=stack.CREATE)
|
||||
res = stack.resources['test_res']
|
||||
res.requires = [2]
|
||||
res._store()
|
||||
self._assert_resource_lock(res.id, None, None)
|
||||
@@ -1757,11 +1763,13 @@ class ResourceTest(common.HeatTestCase):
|
||||
'Properties': {'Foo': 'abc'}}
|
||||
}}, env=self.env)
|
||||
new_temp.store()
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
|
||||
res_data = {(1, True): {u'id': 4, u'name': 'A', 'attrs': {}},
|
||||
(2, True): {u'id': 3, u'name': 'B', 'attrs': {}}}
|
||||
res.update_convergence(new_temp.id, res_data, 'engine-007', 120,
|
||||
mock.ANY)
|
||||
new_stack)
|
||||
|
||||
expected_rsrc_def = new_temp.resource_definitions(self.stack)[res.name]
|
||||
mock_init.assert_called_once_with(res.update, expected_rsrc_def)
|
||||
@@ -1771,8 +1779,35 @@ class ResourceTest(common.HeatTestCase):
|
||||
self._assert_resource_lock(res.id, None, 2)
|
||||
|
||||
def test_update_convergence_throws_timeout(self):
|
||||
tmpl = template.Template({
|
||||
'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Resources': {
|
||||
'test_res': {'Type': 'ResourceWithPropsType'}
|
||||
}}, env=self.env)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
tmpl)
|
||||
stack.converge_stack(stack.t, action=stack.CREATE)
|
||||
res = stack.resources['test_res']
|
||||
res._store()
|
||||
|
||||
new_temp = template.Template({
|
||||
'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Resources': {
|
||||
'test_res': {'Type': 'ResourceWithPropsType',
|
||||
'Properties': {'Foo': 'abc'}}
|
||||
}}, env=self.env)
|
||||
new_temp.store()
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
|
||||
res_data = {}
|
||||
self.assertRaises(scheduler.Timeout, res.update_convergence,
|
||||
new_temp.id, res_data, 'engine-007',
|
||||
-1, new_stack)
|
||||
|
||||
def test_update_convergence_checks_resource_class(self):
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res',
|
||||
'ResourceWithPropsType')
|
||||
'GenericResourceType')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
res._store()
|
||||
|
||||
@@ -1783,11 +1818,13 @@ class ResourceTest(common.HeatTestCase):
|
||||
'Properties': {'Foo': 'abc'}}
|
||||
}}, env=self.env)
|
||||
new_temp.store()
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
|
||||
res_data = {}
|
||||
self.assertRaises(scheduler.Timeout, res.update_convergence,
|
||||
self.assertRaises(exception.UpdateReplace, res.update_convergence,
|
||||
new_temp.id, res_data, 'engine-007',
|
||||
-1, mock.ANY)
|
||||
-1, new_stack)
|
||||
|
||||
def test_update_in_progress_convergence(self):
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||
@@ -1814,9 +1851,15 @@ class ResourceTest(common.HeatTestCase):
|
||||
|
||||
@mock.patch.object(resource.Resource, 'update')
|
||||
def test_update_resource_convergence_failed(self, mock_update):
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res',
|
||||
'ResourceWithPropsType')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
tmpl = template.Template({
|
||||
'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Resources': {
|
||||
'test_res': {'Type': 'ResourceWithPropsType'}
|
||||
}}, env=self.env)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
tmpl)
|
||||
stack.converge_stack(stack.t, action=stack.CREATE)
|
||||
res = stack.resources['test_res']
|
||||
res.requires = [2]
|
||||
res._store()
|
||||
self._assert_resource_lock(res.id, None, None)
|
||||
@@ -1832,11 +1875,13 @@ class ResourceTest(common.HeatTestCase):
|
||||
res_data = {(1, True): {u'id': 4, u'name': 'A', 'attrs': {}},
|
||||
(2, True): {u'id': 3, u'name': 'B', 'attrs': {}}}
|
||||
exc = Exception(_('Resource update failed'))
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
dummy_ex = exception.ResourceFailure(exc, res, action=res.UPDATE)
|
||||
mock_update.side_effect = dummy_ex
|
||||
self.assertRaises(exception.ResourceFailure,
|
||||
res.update_convergence, new_temp.id, res_data,
|
||||
'engine-007', 120, mock.ANY)
|
||||
'engine-007', 120, new_stack)
|
||||
|
||||
expected_rsrc_def = new_temp.resource_definitions(self.stack)[res.name]
|
||||
mock_update.assert_called_once_with(expected_rsrc_def)
|
||||
@@ -1848,9 +1893,15 @@ class ResourceTest(common.HeatTestCase):
|
||||
|
||||
@mock.patch.object(resource.Resource, 'update')
|
||||
def test_update_resource_convergence_update_replace(self, mock_update):
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res',
|
||||
'ResourceWithPropsType')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
tmpl = template.Template({
|
||||
'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Resources': {
|
||||
'test_res': {'Type': 'ResourceWithPropsType'}
|
||||
}}, env=self.env)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
tmpl)
|
||||
stack.converge_stack(stack.t, action=stack.CREATE)
|
||||
res = stack.resources['test_res']
|
||||
res.requires = [2]
|
||||
res._store()
|
||||
self._assert_resource_lock(res.id, None, None)
|
||||
@@ -1866,14 +1917,16 @@ class ResourceTest(common.HeatTestCase):
|
||||
res_data = {(1, True): {u'id': 4, u'name': 'A', 'attrs': {}},
|
||||
(2, True): {u'id': 3, u'name': 'B', 'attrs': {}}}
|
||||
mock_update.side_effect = exception.UpdateReplace
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
self.assertRaises(exception.UpdateReplace,
|
||||
res.update_convergence, new_temp.id, res_data,
|
||||
'engine-007', 120, mock.ANY)
|
||||
'engine-007', 120, new_stack)
|
||||
|
||||
expected_rsrc_def = new_temp.resource_definitions(self.stack)[res.name]
|
||||
mock_update.assert_called_once_with(expected_rsrc_def)
|
||||
# ensure that current_template_id was not updated
|
||||
self.assertIsNone(res.current_template_id)
|
||||
self.assertEqual(stack.t.id, res.current_template_id)
|
||||
# ensure that requires was not updated
|
||||
self.assertItemsEqual([2], res.requires)
|
||||
self._assert_resource_lock(res.id, None, 2)
|
||||
|
||||
Reference in New Issue
Block a user