Convergence: Load resource stack with correct template
When loading a resource, load the stack with template of the resource. Appropriate stack needs to be assigned to resource(resource.stack), else resource actions will fail. Co-Authored-By: Anant Patil <anant.patil@hp.com> Partial-Bug: #1512343 Change-Id: Ic4526152c8fd027049514b71554036321a61efd2
This commit is contained in:
parent
7252e659ee
commit
77c11d037c
|
@ -44,6 +44,7 @@ from heat.engine import support
|
||||||
from heat.engine import template
|
from heat.engine import template
|
||||||
from heat.objects import resource as resource_objects
|
from heat.objects import resource as resource_objects
|
||||||
from heat.objects import resource_data as resource_data_objects
|
from heat.objects import resource_data as resource_data_objects
|
||||||
|
from heat.objects import stack as stack_objects
|
||||||
from heat.rpc import client as rpc_client
|
from heat.rpc import client as rpc_client
|
||||||
|
|
||||||
cfg.CONF.import_opt('action_retry_limit', 'heat.common.config')
|
cfg.CONF.import_opt('action_retry_limit', 'heat.common.config')
|
||||||
|
@ -263,30 +264,32 @@ class Resource(object):
|
||||||
def load(cls, context, resource_id, is_update, data):
|
def load(cls, context, resource_id, is_update, data):
|
||||||
from heat.engine import stack as stack_mod
|
from heat.engine import stack as stack_mod
|
||||||
db_res = resource_objects.Resource.get_obj(context, resource_id)
|
db_res = resource_objects.Resource.get_obj(context, resource_id)
|
||||||
|
curr_stack = stack_mod.Stack.load(context, stack_id=db_res.stack_id,
|
||||||
|
cache_data=data)
|
||||||
|
|
||||||
@contextlib.contextmanager
|
resource_owning_stack = curr_stack
|
||||||
def special_stack(tmpl, swap_template):
|
if db_res.current_template_id != curr_stack.t.id:
|
||||||
stk = stack_mod.Stack.load(context, db_res.stack_id,
|
# load stack with template owning the resource
|
||||||
cache_data=data)
|
db_stack = stack_objects.Stack.get_by_id(context, db_res.stack_id)
|
||||||
|
db_stack.raw_template = None
|
||||||
|
db_stack.raw_template_id = db_res.current_template_id
|
||||||
|
resource_owning_stack = stack_mod.Stack.load(context,
|
||||||
|
stack=db_stack)
|
||||||
|
|
||||||
# NOTE(sirushtim): Because on delete/cleanup operations, we simply
|
# Load only the resource in question; don't load all resources
|
||||||
# update with another template, the stack object won't have the
|
# by invoking stack.resources. Maintain light-weight stack.
|
||||||
# template of the previous stack-run.
|
res_defn = resource_owning_stack.t.resource_definitions(
|
||||||
if swap_template:
|
resource_owning_stack)[db_res.name]
|
||||||
prev_tmpl = stk.t
|
resource = cls(db_res.name, res_defn, resource_owning_stack)
|
||||||
stk.t = tmpl
|
resource._load_data(db_res)
|
||||||
stk.resources
|
|
||||||
yield stk
|
|
||||||
if swap_template:
|
|
||||||
stk.t = prev_tmpl
|
|
||||||
|
|
||||||
tmpl = template.Template.load(context, db_res.current_template_id)
|
# assign current stack to the resource for updates
|
||||||
with special_stack(tmpl, not is_update) as stack:
|
if is_update:
|
||||||
stack_res = tmpl.resource_definitions(stack)[db_res.name]
|
resource.stack = curr_stack
|
||||||
resource = cls(db_res.name, stack_res, stack)
|
|
||||||
resource._load_data(db_res)
|
|
||||||
|
|
||||||
return resource, stack
|
# return resource owning stack so that it is not GCed since it
|
||||||
|
# is the only stack instance with a weak-ref from resource
|
||||||
|
return resource, resource_owning_stack, curr_stack
|
||||||
|
|
||||||
def make_replacement(self, new_tmpl_id):
|
def make_replacement(self, new_tmpl_id):
|
||||||
# 1. create the replacement with "replaces" = self.id
|
# 1. create the replacement with "replaces" = self.id
|
||||||
|
@ -886,7 +889,7 @@ class Resource(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_convergence(self, template_id, resource_data, engine_id,
|
def update_convergence(self, template_id, resource_data, engine_id,
|
||||||
timeout):
|
timeout, new_stack):
|
||||||
"""Update the resource synchronously.
|
"""Update the resource synchronously.
|
||||||
|
|
||||||
Persist the resource's current_template_id to template_id and
|
Persist the resource's current_template_id to template_id and
|
||||||
|
@ -903,7 +906,7 @@ class Resource(object):
|
||||||
|
|
||||||
with self.lock(engine_id):
|
with self.lock(engine_id):
|
||||||
new_temp = template.Template.load(self.context, template_id)
|
new_temp = template.Template.load(self.context, template_id)
|
||||||
new_res_def = new_temp.resource_definitions(self.stack)[self.name]
|
new_res_def = new_temp.resource_definitions(new_stack)[self.name]
|
||||||
if self.stack.action == self.stack.ROLLBACK and \
|
if self.stack.action == self.stack.ROLLBACK and \
|
||||||
self.stack.status == self.stack.IN_PROGRESS \
|
self.stack.status == self.stack.IN_PROGRESS \
|
||||||
and self.replaced_by:
|
and self.replaced_by:
|
||||||
|
|
|
@ -466,7 +466,7 @@ class Port(neutron.NeutronResource):
|
||||||
|
|
||||||
props = {'fixed_ips': []}
|
props = {'fixed_ips': []}
|
||||||
if convergence:
|
if convergence:
|
||||||
existing_port, stack = resource.Resource.load(
|
existing_port, rsrc_owning_stack, stack = resource.Resource.load(
|
||||||
prev_port.context, prev_port.replaced_by, True,
|
prev_port.context, prev_port.replaced_by, True,
|
||||||
prev_port.stack.cache_data
|
prev_port.stack.cache_data
|
||||||
)
|
)
|
||||||
|
|
|
@ -397,7 +397,7 @@ class ServerNetworkMixin(object):
|
||||||
self.stack._backup_stack().resources.get(self.name)
|
self.stack._backup_stack().resources.get(self.name)
|
||||||
|
|
||||||
if convergence:
|
if convergence:
|
||||||
rsrc, stack = resource.Resource.load(
|
rsrc, rsrc_owning_stack, stack = resource.Resource.load(
|
||||||
prev_server.context, prev_server.replaced_by, True,
|
prev_server.context, prev_server.replaced_by, True,
|
||||||
prev_server.stack.cache_data
|
prev_server.stack.cache_data
|
||||||
)
|
)
|
||||||
|
|
|
@ -140,14 +140,13 @@ class WorkerService(service.Service):
|
||||||
# no data to resolve in cleanup phase
|
# no data to resolve in cleanup phase
|
||||||
cache_data = {}
|
cache_data = {}
|
||||||
|
|
||||||
rsrc, stack = None, None
|
|
||||||
try:
|
try:
|
||||||
rsrc, stack = resource.Resource.load(cnxt, resource_id, is_update,
|
return resource.Resource.load(cnxt, resource_id,
|
||||||
cache_data)
|
is_update, cache_data)
|
||||||
except (exception.ResourceNotFound, exception.NotFound):
|
except (exception.ResourceNotFound, exception.NotFound):
|
||||||
pass # can be ignored
|
pass # can be ignored
|
||||||
|
|
||||||
return rsrc, stack
|
return None, None, None
|
||||||
|
|
||||||
def _do_check_resource(self, cnxt, current_traversal, tmpl, resource_data,
|
def _do_check_resource(self, cnxt, current_traversal, tmpl, resource_data,
|
||||||
is_update, rsrc, stack, adopt_stack_data):
|
is_update, rsrc, stack, adopt_stack_data):
|
||||||
|
@ -156,7 +155,7 @@ class WorkerService(service.Service):
|
||||||
try:
|
try:
|
||||||
check_resource_update(rsrc, tmpl.id, resource_data,
|
check_resource_update(rsrc, tmpl.id, resource_data,
|
||||||
self.engine_id,
|
self.engine_id,
|
||||||
stack.time_remaining())
|
stack)
|
||||||
except exception.UpdateReplace:
|
except exception.UpdateReplace:
|
||||||
new_res_id = rsrc.make_replacement(tmpl.id)
|
new_res_id = rsrc.make_replacement(tmpl.id)
|
||||||
LOG.info("Replacing resource with new id %s", new_res_id)
|
LOG.info("Replacing resource with new id %s", new_res_id)
|
||||||
|
@ -229,7 +228,7 @@ class WorkerService(service.Service):
|
||||||
|
|
||||||
def _get_input_data(req, fwd):
|
def _get_input_data(req, fwd):
|
||||||
if fwd:
|
if fwd:
|
||||||
return construct_input_data(rsrc)
|
return construct_input_data(rsrc, stack)
|
||||||
else:
|
else:
|
||||||
# Don't send data if initiating clean-up for self i.e.
|
# Don't send data if initiating clean-up for self i.e.
|
||||||
# initiating delete of a replaced resource
|
# initiating delete of a replaced resource
|
||||||
|
@ -272,8 +271,9 @@ class WorkerService(service.Service):
|
||||||
associated resource.
|
associated resource.
|
||||||
"""
|
"""
|
||||||
resource_data = dict(sync_point.deserialize_input_data(data))
|
resource_data = dict(sync_point.deserialize_input_data(data))
|
||||||
rsrc, stack = self._load_resource(cnxt, resource_id, resource_data,
|
rsrc, rsrc_owning_stack, stack = self._load_resource(cnxt, resource_id,
|
||||||
is_update)
|
resource_data,
|
||||||
|
is_update)
|
||||||
|
|
||||||
if rsrc is None:
|
if rsrc is None:
|
||||||
return
|
return
|
||||||
|
@ -307,10 +307,10 @@ class WorkerService(service.Service):
|
||||||
rsrc, stack)
|
rsrc, stack)
|
||||||
|
|
||||||
|
|
||||||
def construct_input_data(rsrc):
|
def construct_input_data(rsrc, curr_stack):
|
||||||
attributes = rsrc.stack.get_dep_attrs(
|
attributes = curr_stack.get_dep_attrs(
|
||||||
six.itervalues(rsrc.stack.resources),
|
six.itervalues(curr_stack.resources),
|
||||||
rsrc.stack.outputs,
|
curr_stack.outputs,
|
||||||
rsrc.name)
|
rsrc.name)
|
||||||
resolved_attributes = {}
|
resolved_attributes = {}
|
||||||
for attr in attributes:
|
for attr in attributes:
|
||||||
|
@ -366,12 +366,14 @@ def propagate_check_resource(cnxt, rpc_client, next_res_id,
|
||||||
|
|
||||||
|
|
||||||
def check_resource_update(rsrc, template_id, resource_data, engine_id,
|
def check_resource_update(rsrc, template_id, resource_data, engine_id,
|
||||||
timeout):
|
stack):
|
||||||
"""Create or update the Resource if appropriate."""
|
"""Create or update the Resource if appropriate."""
|
||||||
if rsrc.action == resource.Resource.INIT:
|
if rsrc.action == resource.Resource.INIT:
|
||||||
rsrc.create_convergence(template_id, resource_data, engine_id, timeout)
|
rsrc.create_convergence(template_id, resource_data, engine_id,
|
||||||
|
stack.time_remaining())
|
||||||
else:
|
else:
|
||||||
rsrc.update_convergence(template_id, resource_data, engine_id, timeout)
|
rsrc.update_convergence(template_id, resource_data, engine_id,
|
||||||
|
stack.time_remaining(), stack)
|
||||||
|
|
||||||
|
|
||||||
def check_resource_cleanup(rsrc, template_id, resource_data, engine_id,
|
def check_resource_cleanup(rsrc, template_id, resource_data, engine_id,
|
||||||
|
|
|
@ -179,7 +179,7 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
||||||
mock_cru.assert_called_once_with(self.resource,
|
mock_cru.assert_called_once_with(self.resource,
|
||||||
self.resource.stack.t.id,
|
self.resource.stack.t.id,
|
||||||
{}, self.worker.engine_id,
|
{}, self.worker.engine_id,
|
||||||
tr())
|
mock.ANY)
|
||||||
self.assertTrue(mock_mr.called)
|
self.assertTrue(mock_mr.called)
|
||||||
self.assertFalse(mock_crc.called)
|
self.assertFalse(mock_crc.called)
|
||||||
self.assertFalse(mock_pcr.called)
|
self.assertFalse(mock_pcr.called)
|
||||||
|
@ -200,7 +200,7 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
||||||
mock_cru.assert_called_once_with(self.resource,
|
mock_cru.assert_called_once_with(self.resource,
|
||||||
self.resource.stack.t.id,
|
self.resource.stack.t.id,
|
||||||
{}, self.worker.engine_id,
|
{}, self.worker.engine_id,
|
||||||
tr())
|
mock.ANY)
|
||||||
self.assertFalse(mock_crc.called)
|
self.assertFalse(mock_crc.called)
|
||||||
self.assertFalse(mock_pcr.called)
|
self.assertFalse(mock_pcr.called)
|
||||||
self.assertFalse(mock_csc.called)
|
self.assertFalse(mock_csc.called)
|
||||||
|
@ -547,7 +547,8 @@ class MiscMethodsTest(common.HeatTestCase):
|
||||||
'uuid': mock.ANY,
|
'uuid': mock.ANY,
|
||||||
'action': mock.ANY,
|
'action': mock.ANY,
|
||||||
'status': mock.ANY}
|
'status': mock.ANY}
|
||||||
actual_input_data = worker.construct_input_data(self.resource)
|
actual_input_data = worker.construct_input_data(self.resource,
|
||||||
|
self.stack)
|
||||||
self.assertEqual(expected_input_data, actual_input_data)
|
self.assertEqual(expected_input_data, actual_input_data)
|
||||||
|
|
||||||
def test_construct_input_data_exception(self):
|
def test_construct_input_data_exception(self):
|
||||||
|
@ -561,7 +562,8 @@ class MiscMethodsTest(common.HeatTestCase):
|
||||||
self.resource.FnGetAtt = mock.Mock(
|
self.resource.FnGetAtt = mock.Mock(
|
||||||
side_effect=exception.InvalidTemplateAttribute(resource='A',
|
side_effect=exception.InvalidTemplateAttribute(resource='A',
|
||||||
key='value'))
|
key='value'))
|
||||||
actual_input_data = worker.construct_input_data(self.resource)
|
actual_input_data = worker.construct_input_data(self.resource,
|
||||||
|
self.stack)
|
||||||
self.assertEqual(expected_input_data, actual_input_data)
|
self.assertEqual(expected_input_data, actual_input_data)
|
||||||
|
|
||||||
@mock.patch.object(sync_point, 'sync')
|
@mock.patch.object(sync_point, 'sync')
|
||||||
|
@ -608,7 +610,7 @@ class MiscMethodsTest(common.HeatTestCase):
|
||||||
self.resource.action = 'INIT'
|
self.resource.action = 'INIT'
|
||||||
worker.check_resource_update(self.resource, self.resource.stack.t.id,
|
worker.check_resource_update(self.resource, self.resource.stack.t.id,
|
||||||
{}, 'engine-id',
|
{}, 'engine-id',
|
||||||
self.stack.timeout_secs())
|
self.stack)
|
||||||
self.assertTrue(mock_create.called)
|
self.assertTrue(mock_create.called)
|
||||||
self.assertFalse(mock_update.called)
|
self.assertFalse(mock_update.called)
|
||||||
|
|
||||||
|
@ -619,7 +621,7 @@ class MiscMethodsTest(common.HeatTestCase):
|
||||||
self.resource.action = 'CREATE'
|
self.resource.action = 'CREATE'
|
||||||
worker.check_resource_update(self.resource, self.resource.stack.t.id,
|
worker.check_resource_update(self.resource, self.resource.stack.t.id,
|
||||||
{}, 'engine-id',
|
{}, 'engine-id',
|
||||||
self.stack.timeout_secs())
|
self.stack)
|
||||||
self.assertFalse(mock_create.called)
|
self.assertFalse(mock_create.called)
|
||||||
self.assertTrue(mock_update.called)
|
self.assertTrue(mock_update.called)
|
||||||
|
|
||||||
|
@ -630,7 +632,7 @@ class MiscMethodsTest(common.HeatTestCase):
|
||||||
self.resource.action = 'UPDATE'
|
self.resource.action = 'UPDATE'
|
||||||
worker.check_resource_update(self.resource, self.resource.stack.t.id,
|
worker.check_resource_update(self.resource, self.resource.stack.t.id,
|
||||||
{}, 'engine-id',
|
{}, 'engine-id',
|
||||||
self.stack.timeout_secs())
|
self.stack)
|
||||||
self.assertFalse(mock_create.called)
|
self.assertFalse(mock_create.called)
|
||||||
self.assertTrue(mock_update.called)
|
self.assertTrue(mock_update.called)
|
||||||
|
|
||||||
|
|
|
@ -95,8 +95,8 @@ class ResourceTest(common.HeatTestCase):
|
||||||
res.current_template_id = self.stack.t.id
|
res.current_template_id = self.stack.t.id
|
||||||
res.state_set('CREATE', 'IN_PROGRESS')
|
res.state_set('CREATE', 'IN_PROGRESS')
|
||||||
self.stack.add_resource(res)
|
self.stack.add_resource(res)
|
||||||
loaded_res, stack = resource.Resource.load(self.stack.context,
|
loaded_res, res_owning_stack, stack = resource.Resource.load(
|
||||||
res.id, True, {})
|
self.stack.context, res.id, True, {})
|
||||||
self.assertEqual(loaded_res.id, res.id)
|
self.assertEqual(loaded_res.id, res.id)
|
||||||
self.assertEqual(self.stack.t, stack.t)
|
self.assertEqual(self.stack.t, stack.t)
|
||||||
|
|
||||||
|
@ -119,8 +119,8 @@ class ResourceTest(common.HeatTestCase):
|
||||||
res.current_template_id = self.old_stack.t.id
|
res.current_template_id = self.old_stack.t.id
|
||||||
res.state_set('CREATE', 'IN_PROGRESS')
|
res.state_set('CREATE', 'IN_PROGRESS')
|
||||||
self.old_stack.add_resource(res)
|
self.old_stack.add_resource(res)
|
||||||
loaded_res, stack = resource.Resource.load(self.old_stack.context,
|
loaded_res, res_owning_stack, stack = resource.Resource.load(
|
||||||
res.id, False, {})
|
self.old_stack.context, res.id, False, {})
|
||||||
self.assertEqual(loaded_res.id, res.id)
|
self.assertEqual(loaded_res.id, res.id)
|
||||||
self.assertEqual(self.old_stack.t, stack.t)
|
self.assertEqual(self.old_stack.t, stack.t)
|
||||||
self.assertNotEqual(self.new_stack.t, stack.t)
|
self.assertNotEqual(self.new_stack.t, stack.t)
|
||||||
|
@ -141,12 +141,12 @@ class ResourceTest(common.HeatTestCase):
|
||||||
res.current_template_id = self.stack.t.id
|
res.current_template_id = self.stack.t.id
|
||||||
res.state_set('CREATE', 'IN_PROGRESS')
|
res.state_set('CREATE', 'IN_PROGRESS')
|
||||||
self.stack.add_resource(res)
|
self.stack.add_resource(res)
|
||||||
origin_resources = self.stack._resources
|
origin_resources = self.stack.resources
|
||||||
self.stack._resources = None
|
self.stack._resources = None
|
||||||
|
|
||||||
loaded_res, stack = resource.Resource.load(self.stack.context,
|
loaded_res, res_owning_stack, stack = resource.Resource.load(
|
||||||
res.id, False, {})
|
self.stack.context, res.id, False, {})
|
||||||
self.assertEqual(origin_resources, stack._resources)
|
self.assertEqual(origin_resources, stack.resources)
|
||||||
self.assertEqual(loaded_res.id, res.id)
|
self.assertEqual(loaded_res.id, res.id)
|
||||||
self.assertEqual(self.stack.t, stack.t)
|
self.assertEqual(self.stack.t, stack.t)
|
||||||
|
|
||||||
|
@ -1757,7 +1757,8 @@ class ResourceTest(common.HeatTestCase):
|
||||||
|
|
||||||
res_data = {(1, True): {u'id': 4, u'name': 'A', 'attrs': {}},
|
res_data = {(1, True): {u'id': 4, u'name': 'A', 'attrs': {}},
|
||||||
(2, True): {u'id': 3, u'name': 'B', 'attrs': {}}}
|
(2, True): {u'id': 3, u'name': 'B', 'attrs': {}}}
|
||||||
res.update_convergence(new_temp.id, res_data, 'engine-007', 120)
|
res.update_convergence(new_temp.id, res_data, 'engine-007', 120,
|
||||||
|
mock.ANY)
|
||||||
|
|
||||||
expected_rsrc_def = new_temp.resource_definitions(self.stack)[res.name]
|
expected_rsrc_def = new_temp.resource_definitions(self.stack)[res.name]
|
||||||
mock_init.assert_called_once_with(res.update, expected_rsrc_def)
|
mock_init.assert_called_once_with(res.update, expected_rsrc_def)
|
||||||
|
@ -1783,7 +1784,7 @@ class ResourceTest(common.HeatTestCase):
|
||||||
res_data = {}
|
res_data = {}
|
||||||
self.assertRaises(scheduler.Timeout, res.update_convergence,
|
self.assertRaises(scheduler.Timeout, res.update_convergence,
|
||||||
new_temp.id, res_data, 'engine-007',
|
new_temp.id, res_data, 'engine-007',
|
||||||
0)
|
0, mock.ANY)
|
||||||
|
|
||||||
def test_update_in_progress_convergence(self):
|
def test_update_in_progress_convergence(self):
|
||||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||||
|
@ -1800,7 +1801,8 @@ class ResourceTest(common.HeatTestCase):
|
||||||
res.update_convergence,
|
res.update_convergence,
|
||||||
'template_key',
|
'template_key',
|
||||||
res_data, 'engine-007',
|
res_data, 'engine-007',
|
||||||
self.dummy_timeout)
|
self.dummy_timeout,
|
||||||
|
mock.ANY)
|
||||||
msg = ("The resource %s is already being updated." %
|
msg = ("The resource %s is already being updated." %
|
||||||
res.name)
|
res.name)
|
||||||
self.assertEqual(msg, six.text_type(ex))
|
self.assertEqual(msg, six.text_type(ex))
|
||||||
|
@ -1831,7 +1833,7 @@ class ResourceTest(common.HeatTestCase):
|
||||||
mock_update.side_effect = dummy_ex
|
mock_update.side_effect = dummy_ex
|
||||||
self.assertRaises(exception.ResourceFailure,
|
self.assertRaises(exception.ResourceFailure,
|
||||||
res.update_convergence, new_temp.id, res_data,
|
res.update_convergence, new_temp.id, res_data,
|
||||||
'engine-007', 120)
|
'engine-007', 120, mock.ANY)
|
||||||
|
|
||||||
expected_rsrc_def = new_temp.resource_definitions(self.stack)[res.name]
|
expected_rsrc_def = new_temp.resource_definitions(self.stack)[res.name]
|
||||||
mock_update.assert_called_once_with(expected_rsrc_def)
|
mock_update.assert_called_once_with(expected_rsrc_def)
|
||||||
|
@ -1863,7 +1865,7 @@ class ResourceTest(common.HeatTestCase):
|
||||||
mock_update.side_effect = exception.UpdateReplace
|
mock_update.side_effect = exception.UpdateReplace
|
||||||
self.assertRaises(exception.UpdateReplace,
|
self.assertRaises(exception.UpdateReplace,
|
||||||
res.update_convergence, new_temp.id, res_data,
|
res.update_convergence, new_temp.id, res_data,
|
||||||
'engine-007', 120)
|
'engine-007', 120, mock.ANY)
|
||||||
|
|
||||||
expected_rsrc_def = new_temp.resource_definitions(self.stack)[res.name]
|
expected_rsrc_def = new_temp.resource_definitions(self.stack)[res.name]
|
||||||
mock_update.assert_called_once_with(expected_rsrc_def)
|
mock_update.assert_called_once_with(expected_rsrc_def)
|
||||||
|
@ -2096,13 +2098,15 @@ class ResourceTest(common.HeatTestCase):
|
||||||
stack.store()
|
stack.store()
|
||||||
mock_tmpl_load.return_value = tmpl
|
mock_tmpl_load.return_value = tmpl
|
||||||
res = stack['res']
|
res = stack['res']
|
||||||
|
res.current_template_id = stack.t.id
|
||||||
res._store()
|
res._store()
|
||||||
data = {'bar': {'atrr1': 'baz', 'attr2': 'baz2'}}
|
data = {'bar': {'atrr1': 'baz', 'attr2': 'baz2'}}
|
||||||
mock_stack_load.return_value = stack
|
mock_stack_load.return_value = stack
|
||||||
resource.Resource.load(stack.context, res.id, True, data)
|
resource.Resource.load(stack.context, res.id, True, data)
|
||||||
mock_stack_load.assert_called_once_with(stack.context,
|
self.assertTrue(mock_stack_load.called)
|
||||||
stack.id,
|
mock_stack_load.assert_called_with(stack.context,
|
||||||
cache_data=data)
|
stack_id=stack.id,
|
||||||
|
cache_data=data)
|
||||||
self.assertTrue(mock_load_data.called)
|
self.assertTrue(mock_load_data.called)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue