Use StackDefinition in intrinsic functions for resolving data
This unifies the 'lightweight stack' used in convergence with the how things work the rest of the time: we now always obtain resource data from the StackDefinition's ResourceProxy objects. This means that when we are checking an individual resource, we will never create all of the other Resource objects for the stack in memory (although we already avoided loading data for them from the database) - now we will only create ResourceProxy objects as needed. Change-Id: Id7472557e26d172df88841ff7f20afdd7f5bfada Implements: blueprint stack-definitionchanges/77/435177/30
parent
c889f08ab5
commit
764b8fb251
|
@ -45,7 +45,8 @@ class Function(object):
|
|||
return None
|
||||
|
||||
stack = ref()
|
||||
assert stack is not None, "Need a reference to the Stack object"
|
||||
assert stack is not None, ("Need a reference to the "
|
||||
"StackDefinition object")
|
||||
return stack
|
||||
|
||||
def validate(self):
|
||||
|
|
|
@ -222,9 +222,7 @@ class GetAttThenSelect(function.Function):
|
|||
return
|
||||
|
||||
attr = function.resolve(self._attribute)
|
||||
from heat.engine import resource
|
||||
if (type(res).get_attribute == resource.Resource.get_attribute and
|
||||
attr not in res.attributes_schema):
|
||||
if attr not in res.attributes_schema:
|
||||
raise exception.InvalidTemplateAttribute(
|
||||
resource=self._resource_name, key=attr)
|
||||
|
||||
|
|
|
@ -340,8 +340,7 @@ class Resource(status.ResourceStatus):
|
|||
|
||||
# Load only the resource in question; don't load all resources
|
||||
# by invoking stack.resources. Maintain light-weight stack.
|
||||
res_defn = resource_owning_stack.t.resource_definitions(
|
||||
resource_owning_stack)[db_res.name]
|
||||
res_defn = resource_owning_stack.defn.resource_definition(db_res.name)
|
||||
resource = cls(db_res.name, res_defn, resource_owning_stack)
|
||||
resource._load_data(db_res)
|
||||
|
||||
|
@ -1343,8 +1342,7 @@ class Resource(status.ResourceStatus):
|
|||
|
||||
self._calling_engine_id = engine_id
|
||||
registry = new_stack.env.registry
|
||||
new_res_def = new_stack.t.resource_definitions(
|
||||
new_stack)[self.name]
|
||||
new_res_def = new_stack.defn.resource_definition(self.name)
|
||||
new_res_type = registry.get_class_to_instantiate(
|
||||
new_res_def.resource_type, resource_name=self.name)
|
||||
restricted_actions = registry.get_rsrc_restricted_actions(
|
||||
|
|
|
@ -309,7 +309,7 @@ class InstanceGroup(stack_resource.StackResource):
|
|||
def changing_instances(tmpl):
|
||||
instances = grouputils.get_members(self)
|
||||
current = set((i.name, i.t) for i in instances)
|
||||
updated = set(tmpl.resource_definitions(self.nested()).items())
|
||||
updated = set(tmpl.resource_definitions(None).items())
|
||||
# includes instances to be updated and deleted
|
||||
affected = set(k for k, v in current ^ updated)
|
||||
return set(i.FnGetRefId() for i in instances if i.name in affected)
|
||||
|
|
|
@ -283,8 +283,7 @@ class ResourceGroup(stack_resource.StackResource):
|
|||
first_name = next(self._resource_names(update_rsrc_data=False))
|
||||
test_tmpl = self._assemble_nested([first_name],
|
||||
include_all=True)
|
||||
res_def = next(six.itervalues(
|
||||
test_tmpl.resource_definitions(self.stack)))
|
||||
res_def = next(six.itervalues(test_tmpl.resource_definitions(None)))
|
||||
# make sure we can resolve the nested resource type
|
||||
self.stack.env.get_class_to_instantiate(res_def.resource_type)
|
||||
|
||||
|
|
|
@ -298,18 +298,18 @@ class Stack(collections.Mapping):
|
|||
|
||||
@property
|
||||
def outputs(self):
|
||||
if self._outputs is None:
|
||||
self._outputs = self.t.outputs(self)
|
||||
return self._outputs
|
||||
return {n: self.defn.output_definition(n)
|
||||
for n in self.defn.enabled_output_names()}
|
||||
|
||||
@property
|
||||
def resources(self):
|
||||
if self._resources is None:
|
||||
res_defns = self.t.resource_definitions(self)
|
||||
|
||||
self._resources = dict((name,
|
||||
resource.Resource(name, data, self))
|
||||
for (name, data) in res_defns.items())
|
||||
self._resources = {
|
||||
name: resource.Resource(name,
|
||||
self.defn.resource_definition(name),
|
||||
self)
|
||||
for name in self.defn.enabled_rsrc_names()
|
||||
}
|
||||
|
||||
return self._resources
|
||||
|
||||
|
@ -320,7 +320,6 @@ class Stack(collections.Mapping):
|
|||
stk_defn.update_resource_data(self.defn, rsrc.name, node_data)
|
||||
|
||||
def _find_filtered_resources(self, filters=None):
|
||||
rsrc_def_cache = {self.t.id: self.t.resource_definitions(self)}
|
||||
if filters:
|
||||
assert self.cache_data is None, \
|
||||
"Resources should not be loaded from the DB"
|
||||
|
@ -328,8 +327,10 @@ class Stack(collections.Mapping):
|
|||
self.context, self.id, filters)
|
||||
else:
|
||||
resources = self._db_resources_get()
|
||||
|
||||
stk_def_cache = {}
|
||||
for rsc in six.itervalues(resources):
|
||||
loaded_res = self._resource_from_db_resource(rsc, rsrc_def_cache)
|
||||
loaded_res = self._resource_from_db_resource(rsc, stk_def_cache)
|
||||
if loaded_res is not None:
|
||||
yield loaded_res
|
||||
|
||||
|
@ -374,7 +375,7 @@ class Stack(collections.Mapping):
|
|||
self._db_resources = _db_resources
|
||||
return self._db_resources
|
||||
|
||||
def _resource_from_db_resource(self, db_res, rsrc_def_cache=None):
|
||||
def _resource_from_db_resource(self, db_res, stk_def_cache=None):
|
||||
tid = db_res.current_template_id
|
||||
if tid is None:
|
||||
tid = self.t.id
|
||||
|
@ -384,19 +385,19 @@ class Stack(collections.Mapping):
|
|||
if cur_res is not None and (cur_res.id == db_res.id):
|
||||
return cur_res
|
||||
|
||||
if rsrc_def_cache and tid in rsrc_def_cache:
|
||||
rsrc_def = rsrc_def_cache[tid]
|
||||
stk_def = self.defn
|
||||
elif stk_def_cache and tid in stk_def_cache:
|
||||
stk_def = stk_def_cache[tid]
|
||||
else:
|
||||
if tid == self.t.id:
|
||||
rsrc_def = self.t.resource_definitions(self)
|
||||
else:
|
||||
t = tmpl.Template.load(self.context, tid)
|
||||
rsrc_def = t.resource_definitions(self)
|
||||
if rsrc_def_cache:
|
||||
rsrc_def_cache[tid] = rsrc_def
|
||||
defn = rsrc_def.get(db_res.name)
|
||||
t = tmpl.Template.load(self.context, tid)
|
||||
stk_def = self.defn.clone_with_new_template(t,
|
||||
self.identifier())
|
||||
if stk_def_cache is not None:
|
||||
stk_def_cache[tid] = stk_def
|
||||
|
||||
if defn is None:
|
||||
try:
|
||||
defn = stk_def.resource_definition(db_res.name)
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
return resource.Resource(db_res.name, defn, self)
|
||||
|
@ -724,7 +725,7 @@ class Stack(collections.Mapping):
|
|||
"""Insert the given resource into the stack."""
|
||||
template = resource.stack.t
|
||||
resource.stack = self
|
||||
definition = resource.t.reparse(self, template)
|
||||
definition = resource.t.reparse(self.defn, template)
|
||||
resource.t = definition
|
||||
resource.reparse()
|
||||
self.resources[resource.name] = resource
|
||||
|
@ -769,16 +770,23 @@ class Stack(collections.Mapping):
|
|||
not found.
|
||||
"""
|
||||
for r in six.itervalues(self):
|
||||
if (r.state in (
|
||||
(r.INIT, r.COMPLETE),
|
||||
(r.CREATE, r.IN_PROGRESS),
|
||||
(r.CREATE, r.COMPLETE),
|
||||
(r.RESUME, r.IN_PROGRESS),
|
||||
(r.RESUME, r.COMPLETE),
|
||||
(r.UPDATE, r.IN_PROGRESS),
|
||||
(r.UPDATE, r.COMPLETE),
|
||||
(r.CHECK, r.COMPLETE)) and
|
||||
(r.FnGetRefId() == refid or r.name == refid)):
|
||||
if r.state not in ((r.INIT, r.COMPLETE),
|
||||
(r.CREATE, r.IN_PROGRESS),
|
||||
(r.CREATE, r.COMPLETE),
|
||||
(r.RESUME, r.IN_PROGRESS),
|
||||
(r.RESUME, r.COMPLETE),
|
||||
(r.UPDATE, r.IN_PROGRESS),
|
||||
(r.UPDATE, r.COMPLETE),
|
||||
(r.CHECK, r.COMPLETE)):
|
||||
continue
|
||||
|
||||
proxy = self.defn[r.name]
|
||||
if proxy._resource_data is None:
|
||||
matches = r.FnGetRefId() == refid or r.name == refid
|
||||
else:
|
||||
matches = proxy.FnGetRefId() == refid
|
||||
|
||||
if matches:
|
||||
if self.cache_data is not None and r.id is not None:
|
||||
# We don't have resources loaded from the database at this
|
||||
# point, so load the data for just this one from the DB.
|
||||
|
@ -786,7 +794,6 @@ class Stack(collections.Mapping):
|
|||
r.id)
|
||||
if db_res is not None:
|
||||
r._load_data(db_res)
|
||||
|
||||
return r
|
||||
|
||||
def register_access_allowed_handler(self, credential_id, handler):
|
||||
|
@ -852,6 +859,8 @@ class Stack(collections.Mapping):
|
|||
raise exception.StackValidationFailed(
|
||||
message=_("Duplicate names %s") % dup_names)
|
||||
|
||||
self._update_all_resource_data(for_resources=True, for_outputs=True)
|
||||
|
||||
if self.strict_validate:
|
||||
iter_rsc = self.dependencies
|
||||
else:
|
||||
|
@ -1252,7 +1261,9 @@ class Stack(collections.Mapping):
|
|||
self.prev_raw_template_id = getattr(self.t, 'id', None)
|
||||
|
||||
# switch template and reset dependencies
|
||||
self.t = template
|
||||
self.defn = self.defn.clone_with_new_template(template,
|
||||
self.identifier(),
|
||||
clear_resource_data=True)
|
||||
self.reset_dependencies()
|
||||
self._resources = None
|
||||
self.cache_data = None
|
||||
|
@ -1937,8 +1948,8 @@ class Stack(collections.Mapping):
|
|||
timeout_mins=self.timeout_mins,
|
||||
disable_rollback=self.disable_rollback)
|
||||
|
||||
for name, defn in six.iteritems(
|
||||
template.resource_definitions(newstack)):
|
||||
for name in newstack.defn.enabled_rsrc_names():
|
||||
defn = newstack.defn.resource_definition(name)
|
||||
rsrc = resource.Resource(name, defn, self)
|
||||
data = snapshot.data['resources'].get(name)
|
||||
handle_restore = getattr(rsrc, 'handle_restore', None)
|
||||
|
|
|
@ -205,7 +205,7 @@ class StackUpdate(object):
|
|||
# of the existing stack (which is the stack being updated)
|
||||
# but with the template of the new stack (in case the update
|
||||
# is switching template implementations)
|
||||
new_snippet = new_res.t.reparse(self.existing_stack,
|
||||
new_snippet = new_res.t.reparse(self.existing_stack.defn,
|
||||
self.new_stack.t)
|
||||
if is_substituted:
|
||||
substitute = type(new_res)(existing_res.name,
|
||||
|
|
|
@ -166,7 +166,7 @@ class TestAutoScalingPolicy(common.HeatTestCase):
|
|||
'reference_id': 'convg_xyz'
|
||||
})}
|
||||
stack = utils.parse_stack(t, cache_data=cache_data)
|
||||
rsrc = stack['my-policy']
|
||||
rsrc = stack.defn['my-policy']
|
||||
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
||||
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ class LaunchConfigurationTest(common.HeatTestCase):
|
|||
})}
|
||||
stack = utils.parse_stack(t, params=inline_templates.as_params,
|
||||
cache_data=cache_data)
|
||||
rsrc = stack['LaunchConfig']
|
||||
rsrc = stack.defn['LaunchConfig']
|
||||
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
||||
|
||||
def test_launch_config_create_with_instanceid(self):
|
||||
|
|
|
@ -166,7 +166,7 @@ class TestAutoScalingPolicy(common.HeatTestCase):
|
|||
'reference_id': 'http://convg_signed_url'
|
||||
})}
|
||||
stack = utils.parse_stack(t, cache_data=cache_data)
|
||||
rsrc = stack['WebServerScaleUpPolicy']
|
||||
rsrc = stack.defn['WebServerScaleUpPolicy']
|
||||
self.assertEqual('http://convg_signed_url', rsrc.FnGetRefId())
|
||||
|
||||
|
||||
|
|
|
@ -405,7 +405,7 @@ class EIPTest(common.HeatTestCase):
|
|||
'status': 'COMPLETE',
|
||||
'reference_id': '1.1.1.1'})})
|
||||
|
||||
rsrc = stack['eip']
|
||||
rsrc = stack.defn['eip']
|
||||
self.assertEqual('1.1.1.1', rsrc.FnGetRefId())
|
||||
|
||||
|
||||
|
@ -480,9 +480,8 @@ class AllocTest(common.HeatTestCase):
|
|||
self.fc.servers.get(server).AndReturn(mock_server)
|
||||
|
||||
def create_eip(self, t, stack, resource_name):
|
||||
resource_defns = stack.t.resource_definitions(stack)
|
||||
rsrc = eip.ElasticIp(resource_name,
|
||||
resource_defns[resource_name],
|
||||
stack.defn.resource_definition(resource_name),
|
||||
stack)
|
||||
self.assertIsNone(rsrc.validate())
|
||||
scheduler.TaskRunner(rsrc.create)()
|
||||
|
@ -492,9 +491,9 @@ class AllocTest(common.HeatTestCase):
|
|||
return rsrc
|
||||
|
||||
def create_association(self, t, stack, resource_name):
|
||||
resource_defns = stack.t.resource_definitions(stack)
|
||||
resource_defn = stack.defn.resource_definition(resource_name)
|
||||
rsrc = eip.ElasticIpAssociation(resource_name,
|
||||
resource_defns[resource_name],
|
||||
resource_defn,
|
||||
stack)
|
||||
self.assertIsNone(rsrc.validate())
|
||||
scheduler.TaskRunner(rsrc.create)()
|
||||
|
@ -530,7 +529,7 @@ class AllocTest(common.HeatTestCase):
|
|||
}).AndReturn({'floatingip': {
|
||||
"status": "ACTIVE",
|
||||
"id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
|
||||
"floating_ip_address": "192.168.9.3"
|
||||
"floating_ip_address": "11.0.0.1"
|
||||
}})
|
||||
|
||||
def mock_show_floatingip(self, refid):
|
||||
|
@ -766,7 +765,6 @@ class AllocTest(common.HeatTestCase):
|
|||
mock_again=True)
|
||||
|
||||
self.mock_create_floatingip()
|
||||
self.mock_show_floatingip('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
|
||||
self.m.ReplayAll()
|
||||
|
||||
t = template_format.parse(eip_template_ipassoc)
|
||||
|
@ -780,7 +778,7 @@ class AllocTest(common.HeatTestCase):
|
|||
update_server_id = '5678'
|
||||
props['InstanceId'] = update_server_id
|
||||
update_snippet = rsrc_defn.ResourceDefinition(ass.name, ass.type(),
|
||||
stack.t.parse(stack,
|
||||
stack.t.parse(stack.defn,
|
||||
props))
|
||||
scheduler.TaskRunner(ass.update, update_snippet)()
|
||||
self.assertEqual((ass.UPDATE, ass.COMPLETE), ass.state)
|
||||
|
@ -791,7 +789,6 @@ class AllocTest(common.HeatTestCase):
|
|||
server = self.fc.servers.list()[0]
|
||||
self._mock_server_get(mock_server=server, multiple=True)
|
||||
self.mock_create_floatingip()
|
||||
self.mock_show_floatingip('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
|
||||
self.m.ReplayAll()
|
||||
|
||||
t = template_format.parse(eip_template_ipassoc)
|
||||
|
@ -804,7 +801,7 @@ class AllocTest(common.HeatTestCase):
|
|||
update_eip = '11.0.0.2'
|
||||
props['EIP'] = update_eip
|
||||
update_snippet = rsrc_defn.ResourceDefinition(ass.name, ass.type(),
|
||||
stack.t.parse(stack,
|
||||
stack.t.parse(stack.defn,
|
||||
props))
|
||||
scheduler.TaskRunner(ass.update, update_snippet)()
|
||||
self.assertEqual((ass.UPDATE, ass.COMPLETE), ass.state)
|
||||
|
@ -815,7 +812,6 @@ class AllocTest(common.HeatTestCase):
|
|||
server = self.fc.servers.list()[0]
|
||||
self._mock_server_get(mock_server=server, multiple=True)
|
||||
self.mock_create_floatingip()
|
||||
self.mock_show_floatingip('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
|
||||
|
||||
self.mock_list_instance_ports('WebServer')
|
||||
self.mock_show_network()
|
||||
|
@ -838,7 +834,7 @@ class AllocTest(common.HeatTestCase):
|
|||
props['AllocationId'] = update_allocationId
|
||||
props.pop('EIP')
|
||||
update_snippet = rsrc_defn.ResourceDefinition(ass.name, ass.type(),
|
||||
stack.t.parse(stack,
|
||||
stack.t.parse(stack.defn,
|
||||
props))
|
||||
scheduler.TaskRunner(ass.update, update_snippet)()
|
||||
self.assertEqual((ass.UPDATE, ass.COMPLETE), ass.state)
|
||||
|
@ -850,7 +846,7 @@ class AllocTest(common.HeatTestCase):
|
|||
props['EIP'] = update_eip
|
||||
props.pop('AllocationId')
|
||||
update_snippet = rsrc_defn.ResourceDefinition(ass.name, ass.type(),
|
||||
stack.t.parse(stack,
|
||||
stack.t.parse(stack.defn,
|
||||
props))
|
||||
scheduler.TaskRunner(ass.update, update_snippet)()
|
||||
self.assertEqual((ass.UPDATE, ass.COMPLETE), ass.state)
|
||||
|
@ -944,7 +940,7 @@ class AllocTest(common.HeatTestCase):
|
|||
props['NetworkInterfaceId'] = update_networkInterfaceId
|
||||
|
||||
update_snippet = rsrc_defn.ResourceDefinition(ass.name, ass.type(),
|
||||
stack.t.parse(stack,
|
||||
stack.t.parse(stack.defn,
|
||||
props))
|
||||
scheduler.TaskRunner(ass.update, update_snippet)()
|
||||
self.assertEqual((ass.UPDATE, ass.COMPLETE), ass.state)
|
||||
|
@ -956,7 +952,7 @@ class AllocTest(common.HeatTestCase):
|
|||
props['InstanceId'] = instance_id
|
||||
|
||||
update_snippet = rsrc_defn.ResourceDefinition(ass.name, ass.type(),
|
||||
stack.t.parse(stack,
|
||||
stack.t.parse(stack.defn,
|
||||
props))
|
||||
scheduler.TaskRunner(ass.update, update_snippet)()
|
||||
self.assertEqual((ass.UPDATE, ass.COMPLETE), ass.state)
|
||||
|
@ -992,5 +988,5 @@ class AllocTest(common.HeatTestCase):
|
|||
'reference_id': 'convg_xyz'
|
||||
})}
|
||||
stack = utils.parse_stack(t, cache_data=cache_data)
|
||||
rsrc = stack['IPAssoc']
|
||||
rsrc = stack.defn['IPAssoc']
|
||||
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
||||
|
|
|
@ -169,7 +169,7 @@ class LoadBalancerTest(common.HeatTestCase):
|
|||
self.stack = utils.parse_stack(template, cache_data=cache_data)
|
||||
|
||||
resource_name = 'LoadBalancer'
|
||||
lb_defn = self.stack.t.resource_definitions(self.stack)[resource_name]
|
||||
lb_defn = self.stack.defn.resource_definition(resource_name)
|
||||
return lb.LoadBalancer(resource_name, lb_defn, self.stack)
|
||||
|
||||
def test_loadbalancer_refid(self):
|
||||
|
@ -185,7 +185,8 @@ class LoadBalancerTest(common.HeatTestCase):
|
|||
'reference_id': 'LoadBalancer_convg_mock'
|
||||
})}
|
||||
rsrc = self.setup_loadbalancer(cache_data=cache_data)
|
||||
self.assertEqual('LoadBalancer_convg_mock', rsrc.FnGetRefId())
|
||||
self.assertEqual('LoadBalancer_convg_mock',
|
||||
self.stack.defn[rsrc.name].FnGetRefId())
|
||||
|
||||
def test_loadbalancer_attr_dnsname(self):
|
||||
rsrc = self.setup_loadbalancer()
|
||||
|
|
|
@ -292,7 +292,7 @@ class UserTest(common.HeatTestCase):
|
|||
'reference_id': 'convg_xyz'
|
||||
})}
|
||||
stack = utils.parse_stack(t, cache_data=cache_data)
|
||||
rsrc = stack['CfnUser']
|
||||
rsrc = stack.defn['CfnUser']
|
||||
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
||||
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@ class WaitConditionTest(common.HeatTestCase):
|
|||
'reference_id': 'http://convg_signed_url'
|
||||
})})
|
||||
|
||||
rsrc = stack['WaitHandle']
|
||||
rsrc = stack.defn['WaitHandle']
|
||||
self.assertEqual('http://convg_signed_url', rsrc.FnGetRefId())
|
||||
|
||||
def test_validate_handle_url_bad_stackid(self):
|
||||
|
|
|
@ -73,7 +73,7 @@ class BaseVolumeTest(common.HeatTestCase):
|
|||
data['Properties']['AvailabilityZone'] = 'nova'
|
||||
Volume = aws_vol.Volume
|
||||
vol = Volume(resource_name,
|
||||
stack.t.resource_definitions(stack)[resource_name],
|
||||
stack.defn.resource_definition(resource_name),
|
||||
stack)
|
||||
return vol
|
||||
|
||||
|
@ -94,9 +94,8 @@ class BaseVolumeTest(common.HeatTestCase):
|
|||
Attachment = os_vol.CinderVolumeAttachment
|
||||
else:
|
||||
Attachment = aws_vol.VolumeAttachment
|
||||
resource_defns = stack.t.resource_definitions(stack)
|
||||
rsrc = Attachment(resource_name,
|
||||
resource_defns[resource_name],
|
||||
stack.defn.resource_definition(resource_name),
|
||||
stack)
|
||||
self.assertIsNone(rsrc.validate())
|
||||
scheduler.TaskRunner(rsrc.create)()
|
||||
|
|
|
@ -25,7 +25,7 @@ from heat.engine import resource
|
|||
from heat.engine.resources.openstack.heat import instance_group as instgrp
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import scheduler
|
||||
from heat.engine import stack as parser
|
||||
from heat.engine import stk_defn
|
||||
from heat.tests.autoscaling import inline_templates
|
||||
from heat.tests import common
|
||||
from heat.tests import utils
|
||||
|
@ -320,7 +320,7 @@ class LoadbalancerReloadTest(common.HeatTestCase):
|
|||
properties = t['Resources']['ElasticLoadBalancer']['Properties']
|
||||
properties['AvailabilityZones'] = {'Fn::GetAZs': ''}
|
||||
|
||||
self.patchobject(parser.Stack, 'get_availability_zones',
|
||||
self.patchobject(stk_defn.StackDefinition, 'get_availability_zones',
|
||||
return_value=['abc', 'xyz'])
|
||||
|
||||
mock_members = self.patchobject(grouputils, 'get_member_refids')
|
||||
|
|
|
@ -171,7 +171,7 @@ Resources:
|
|||
'reference_id': 'xyz'
|
||||
})}
|
||||
stack = utils.parse_stack(t, cache_data=cache_data)
|
||||
rsrc = stack['secret1']
|
||||
rsrc = stack.defn['secret1']
|
||||
self.assertEqual('xyz', rsrc.FnGetRefId())
|
||||
|
||||
def test_invalid_length(self):
|
||||
|
|
|
@ -677,7 +677,7 @@ class RemoteStackTest(tests_common.HeatTestCase):
|
|||
'reference_id': 'convg_xyz'
|
||||
})}
|
||||
stack = utils.parse_stack(t, cache_data=cache_data)
|
||||
rsrc = stack['remote_stack']
|
||||
rsrc = stack.defn['remote_stack']
|
||||
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
||||
|
||||
def test_update_in_check_failed_state(self):
|
||||
|
|
|
@ -228,5 +228,5 @@ class ResourceChainTest(common.HeatTestCase):
|
|||
'attrs': {'refs': ['rsrc1', 'rsrc2']}
|
||||
})}
|
||||
stack = utils.parse_stack(TEMPLATE, cache_data=cache_data)
|
||||
rsrc = stack['test-chain']
|
||||
self.assertEqual(['rsrc1', 'rsrc2'], rsrc.FnGetAtt(rsrc.REFS))
|
||||
rsrc = stack.defn['test-chain']
|
||||
self.assertEqual(['rsrc1', 'rsrc2'], rsrc.FnGetAtt('refs'))
|
||||
|
|
|
@ -884,8 +884,8 @@ class ResourceGroupAttrTest(common.HeatTestCase):
|
|||
'attrs': {'refs': ['rsrc1', 'rsrc2']}
|
||||
})}
|
||||
stack = utils.parse_stack(template, cache_data=cache_data)
|
||||
rsrc = stack['group1']
|
||||
self.assertEqual(['rsrc1', 'rsrc2'], rsrc.FnGetAtt(rsrc.REFS))
|
||||
rsrc = stack.defn['group1']
|
||||
self.assertEqual(['rsrc1', 'rsrc2'], rsrc.FnGetAtt('refs'))
|
||||
|
||||
def test_get_attribute_blacklist(self):
|
||||
resg = self._create_dummy_stack()
|
||||
|
|
|
@ -1104,7 +1104,8 @@ class SoftwareDeploymentTest(common.HeatTestCase):
|
|||
'attrs': {'foo': 'bar'}
|
||||
})}
|
||||
self._create_stack(self.template, cache_data=cache_data)
|
||||
self.assertEqual('bar', self.deployment.FnGetAtt('foo'))
|
||||
self.assertEqual('bar',
|
||||
self.stack.defn[self.deployment.name].FnGetAtt('foo'))
|
||||
|
||||
def test_fn_get_att_error(self):
|
||||
self._create_stack(self.template)
|
||||
|
|
|
@ -291,7 +291,7 @@ class SwiftSignalHandleTest(common.HeatTestCase):
|
|||
})
|
||||
}
|
||||
st = create_stack(swiftsignalhandle_template, cache_data=cache_data)
|
||||
rsrc = st['test_wait_condition_handle']
|
||||
rsrc = st.defn['test_wait_condition_handle']
|
||||
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
||||
|
||||
|
||||
|
|
|
@ -821,7 +821,7 @@ class TestMistralWorkflow(common.HeatTestCase):
|
|||
|
||||
return [FakeWorkflow('create_vm')]
|
||||
|
||||
def test_mistal_workflow_refid(self):
|
||||
def test_mistral_workflow_refid(self):
|
||||
tmpl = template_format.parse(workflow_template)
|
||||
stack = utils.parse_stack(tmpl, stack_name='test')
|
||||
rsrc = stack['workflow']
|
||||
|
@ -830,7 +830,7 @@ class TestMistralWorkflow(common.HeatTestCase):
|
|||
rsrc.action = 'CREATE'
|
||||
self.assertEqual('test-workflow-owevpzgiqw66', rsrc.FnGetRefId())
|
||||
|
||||
def test_mistal_workflow_refid_convergence_cache_data(self):
|
||||
def test_mistral_workflow_refid_convergence_cache_data(self):
|
||||
tmpl = template_format.parse(workflow_template)
|
||||
cache_data = {'workflow': node_data.NodeData.from_dict({
|
||||
'uuid': mock.ANY,
|
||||
|
@ -841,7 +841,7 @@ class TestMistralWorkflow(common.HeatTestCase):
|
|||
})}
|
||||
stack = utils.parse_stack(tmpl, stack_name='test',
|
||||
cache_data=cache_data)
|
||||
rsrc = stack['workflow']
|
||||
rsrc = stack.defn['workflow']
|
||||
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
||||
|
||||
def test_policies_translation_successful(self):
|
||||
|
|
|
@ -296,7 +296,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
|
|||
'status': 'COMPLETE',
|
||||
'reference_id': 'abc'})})
|
||||
|
||||
rsrc = stack['floating_ip']
|
||||
rsrc = stack.defn['floating_ip']
|
||||
self.assertEqual('abc', rsrc.FnGetRefId())
|
||||
|
||||
def test_floatip_association_port(self):
|
||||
|
@ -449,7 +449,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
|
|||
update_port_id = '2146dfbf-ba77-4083-8e86-d052f671ece5'
|
||||
props['port_id'] = update_port_id
|
||||
update_snippet = rsrc_defn.ResourceDefinition(fipa.name, fipa.type(),
|
||||
stack.t.parse(stack,
|
||||
stack.t.parse(stack.defn,
|
||||
props))
|
||||
|
||||
scheduler.TaskRunner(fipa.update, update_snippet)()
|
||||
|
@ -708,7 +708,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
|
|||
update_port_id = '2146dfbf-ba77-4083-8e86-d052f671ece5'
|
||||
props['port_id'] = update_port_id
|
||||
update_snippet = rsrc_defn.ResourceDefinition(fip.name, fip.type(),
|
||||
stack.t.parse(stack,
|
||||
stack.t.parse(stack.defn,
|
||||
props))
|
||||
scheduler.TaskRunner(fip.update, update_snippet)()
|
||||
self.assertEqual((fip.UPDATE, fip.COMPLETE), fip.state)
|
||||
|
@ -718,7 +718,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
|
|||
props = copy.deepcopy(fip.properties.data)
|
||||
del(props['port_id'])
|
||||
update_snippet = rsrc_defn.ResourceDefinition(fip.name, fip.type(),
|
||||
stack.t.parse(stack,
|
||||
stack.t.parse(stack.defn,
|
||||
props))
|
||||
scheduler.TaskRunner(fip.update, update_snippet)()
|
||||
self.assertEqual((fip.UPDATE, fip.COMPLETE), fip.state)
|
||||
|
|
|
@ -22,10 +22,12 @@ from heat.common import template_format
|
|||
from heat.engine.clients.os import neutron
|
||||
from heat.engine.clients.os import openstacksdk
|
||||
from heat.engine.hot import functions as hot_funcs
|
||||
from heat.engine import node_data
|
||||
from heat.engine import resource
|
||||
from heat.engine.resources.openstack.neutron import subnet
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import scheduler
|
||||
from heat.engine import stk_defn
|
||||
from heat.tests import common
|
||||
from heat.tests import utils
|
||||
|
||||
|
@ -682,9 +684,10 @@ class NeutronSubnetTest(common.HeatTestCase):
|
|||
"""
|
||||
t = template_format.parse(template)
|
||||
stack = utils.parse_stack(t)
|
||||
self.patchobject(stack['net'], 'FnGetRefId',
|
||||
return_value='fc68ea2c-b60b-4b4f-bd82-94ec81110766')
|
||||
rsrc = stack['subnet']
|
||||
nd = {'reference_id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'}
|
||||
stk_defn.update_resource_data(stack.defn, 'net',
|
||||
node_data.NodeData.from_dict(nd))
|
||||
self.create_mock.return_value = {
|
||||
"subnet": {
|
||||
"id": "91e47a57-7508-46fe-afc9-fc454e8580e1",
|
||||
|
@ -696,6 +699,7 @@ class NeutronSubnetTest(common.HeatTestCase):
|
|||
}
|
||||
stack.create()
|
||||
|
||||
self.assertEqual(hot_funcs.GetResource(stack, 'get_resource', 'net'),
|
||||
self.assertEqual(hot_funcs.GetResource(stack.defn, 'get_resource',
|
||||
'net'),
|
||||
rsrc.properties.get('network'))
|
||||
self.assertIsNone(rsrc.properties.get('network_id'))
|
||||
|
|
|
@ -369,7 +369,7 @@ class NeutronTrunkTest(common.HeatTestCase):
|
|||
t = template_format.parse(update_template)
|
||||
stack = utils.parse_stack(t)
|
||||
|
||||
rsrc_defn = stack.t.resource_definitions(stack)['trunk']
|
||||
rsrc_defn = stack.defn.resource_definition('trunk')
|
||||
rsrc = trunk.Trunk('trunk', rsrc_defn, stack)
|
||||
scheduler.TaskRunner(rsrc.create)()
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
@ -390,7 +390,7 @@ class NeutronTrunkTest(common.HeatTestCase):
|
|||
t = template_format.parse(update_template)
|
||||
stack = utils.parse_stack(t)
|
||||
|
||||
rsrc_defn = stack.t.resource_definitions(stack)['trunk']
|
||||
rsrc_defn = stack.defn.resource_definition('trunk')
|
||||
rsrc = trunk.Trunk('trunk', rsrc_defn, stack)
|
||||
scheduler.TaskRunner(rsrc.create)()
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
@ -411,7 +411,7 @@ class NeutronTrunkTest(common.HeatTestCase):
|
|||
t = template_format.parse(update_template)
|
||||
stack = utils.parse_stack(t)
|
||||
|
||||
rsrc_defn = stack.t.resource_definitions(stack)['trunk']
|
||||
rsrc_defn = stack.defn.resource_definition('trunk')
|
||||
rsrc = trunk.Trunk('trunk', rsrc_defn, stack)
|
||||
scheduler.TaskRunner(rsrc.create)()
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
@ -440,7 +440,7 @@ class NeutronTrunkTest(common.HeatTestCase):
|
|||
t = template_format.parse(update_template)
|
||||
stack = utils.parse_stack(t)
|
||||
|
||||
rsrc_defn = stack.t.resource_definitions(stack)['trunk']
|
||||
rsrc_defn = stack.defn.resource_definition('trunk')
|
||||
rsrc = trunk.Trunk('trunk', rsrc_defn, stack)
|
||||
scheduler.TaskRunner(rsrc.create)()
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
|
|
@ -357,5 +357,5 @@ class NovaFloatingIPTest(common.HeatTestCase):
|
|||
'reference_id': 'convg_xyz'
|
||||
})}
|
||||
stack = utils.parse_stack(t, cache_data=cache_data)
|
||||
rsrc = stack['MyFloatingIPAssociation']
|
||||
rsrc = stack.defn['MyFloatingIPAssociation']
|
||||
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
||||
|
|
|
@ -286,5 +286,5 @@ class NovaKeyPairTest(common.HeatTestCase):
|
|||
'reference_id': 'convg_xyz'
|
||||
}}
|
||||
stack = utils.parse_stack(self.kp_template, cache_data=cache_data)
|
||||
rsrc = stack['kp']
|
||||
rsrc = stack.defn['kp']
|
||||
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
||||
|
|
|
@ -472,7 +472,7 @@ class SwiftTest(common.HeatTestCase):
|
|||
'reference_id': 'xyz_convg'
|
||||
})}
|
||||
stack = utils.parse_stack(self.t, cache_data=cache_data)
|
||||
rsrc = stack['SwiftContainer']
|
||||
rsrc = stack.defn['SwiftContainer']
|
||||
self.assertEqual('xyz_convg', rsrc.FnGetRefId())
|
||||
|
||||
@mock.patch('swiftclient.client.Connection.head_account')
|
||||
|
|
|
@ -24,6 +24,7 @@ from heat.engine import function
|
|||
from heat.engine import resource
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import stack
|
||||
from heat.engine import stk_defn
|
||||
from heat.engine import template
|
||||
from heat.tests import common
|
||||
from heat.tests import utils
|
||||
|
@ -241,25 +242,38 @@ class ValidateGetAttTest(common.HeatTestCase):
|
|||
env.load({u'resource_registry':
|
||||
{u'OS::Test::FakeResource': u'OverwrittenFnGetAttType'}})
|
||||
|
||||
tmpl = template.Template({"HeatTemplateFormatVersion": "2012-12-12",
|
||||
"Resources": {
|
||||
"test_rsrc": {
|
||||
"Type": "OS::Test::GenericResource"
|
||||
},
|
||||
"get_att_rsrc": {
|
||||
"Type": "OS::Heat::Value",
|
||||
"Properties": {
|
||||
"value": {
|
||||
"Fn::GetAtt": ["test_rsrc",
|
||||
"Foo"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
env=env)
|
||||
self.stack = stack.Stack(
|
||||
utils.dummy_context(), 'test_stack',
|
||||
template.Template({"HeatTemplateFormatVersion": "2012-12-12"},
|
||||
env=env),
|
||||
tmpl,
|
||||
stack_id=str(uuid.uuid4()))
|
||||
res_defn = rsrc_defn.ResourceDefinition('test_rsrc',
|
||||
'OS::Test::GenericResource')
|
||||
self.rsrc = resource.Resource('test_rsrc', res_defn, self.stack)
|
||||
self.stack.add_resource(self.rsrc)
|
||||
self.rsrc = self.stack['test_rsrc']
|
||||
self.stack.validate()
|
||||
|
||||
def test_resource_is_appear_in_stack(self):
|
||||
func = functions.GetAtt(self.stack, 'Fn::GetAtt',
|
||||
func = functions.GetAtt(self.stack.defn, 'Fn::GetAtt',
|
||||
[self.rsrc.name, 'Foo'])
|
||||
self.assertIsNone(func.validate())
|
||||
|
||||
def test_resource_is_not_appear_in_stack(self):
|
||||
self.stack.remove_resource(self.rsrc.name)
|
||||
|
||||
func = functions.GetAtt(self.stack, 'Fn::GetAtt',
|
||||
func = functions.GetAtt(self.stack.defn, 'Fn::GetAtt',
|
||||
[self.rsrc.name, 'Foo'])
|
||||
ex = self.assertRaises(exception.InvalidTemplateReference,
|
||||
func.validate)
|
||||
|
@ -267,7 +281,15 @@ class ValidateGetAttTest(common.HeatTestCase):
|
|||
'is incorrect.', six.text_type(ex))
|
||||
|
||||
def test_resource_no_attribute_with_default_fn_get_att(self):
|
||||
func = functions.GetAtt(self.stack, 'Fn::GetAtt',
|
||||
res_defn = rsrc_defn.ResourceDefinition('test_rsrc',
|
||||
'ResWithStringPropAndAttr')
|
||||
self.rsrc = resource.Resource('test_rsrc', res_defn, self.stack)
|
||||
self.stack.add_resource(self.rsrc)
|
||||
stk_defn.update_resource_data(self.stack.defn, self.rsrc.name,
|
||||
self.rsrc.node_data())
|
||||
self.stack.validate()
|
||||
|
||||
func = functions.GetAtt(self.stack.defn, 'Fn::GetAtt',
|
||||
[self.rsrc.name, 'Bar'])
|
||||
ex = self.assertRaises(exception.InvalidTemplateAttribute,
|
||||
func.validate)
|
||||
|
@ -278,16 +300,19 @@ class ValidateGetAttTest(common.HeatTestCase):
|
|||
res_defn = rsrc_defn.ResourceDefinition('test_rsrc',
|
||||
'OS::Test::FakeResource')
|
||||
self.rsrc = resource.Resource('test_rsrc', res_defn, self.stack)
|
||||
self.stack.add_resource(self.rsrc)
|
||||
self.rsrc.attributes_schema = {}
|
||||
self.stack.add_resource(self.rsrc)
|
||||
stk_defn.update_resource_data(self.stack.defn, self.rsrc.name,
|
||||
self.rsrc.node_data())
|
||||
self.stack.validate()
|
||||
|
||||
func = functions.GetAtt(self.stack, 'Fn::GetAtt',
|
||||
func = functions.GetAtt(self.stack.defn, 'Fn::GetAtt',
|
||||
[self.rsrc.name, 'Foo'])
|
||||
self.assertIsNone(func.validate())
|
||||
|
||||
def test_get_attr_without_attribute_name(self):
|
||||
ex = self.assertRaises(ValueError, functions.GetAtt,
|
||||
self.stack, 'Fn::GetAtt', [self.rsrc.name])
|
||||
self.stack.defn, 'Fn::GetAtt', [self.rsrc.name])
|
||||
self.assertEqual('Arguments to "Fn::GetAtt" must be '
|
||||
'of the form [resource_name, attribute]',
|
||||
six.text_type(ex))
|
||||
|
|
|
@ -30,6 +30,7 @@ from heat.engine import resource
|
|||
from heat.engine import resources
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import stack as parser
|
||||
from heat.engine import stk_defn
|
||||
from heat.engine import template
|
||||
from heat.tests import common
|
||||
from heat.tests import generic_resource as generic_rsrc
|
||||
|
@ -162,11 +163,12 @@ class HOTemplateTest(common.HeatTestCase):
|
|||
|
||||
@staticmethod
|
||||
def resolve(snippet, template, stack=None):
|
||||
return function.resolve(template.parse(stack, snippet))
|
||||
return function.resolve(template.parse(stack and stack.defn, snippet))
|
||||
|
||||
@staticmethod
|
||||
def resolve_condition(snippet, template, stack=None):
|
||||
return function.resolve(template.parse_condition(stack, snippet))
|
||||
return function.resolve(template.parse_condition(stack and stack.defn,
|
||||
snippet))
|
||||
|
||||
def test_defaults(self):
|
||||
"""Test default content behavior of HOT template."""
|
||||
|
@ -1913,7 +1915,7 @@ conditions:
|
|||
self.assertRaisesRegex(exception.StackValidationFailed,
|
||||
regxp,
|
||||
function.validate,
|
||||
stack.t.parse(stack, snippet))
|
||||
stack.t.parse(stack.defn, snippet))
|
||||
|
||||
def test_add_resource(self):
|
||||
hot_tpl = template_format.parse('''
|
||||
|
@ -2349,7 +2351,7 @@ class HotStackTest(common.HeatTestCase):
|
|||
self.ctx = utils.dummy_context()
|
||||
|
||||
def resolve(self, snippet):
|
||||
return function.resolve(self.stack.t.parse(self.stack, snippet))
|
||||
return function.resolve(self.stack.t.parse(self.stack.defn, snippet))
|
||||
|
||||
def test_repeat_get_attr(self):
|
||||
"""Test repeat function with get_attr function as an argument."""
|
||||
|
@ -2358,7 +2360,7 @@ class HotStackTest(common.HeatTestCase):
|
|||
|
||||
snippet = {'repeat': {'template': 'this is %var%',
|
||||
'for_each': {'%var%': {'get_attr': ['resource1', 'list']}}}}
|
||||
repeat = self.stack.t.parse(self.stack, snippet)
|
||||
repeat = self.stack.t.parse(self.stack.defn, snippet)
|
||||
|
||||
self.stack.store()
|
||||
with mock.patch.object(rsrc_defn.ResourceDefinition,
|
||||
|
@ -2724,7 +2726,8 @@ class StackAttributesTest(common.HeatTestCase):
|
|||
template.Template(self.hot_tpl))
|
||||
self.stack.store()
|
||||
|
||||
parsed = self.stack.t.parse(self.stack, self.snippet)
|
||||
parsed = self.stack.t.parse(self.stack.defn, self.snippet)
|
||||
dep_attrs = list(function.dep_attrs(parsed, self.resource_name))
|
||||
|
||||
self.stack.create()
|
||||
self.assertEqual((parser.Stack.CREATE, parser.Stack.COMPLETE),
|
||||
|
@ -2748,177 +2751,16 @@ class StackAttributesTest(common.HeatTestCase):
|
|||
(rsrc.ADOPT, rsrc.COMPLETE)):
|
||||
rsrc.state_set(action, status)
|
||||
|
||||
with mock.patch.object(rsrc_defn.ResourceDefinition,
|
||||
'dep_attrs') as mock_da:
|
||||
mock_da.return_value = dep_attrs
|
||||
node_data = rsrc.node_data()
|
||||
stk_defn.update_resource_data(self.stack.defn, rsrc.name,
|
||||
node_data)
|
||||
|
||||
self.assertEqual(self.expected, function.resolve(parsed))
|
||||
|
||||
|
||||
class StackGetAttributesTestConvergence(common.HeatTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(StackGetAttributesTestConvergence, self).setUp()
|
||||
|
||||
self.ctx = utils.dummy_context()
|
||||
|
||||
self.m.ReplayAll()
|
||||
|
||||
scenarios = [
|
||||
# for hot template 2013-05-23, get_attr: hot_funcs.GetAttThenSelect
|
||||
('get_flat_attr',
|
||||
dict(hot_tpl=hot_tpl_generic_resource,
|
||||
snippet={'Value': {'get_attr': ['resource1', 'foo']}},
|
||||
resource_name='resource1',
|
||||
expected={'Value': 'resource1'})),
|
||||
('get_list_attr',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs,
|
||||
snippet={'Value': {'get_attr': ['resource1', 'list', 0]}},
|
||||
resource_name='resource1',
|
||||
expected={
|
||||
'Value':
|
||||
generic_rsrc.ResourceWithComplexAttributes.list[0]})),
|
||||
('get_flat_dict_attr',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs,
|
||||
snippet={'Value': {'get_attr': ['resource1',
|
||||
'flat_dict',
|
||||
'key2']}},
|
||||
resource_name='resource1',
|
||||
expected={
|
||||
'Value':
|
||||
generic_rsrc.ResourceWithComplexAttributes.
|
||||
flat_dict['key2']})),
|
||||
('get_nested_attr_list',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs,
|
||||
snippet={'Value': {'get_attr': ['resource1',
|
||||
'nested_dict',
|
||||
'list',
|
||||
0]}},
|
||||
resource_name='resource1',
|
||||
expected={
|
||||
'Value':
|
||||
generic_rsrc.ResourceWithComplexAttributes.
|
||||
nested_dict['list'][0]})),
|
||||
('get_nested_attr_dict',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs,
|
||||
snippet={'Value': {'get_attr': ['resource1',
|
||||
'nested_dict',
|
||||
'dict',
|
||||
'a']}},
|
||||
resource_name='resource1',
|
||||
expected={
|
||||
'Value':
|
||||
generic_rsrc.ResourceWithComplexAttributes.
|
||||
nested_dict['dict']['a']})),
|
||||
('get_attr_none',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs,
|
||||
snippet={'Value': {'get_attr': ['resource1',
|
||||
'none',
|
||||
'who_cares']}},
|
||||
resource_name='resource1',
|
||||
expected={'Value': None})),
|
||||
# for hot template version 2014-10-16 and 2015-04-30,
|
||||
# get_attr: hot_funcs.GetAtt
|
||||
('get_flat_attr',
|
||||
dict(hot_tpl=hot_tpl_generic_resource_20141016,
|
||||
snippet={'Value': {'get_attr': ['resource1', 'foo']}},
|
||||
resource_name='resource1',
|
||||
expected={'Value': 'resource1'})),
|
||||
('get_list_attr',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs_20141016,
|
||||
snippet={'Value': {'get_attr': ['resource1', 'list', 0]}},
|
||||
resource_name='resource1',
|
||||
expected={
|
||||
'Value':
|
||||
generic_rsrc.ResourceWithComplexAttributes.list[0]})),
|
||||
('get_flat_dict_attr',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs_20141016,
|
||||
snippet={'Value': {'get_attr': ['resource1',
|
||||
'flat_dict',
|
||||
'key2']}},
|
||||
resource_name='resource1',
|
||||
expected={
|
||||
'Value':
|
||||
generic_rsrc.ResourceWithComplexAttributes.
|
||||
flat_dict['key2']})),
|
||||
('get_nested_attr_list',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs_20141016,
|
||||
snippet={'Value': {'get_attr': ['resource1',
|
||||
'nested_dict',
|
||||
'list',
|
||||
0]}},
|
||||
resource_name='resource1',
|
||||
expected={
|
||||
'Value':
|
||||
generic_rsrc.ResourceWithComplexAttributes.
|
||||
nested_dict['list'][0]})),
|
||||
('get_nested_attr_dict',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs_20141016,
|
||||
snippet={'Value': {'get_attr': ['resource1',
|
||||
'nested_dict',
|
||||
'dict',
|
||||
'a']}},
|
||||
resource_name='resource1',
|
||||
expected={
|
||||
'Value':
|
||||
generic_rsrc.ResourceWithComplexAttributes.
|
||||
nested_dict['dict']['a']})),
|
||||
('get_attr_none',
|
||||
dict(hot_tpl=hot_tpl_complex_attrs_20141016,
|
||||
snippet={'Value': {'get_attr': ['resource1',
|
||||
'none',
|
||||
'who_cares']}},
|
||||
resource_name='resource1',
|
||||
expected={'Value': None}))
|
||||
]
|
||||
|
||||
def _prepare_cache_data(self, rsrc):
|
||||
dep_attrs = function.dep_attrs(
|
||||
self.stack.t.parse(self.stack, self.snippet),
|
||||
self.resource_name)
|
||||
with mock.patch.object(rsrc_defn.ResourceDefinition,
|
||||
'dep_attrs') as mock_da:
|
||||
mock_da.return_value = dep_attrs
|
||||
rsrc_data = rsrc.node_data()
|
||||
# store as cache data
|
||||
self.stack.cache_data = {
|
||||
rsrc.name: rsrc_data
|
||||
}
|
||||
|
||||
def test_get_attr_convergence(self):
|
||||
"""Test resolution of get_attr occurrences with convergence."""
|
||||
|
||||
self.stack = parser.Stack(self.ctx, 'test_get_attr',
|
||||
template.Template(self.hot_tpl))
|
||||
self.stack.store()
|
||||
self.stack.create()
|
||||
self.assertEqual((parser.Stack.CREATE, parser.Stack.COMPLETE),
|
||||
self.stack.state)
|
||||
rsrc = self.stack[self.resource_name]
|
||||
self._prepare_cache_data(rsrc)
|
||||
|
||||
with mock.patch.object(resource.Resource, 'get_attribute') as mock_ga:
|
||||
for action, status in (
|
||||
(rsrc.CREATE, rsrc.IN_PROGRESS),
|
||||
(rsrc.CREATE, rsrc.COMPLETE),
|
||||
(rsrc.RESUME, rsrc.IN_PROGRESS),
|
||||
(rsrc.RESUME, rsrc.COMPLETE),
|
||||
(rsrc.SUSPEND, rsrc.IN_PROGRESS),
|
||||
(rsrc.SUSPEND, rsrc.COMPLETE),
|
||||
(rsrc.UPDATE, rsrc.IN_PROGRESS),
|
||||
(rsrc.UPDATE, rsrc.COMPLETE),
|
||||
(rsrc.SNAPSHOT, rsrc.IN_PROGRESS),
|
||||
(rsrc.SNAPSHOT, rsrc.COMPLETE),
|
||||
(rsrc.CHECK, rsrc.IN_PROGRESS),
|
||||
(rsrc.CHECK, rsrc.COMPLETE),
|
||||
(rsrc.ADOPT, rsrc.IN_PROGRESS),
|
||||
(rsrc.ADOPT, rsrc.COMPLETE)):
|
||||
rsrc.state_set(action, status)
|
||||
|
||||
resolved = function.resolve(self.stack.t.parse(self.stack,
|
||||
self.snippet))
|
||||
self.assertEqual(self.expected, resolved)
|
||||
# get_attribute should never be called, everything
|
||||
# should be resolved from cache data
|
||||
self.assertFalse(mock_ga.called)
|
||||
|
||||
|
||||
class StackGetAttrValidationTest(common.HeatTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -3067,7 +2909,8 @@ class StackParametersTest(common.HeatTestCase):
|
|||
stack_id='1ba8c334-2297-4312-8c7c-43763a988ced',
|
||||
tenant_id='9913ef0a-b8be-4b33-b574-9061441bd373')
|
||||
self.assertEqual(self.expected,
|
||||
function.resolve(tmpl.parse(stack, self.snippet)))
|
||||
function.resolve(tmpl.parse(stack.defn,
|
||||
self.snippet)))
|
||||
|
||||
|
||||
class HOTParamValidatorTest(common.HeatTestCase):
|
||||
|
@ -3598,13 +3441,20 @@ class TestGetAttAllAttributes(common.HeatTestCase):
|
|||
]
|
||||
|
||||
@staticmethod
|
||||
def resolve(snippet, template, stack=None):
|
||||
return function.resolve(template.parse(stack, snippet))
|
||||
def resolve(snippet, template, stack):
|
||||
return function.resolve(template.parse(stack.defn, snippet))
|
||||
|
||||
def test_get_attr_all_attributes(self):
|
||||
tmpl = template.Template(self.hot_tpl)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_get_attr', tmpl)
|
||||
stack.store()
|
||||
|
||||
if self.raises is None:
|
||||
dep_attrs = list(function.dep_attrs(tmpl.parse(stack.defn,
|
||||
self.snippet),
|
||||
'resource1'))
|
||||
else:
|
||||
dep_attrs = []
|
||||
stack.create()
|
||||