From 764b8fb25132ac60c7760f134b78d600269ff516 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Wed, 19 Jul 2017 17:35:40 -0400 Subject: [PATCH] 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-definition --- heat/engine/function.py | 3 +- heat/engine/hot/functions.py | 4 +- heat/engine/resource.py | 6 +- .../openstack/heat/instance_group.py | 2 +- .../openstack/heat/resource_group.py | 3 +- heat/engine/stack.py | 85 ++++--- heat/engine/update.py | 2 +- .../autoscaling/test_heat_scaling_policy.py | 2 +- heat/tests/autoscaling/test_launch_config.py | 2 +- heat/tests/autoscaling/test_scaling_policy.py | 2 +- heat/tests/aws/test_eip.py | 28 +-- heat/tests/aws/test_loadbalancer.py | 5 +- heat/tests/aws/test_user.py | 2 +- heat/tests/aws/test_waitcondition.py | 2 +- .../openstack/cinder/test_volume_utils.py | 5 +- .../openstack/heat/test_instance_group.py | 4 +- .../openstack/heat/test_random_string.py | 2 +- .../tests/openstack/heat/test_remote_stack.py | 2 +- .../openstack/heat/test_resource_chain.py | 4 +- .../openstack/heat/test_resource_group.py | 4 +- .../heat/test_software_deployment.py | 3 +- heat/tests/openstack/heat/test_swiftsignal.py | 2 +- heat/tests/openstack/mistral/test_workflow.py | 6 +- .../neutron/test_neutron_floating_ip.py | 8 +- .../openstack/neutron/test_neutron_subnet.py | 10 +- .../openstack/neutron/test_neutron_trunk.py | 8 +- heat/tests/openstack/nova/test_floatingip.py | 2 +- heat/tests/openstack/nova/test_keypair.py | 2 +- heat/tests/openstack/swift/test_container.py | 2 +- heat/tests/test_function.py | 49 +++- heat/tests/test_hot.py | 210 +++--------------- heat/tests/test_metadata_refresh.py | 9 +- heat/tests/test_nested_stack.py | 2 +- heat/tests/test_resource.py | 45 +--- heat/tests/test_stack.py | 25 ++- heat/tests/test_stack_collect_attributes.py | 5 +- heat/tests/test_stack_resource.py | 4 +- heat/tests/test_stack_update.py | 16 +- heat/tests/test_template.py | 19 +- 39 files changed, 221 insertions(+), 375 deletions(-) diff --git a/heat/engine/function.py b/heat/engine/function.py index 40d7a58c1f..4fb6047bcf 100644 --- a/heat/engine/function.py +++ b/heat/engine/function.py @@ -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): diff --git a/heat/engine/hot/functions.py b/heat/engine/hot/functions.py index 93223be596..aee58c89d7 100644 --- a/heat/engine/hot/functions.py +++ b/heat/engine/hot/functions.py @@ -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) diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 94e46615f7..f457a944fe 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -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( diff --git a/heat/engine/resources/openstack/heat/instance_group.py b/heat/engine/resources/openstack/heat/instance_group.py index 92b10885ab..75f3c53a20 100644 --- a/heat/engine/resources/openstack/heat/instance_group.py +++ b/heat/engine/resources/openstack/heat/instance_group.py @@ -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) diff --git a/heat/engine/resources/openstack/heat/resource_group.py b/heat/engine/resources/openstack/heat/resource_group.py index f6ebd2e762..3351395277 100644 --- a/heat/engine/resources/openstack/heat/resource_group.py +++ b/heat/engine/resources/openstack/heat/resource_group.py @@ -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) diff --git a/heat/engine/stack.py b/heat/engine/stack.py index 9ab6e484cf..341d2ff9f5 100644 --- a/heat/engine/stack.py +++ b/heat/engine/stack.py @@ -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) diff --git a/heat/engine/update.py b/heat/engine/update.py index 727a9c360d..156eeb49af 100644 --- a/heat/engine/update.py +++ b/heat/engine/update.py @@ -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, diff --git a/heat/tests/autoscaling/test_heat_scaling_policy.py b/heat/tests/autoscaling/test_heat_scaling_policy.py index 02171b2a36..65fb7695c9 100644 --- a/heat/tests/autoscaling/test_heat_scaling_policy.py +++ b/heat/tests/autoscaling/test_heat_scaling_policy.py @@ -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()) diff --git a/heat/tests/autoscaling/test_launch_config.py b/heat/tests/autoscaling/test_launch_config.py index 1850b88635..7509564d16 100644 --- a/heat/tests/autoscaling/test_launch_config.py +++ b/heat/tests/autoscaling/test_launch_config.py @@ -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): diff --git a/heat/tests/autoscaling/test_scaling_policy.py b/heat/tests/autoscaling/test_scaling_policy.py index b943db0be3..dff0fe536a 100644 --- a/heat/tests/autoscaling/test_scaling_policy.py +++ b/heat/tests/autoscaling/test_scaling_policy.py @@ -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()) diff --git a/heat/tests/aws/test_eip.py b/heat/tests/aws/test_eip.py index 2943e82f42..abf1186150 100644 --- a/heat/tests/aws/test_eip.py +++ b/heat/tests/aws/test_eip.py @@ -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()) diff --git a/heat/tests/aws/test_loadbalancer.py b/heat/tests/aws/test_loadbalancer.py index 6a2c336dcd..71b7516524 100644 --- a/heat/tests/aws/test_loadbalancer.py +++ b/heat/tests/aws/test_loadbalancer.py @@ -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() diff --git a/heat/tests/aws/test_user.py b/heat/tests/aws/test_user.py index 63102a53de..be8f7d8bdb 100644 --- a/heat/tests/aws/test_user.py +++ b/heat/tests/aws/test_user.py @@ -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()) diff --git a/heat/tests/aws/test_waitcondition.py b/heat/tests/aws/test_waitcondition.py index ba3f68a0c2..7c6406e926 100644 --- a/heat/tests/aws/test_waitcondition.py +++ b/heat/tests/aws/test_waitcondition.py @@ -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): diff --git a/heat/tests/openstack/cinder/test_volume_utils.py b/heat/tests/openstack/cinder/test_volume_utils.py index a3726e2af5..ce4df1b905 100644 --- a/heat/tests/openstack/cinder/test_volume_utils.py +++ b/heat/tests/openstack/cinder/test_volume_utils.py @@ -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)() diff --git a/heat/tests/openstack/heat/test_instance_group.py b/heat/tests/openstack/heat/test_instance_group.py index 72998ab398..fb98e11d81 100644 --- a/heat/tests/openstack/heat/test_instance_group.py +++ b/heat/tests/openstack/heat/test_instance_group.py @@ -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') diff --git a/heat/tests/openstack/heat/test_random_string.py b/heat/tests/openstack/heat/test_random_string.py index 02707874e6..5f35578d67 100644 --- a/heat/tests/openstack/heat/test_random_string.py +++ b/heat/tests/openstack/heat/test_random_string.py @@ -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): diff --git a/heat/tests/openstack/heat/test_remote_stack.py b/heat/tests/openstack/heat/test_remote_stack.py index 8f3bdf1ff8..728622cc67 100644 --- a/heat/tests/openstack/heat/test_remote_stack.py +++ b/heat/tests/openstack/heat/test_remote_stack.py @@ -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): diff --git a/heat/tests/openstack/heat/test_resource_chain.py b/heat/tests/openstack/heat/test_resource_chain.py index a95819e88e..f352ec5614 100644 --- a/heat/tests/openstack/heat/test_resource_chain.py +++ b/heat/tests/openstack/heat/test_resource_chain.py @@ -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')) diff --git a/heat/tests/openstack/heat/test_resource_group.py b/heat/tests/openstack/heat/test_resource_group.py index ccecf5169a..75bff2dfd4 100644 --- a/heat/tests/openstack/heat/test_resource_group.py +++ b/heat/tests/openstack/heat/test_resource_group.py @@ -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() diff --git a/heat/tests/openstack/heat/test_software_deployment.py b/heat/tests/openstack/heat/test_software_deployment.py index 5e2800f8c9..01c079b4cc 100644 --- a/heat/tests/openstack/heat/test_software_deployment.py +++ b/heat/tests/openstack/heat/test_software_deployment.py @@ -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) diff --git a/heat/tests/openstack/heat/test_swiftsignal.py b/heat/tests/openstack/heat/test_swiftsignal.py index fb4b1c59de..a5bf36d134 100644 --- a/heat/tests/openstack/heat/test_swiftsignal.py +++ b/heat/tests/openstack/heat/test_swiftsignal.py @@ -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()) diff --git a/heat/tests/openstack/mistral/test_workflow.py b/heat/tests/openstack/mistral/test_workflow.py index dbf843c9f4..9419b8b2a1 100644 --- a/heat/tests/openstack/mistral/test_workflow.py +++ b/heat/tests/openstack/mistral/test_workflow.py @@ -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): diff --git a/heat/tests/openstack/neutron/test_neutron_floating_ip.py b/heat/tests/openstack/neutron/test_neutron_floating_ip.py index 72e57596dd..5b865de7e1 100644 --- a/heat/tests/openstack/neutron/test_neutron_floating_ip.py +++ b/heat/tests/openstack/neutron/test_neutron_floating_ip.py @@ -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) diff --git a/heat/tests/openstack/neutron/test_neutron_subnet.py b/heat/tests/openstack/neutron/test_neutron_subnet.py index 7f77cb4ee0..a4072eda03 100644 --- a/heat/tests/openstack/neutron/test_neutron_subnet.py +++ b/heat/tests/openstack/neutron/test_neutron_subnet.py @@ -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')) diff --git a/heat/tests/openstack/neutron/test_neutron_trunk.py b/heat/tests/openstack/neutron/test_neutron_trunk.py index 6f1dfa78f9..4fe5f4ec0b 100644 --- a/heat/tests/openstack/neutron/test_neutron_trunk.py +++ b/heat/tests/openstack/neutron/test_neutron_trunk.py @@ -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) diff --git a/heat/tests/openstack/nova/test_floatingip.py b/heat/tests/openstack/nova/test_floatingip.py index 79a55e9baa..1cd79ca090 100644 --- a/heat/tests/openstack/nova/test_floatingip.py +++ b/heat/tests/openstack/nova/test_floatingip.py @@ -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()) diff --git a/heat/tests/openstack/nova/test_keypair.py b/heat/tests/openstack/nova/test_keypair.py index baa3468f0e..36e7bf5997 100644 --- a/heat/tests/openstack/nova/test_keypair.py +++ b/heat/tests/openstack/nova/test_keypair.py @@ -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()) diff --git a/heat/tests/openstack/swift/test_container.py b/heat/tests/openstack/swift/test_container.py index 8a4939cecd..a91baba034 100644 --- a/heat/tests/openstack/swift/test_container.py +++ b/heat/tests/openstack/swift/test_container.py @@ -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') diff --git a/heat/tests/test_function.py b/heat/tests/test_function.py index afdb355227..3188937b6e 100644 --- a/heat/tests/test_function.py +++ b/heat/tests/test_function.py @@ -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)) diff --git a/heat/tests/test_hot.py b/heat/tests/test_hot.py index e4054f80e3..62be09a667 100644 --- a/heat/tests/test_hot.py +++ b/heat/tests/test_hot.py @@ -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() self.assertEqual((parser.Stack.CREATE, parser.Stack.COMPLETE), @@ -3628,6 +3478,12 @@ class TestGetAttAllAttributes(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(stack.defn, rsrc.name, node_data) + if self.raises is not None: ex = self.assertRaises(self.raises, self.resolve, self.snippet, tmpl, stack) diff --git a/heat/tests/test_metadata_refresh.py b/heat/tests/test_metadata_refresh.py index ac4960dfc1..94992599c5 100644 --- a/heat/tests/test_metadata_refresh.py +++ b/heat/tests/test_metadata_refresh.py @@ -269,7 +269,10 @@ class WaitConditionMetadataUpdateTest(common.HeatTestCase): update_metadata('123', 'foo', 'bar') def side_effect_popper(sleep_time): - if self.run_empty: + wh = stack['WH'] + if wh.status == wh.IN_PROGRESS: + return + elif self.run_empty: self.run_empty = False check_empty(sleep_time) else: @@ -308,7 +311,7 @@ class MetadataRefreshServerTest(common.HeatTestCase): return_value=1) @mock.patch.object(server.Server, 'handle_create') @mock.patch.object(server.Server, 'check_create_complete') - @mock.patch.object(server.Server, 'FnGetAtt') + @mock.patch.object(server.Server, 'get_attribute', new_callable=mock.Mock) def test_FnGetAtt_metadata_update(self, mock_get, mock_check, mock_handle, *args): temp = template_format.parse(TEST_TEMPLATE_SERVER) @@ -321,7 +324,7 @@ class MetadataRefreshServerTest(common.HeatTestCase): self.stub_KeypairConstraint_validate() # Note dummy addresses are from TEST-NET-1 ref rfc5737 - mock_get.side_effect = ['192.0.2.1', '192.0.2.2', '192.0.2.2'] + mock_get.side_effect = ['192.0.2.1', '192.0.2.2'] # Test stack.create() diff --git a/heat/tests/test_nested_stack.py b/heat/tests/test_nested_stack.py index 0cf70f8f4f..e7e979f71a 100644 --- a/heat/tests/test_nested_stack.py +++ b/heat/tests/test_nested_stack.py @@ -286,7 +286,7 @@ Resources: 'reference_id': 'the_nested_convg_mock' })} stack = parser.Stack(ctx, 'test_stack', tmpl, cache_data=cache_data) - nested_stack = stack['the_nested'] + nested_stack = stack.defn['the_nested'] self.assertEqual('the_nested_convg_mock', nested_stack.FnGetRefId()) def test_get_attribute(self): diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py index 8189a16f70..2c87c74bc3 100644 --- a/heat/tests/test_resource.py +++ b/heat/tests/test_resource.py @@ -1910,7 +1910,7 @@ class ResourceTest(common.HeatTestCase): 'action': 'CREATE', 'status': 'COMPLETE'})}) - res = stack['res'] + res = stack.defn['res'] self.assertEqual('Res', res.FnGetAtt('Foo')) def test_getatt_with_path_cache_data(self): @@ -1932,50 +1932,9 @@ class ResourceTest(common.HeatTestCase): 'action': 'CREATE', 'status': 'COMPLETE'})}) - res = stack['res'] + res = stack.defn['res'] self.assertEqual('abc', res.FnGetAtt('nested', 'string')) - def test_getatts(self): - tmpl = template.Template({ - 'heat_template_version': '2013-05-23', - 'resources': { - 'res': { - 'type': 'ResourceWithComplexAttributesType' - } - } - }) - stack = parser.Stack(utils.dummy_context(), 'test', tmpl) - res = stack['res'] - self.assertEqual({'list': ['foo', 'bar'], - 'flat_dict': {'key1': 'val1', - 'key2': 'val2', - 'key3': 'val3'}, - 'nested_dict': {'list': [1, 2, 3], - 'string': 'abc', - 'dict': {'a': 1, 'b': 2, 'c': 3}}, - 'none': None}, res.FnGetAtts()) - - def test_getatts_with_cache_data(self): - tmpl = template.Template({ - 'heat_template_version': '2013-05-23', - 'resources': { - 'res': { - 'type': 'ResourceWithPropsType' - } - } - }) - stack = parser.Stack(utils.dummy_context(), 'test', tmpl, - cache_data={ - 'res': node_data.NodeData.from_dict({ - 'attrs': {'Foo': 'res', - 'foo': 'res'}, - 'uuid': mock.ANY, - 'id': mock.ANY, - 'action': 'CREATE', - 'status': 'COMPLETE'})}) - res = stack['res'] - self.assertEqual({'foo': 'res', 'Foo': 'res'}, res.FnGetAtts()) - def test_properties_data_stored_encrypted_decrypted_on_load(self): cfg.CONF.set_override('encrypt_parameters_and_properties', True) diff --git a/heat/tests/test_stack.py b/heat/tests/test_stack.py index fe8c182c97..94f42ea2c1 100644 --- a/heat/tests/test_stack.py +++ b/heat/tests/test_stack.py @@ -1328,12 +1328,7 @@ class StackTest(common.HeatTestCase): (rsrc.RESUME, rsrc.COMPLETE), (rsrc.UPDATE, rsrc.IN_PROGRESS), (rsrc.UPDATE, rsrc.FAILED), - (rsrc.UPDATE, rsrc.COMPLETE)): - rsrc.state_set(action, status) - self.stack._update_all_resource_data(False, True) - self.assertEqual('AResource', - self.stack.outputs['TestOutput'].get_value()) - for action, status in ( + (rsrc.UPDATE, rsrc.COMPLETE), (rsrc.DELETE, rsrc.IN_PROGRESS), (rsrc.DELETE, rsrc.FAILED), (rsrc.DELETE, rsrc.COMPLETE)): @@ -2387,11 +2382,14 @@ class StackTest(common.HeatTestCase): cache_data=cache_data) # Check if the property has the appropriate resolved value. - cached_property = lightweight_stack['bar'].properties['Foo'] - self.assertEqual(cached_property, 'baz') + bar = resource.Resource( + 'bar', + lightweight_stack.defn.resource_definition('bar'), + lightweight_stack) + self.assertEqual('baz', bar.properties['Foo']) # Make sure FnGetAtt returns the cached value. - attr_value = lightweight_stack['foo'].FnGetAtt('bar') + attr_value = lightweight_stack.defn['foo'].FnGetAtt('bar') self.assertEqual('baz', attr_value) # Make sure calls are not made to the database to retrieve the @@ -2427,11 +2425,14 @@ class StackTest(common.HeatTestCase): cache_data=cache_data) # Check if the property has the appropriate resolved value. - cached_property = lightweight_stack['bar'].properties['Foo'] - self.assertEqual(cached_property, 'physical-resource-id') + bar = resource.Resource( + 'bar', + lightweight_stack.defn.resource_definition('bar'), + lightweight_stack) + self.assertEqual('physical-resource-id', bar.properties['Foo']) # Make sure FnGetRefId returns the cached value. - resource_id = lightweight_stack['foo'].FnGetRefId() + resource_id = lightweight_stack.defn['foo'].FnGetRefId() self.assertEqual('physical-resource-id', resource_id) # Make sure calls are not made to the database to retrieve the diff --git a/heat/tests/test_stack_collect_attributes.py b/heat/tests/test_stack_collect_attributes.py index 381a1aec56..68e198f845 100644 --- a/heat/tests/test_stack_collect_attributes.py +++ b/heat/tests/test_stack_collect_attributes.py @@ -230,10 +230,11 @@ class DepAttrsTest(common.HeatTestCase): template.Template(parsed_tmpl)) for res in six.itervalues(self.stack): - resources = six.itervalues(self.stack.resources) + definitions = (self.stack.defn.resource_definition(n) + for n in parsed_tmpl['resources']) self.assertEqual(self.expected[res.name], set(itertools.chain.from_iterable( - r.t.dep_attrs(res.name) for r in resources))) + d.dep_attrs(res.name) for d in definitions))) class ReferencedAttrsTest(common.HeatTestCase): diff --git a/heat/tests/test_stack_resource.py b/heat/tests/test_stack_resource.py index 4fc78001d8..fab4e570c7 100644 --- a/heat/tests/test_stack_resource.py +++ b/heat/tests/test_stack_resource.py @@ -470,8 +470,8 @@ class StackResourceTest(StackResourceBaseTest): })} stack = parser.Stack(utils.dummy_context(), 'test_att', tmpl, cache_data=cache_data) - rsrc = stack['my_autoscaling_group'] - self.assertEqual(4, rsrc.FnGetAtt(rsrc.CURRENT_SIZE)) + rsrc = stack.defn['my_autoscaling_group'] + self.assertEqual(4, rsrc.FnGetAtt('current_size')) def test__validate_nested_resources_checks_num_of_resources(self): stack_resource.cfg.CONF.set_override('max_resources_per_stack', 2) diff --git a/heat/tests/test_stack_update.py b/heat/tests/test_stack_update.py index 4c62234ae0..8a3173d504 100644 --- a/heat/tests/test_stack_update.py +++ b/heat/tests/test_stack_update.py @@ -1269,17 +1269,9 @@ class StackUpdateTest(common.HeatTestCase): 'AResource', self.stack['BResource']._stored_properties_data['Foo']) - self.ref_id_called = False - - def get_ref_id(*args): - ref_id = 'inst-007' if self.ref_id_called else 'AResource' - if self.ref_id_called is False: - self.ref_id_called = True - return ref_id - mock_id = self.patchobject(generic_rsrc.ResourceWithProps, - 'FnGetRefId', - side_effect=get_ref_id) + 'get_reference_id', + return_value='inst-007') updated_stack = stack.Stack(self.ctx, 'updated_stack', template.Template(tmpl2)) @@ -1293,7 +1285,6 @@ class StackUpdateTest(common.HeatTestCase): 'inst-007', self.stack['BResource']._stored_properties_data['Foo']) - # Note: mock_id is called 14 times!!! mock_id.assert_called_with() def test_update_with_new_resources_with_reference(self): @@ -1383,7 +1374,8 @@ class StackUpdateTest(common.HeatTestCase): self.stack['BResource']._stored_properties_data['Foo']) mock_id = self.patchobject(generic_rsrc.ResourceWithProps, - 'FnGetRefId', return_value='AResource') + 'get_reference_id', + return_value='AResource') # mock to make the replace fail when creating the replacement resource mock_create = self.patchobject(generic_rsrc.ResourceWithProps, diff --git a/heat/tests/test_template.py b/heat/tests/test_template.py index d09c0804da..ee4ecfe4d6 100644 --- a/heat/tests/test_template.py +++ b/heat/tests/test_template.py @@ -28,8 +28,10 @@ from heat.engine.clients.os import nova from heat.engine import environment from heat.engine import function from heat.engine.hot import template as hot_t +from heat.engine import node_data 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.openstack.nova import fakes as fakes_nova @@ -697,11 +699,12 @@ class TemplateTest(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): empty = template.Template(empty_template) @@ -900,21 +903,19 @@ class TemplateTest(common.HeatTestCase): def test_resource_refs(self): tmpl = template.Template(resource_template) stk = stack.Stack(self.ctx, 'test', tmpl) + stk.validate() - self.m.StubOutWithMock(stk['foo'], 'FnGetRefId') - stk['foo'].FnGetRefId().MultipleTimes().AndReturn('bar') - self.m.ReplayAll() - + data = node_data.NodeData.from_dict({'reference_id': 'bar'}) + stk_defn.update_resource_data(stk.defn, 'foo', data) r_snippet = {"Ref": "foo"} self.assertEqual("bar", self.resolve(r_snippet, tmpl, stk)) - self.m.VerifyAll() def test_resource_refs_param(self): tmpl = template.Template(resource_template) stk = stack.Stack(self.ctx, 'test', tmpl) p_snippet = {"Ref": "baz"} - parsed = tmpl.parse(stk, p_snippet) + parsed = tmpl.parse(stk.defn, p_snippet) self.assertIsInstance(parsed, cfn_funcs.ParamRef) def test_select_from_list(self): @@ -1654,7 +1655,7 @@ class ResolveDataTest(common.HeatTestCase): template.Template(empty_template)) 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_join_split(self): # join