From cfff39ce68be4ad88bea8f595aa9ae4e78983c78 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Mon, 10 Jul 2017 13:47:59 -0400 Subject: [PATCH] Always cache attributes in outputs in Resource.node_data() Ensure that attributes that are referenced in outputs get cached (and therefore stored in the database) even when they are not referenced by other resources. Change-Id: I667ab04f91edddef5c5dbec0a89d465110c312b4 Closes-Bug: #1660831 --- heat/engine/resource.py | 26 ++++++++++++++++++- heat/engine/service.py | 3 --- heat/tests/test_hot.py | 2 +- ...-resource-attributes-8bcbedca2f86986e.yaml | 10 +++++++ 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/store-resource-attributes-8bcbedca2f86986e.yaml diff --git a/heat/engine/resource.py b/heat/engine/resource.py index e8f158e9a2..30eabf1dca 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -943,15 +943,39 @@ class Resource(status.ResourceStatus): return refd_attrs def node_data(self): - def get_attrs(attrs): + """Return a NodeData object representing the resource. + + The NodeData object returned contains basic data about the resource, + including its name, ID and state, as well as its reference ID and any + attribute values that are used. + + Only those attribute values that are referenced by other + resources are included. + + After calling this method, the resource's attribute cache is + populated with any cacheable attribute values referenced by stack + outputs, even if they are not also referenced by other resources. + """ + def get_attrs(attrs, cacheable_only=False): for attr in attrs: path = (attr,) if isinstance(attr, six.string_types) else attr + if (cacheable_only and + (self.attributes.get_cache_mode(path[0]) == + attributes.Schema.CACHE_NONE)): + continue try: yield attr, self._get_attribute_caching(*path) except exception.InvalidTemplateAttribute as ita: LOG.info('%s', ita) dep_attrs = self.referenced_attrs(in_outputs=False) + + # Ensure all attributes referenced in outputs get cached + if self.stack.convergence: + out_attrs = self.referenced_attrs(in_resources=False) + for e in get_attrs(out_attrs - dep_attrs, cacheable_only=True): + pass + return node_data.NodeData(self.id, self.name, self.uuid, self.get_reference_id(), dict(get_attrs(dep_attrs)), diff --git a/heat/engine/service.py b/heat/engine/service.py index 31b6874da6..71a5821489 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -530,9 +530,6 @@ class EngineService(service.ServiceBase): stack, resolve_outputs=resolve_outputs) for stack in stacks] if resolve_outputs: # Cases where stored attributes may not exist for a resource: - # * For those resources that have attributes that were - # *not* referenced by other resources, their attributes - # are not resolved/stored over a stack update traversal # * The resource is an AutoScalingGroup that received a signal # * Near simultaneous updates (say by an update and a signal) # * The first time resolving a pre-Pike stack diff --git a/heat/tests/test_hot.py b/heat/tests/test_hot.py index cde940519f..e238caab3b 100644 --- a/heat/tests/test_hot.py +++ b/heat/tests/test_hot.py @@ -2781,7 +2781,7 @@ class StackGetAttributesTestConvergence(common.HeatTestCase): self.stack.t.parse(self.stack, self.snippet), self.resource_name) with mock.patch.object(rsrc.stack, 'get_dep_attrs') as mock_da: - mock_da.return_value = dep_attrs + mock_da.return_value = list(dep_attrs) rsrc_data = rsrc.node_data() # store as cache data self.stack.cache_data = { diff --git a/releasenotes/notes/store-resource-attributes-8bcbedca2f86986e.yaml b/releasenotes/notes/store-resource-attributes-8bcbedca2f86986e.yaml new file mode 100644 index 0000000000..062176b33a --- /dev/null +++ b/releasenotes/notes/store-resource-attributes-8bcbedca2f86986e.yaml @@ -0,0 +1,10 @@ +--- +features: + - Resource attributes are now stored at the time a resource is created or + updated, allowing for fast resolution of outputs without having to retrieve + live data from the underlying physical resource. To minimise compatibility + problems, the behaviour of the `show` attribute, the `with_attr` option to + the resource show API, and stacks that do not yet use the convergence + architecture (due to the convergence_engine being disabled at the time they + were created) is unchanged - in each of these cases live data will still be + returned.