Eliminate errors getting TemplateResource OS::stack_id

We want to avoid making an RPC call to get the OS::stack_id output in order
to calculate the reference ID of a TemplateResource whenever possible -
which should be most of the time given the limited use of this feature in
the wild - since this happens virtually every time we load the stack.
Previously, we were doing this by trying to load the template from the
parent stack's environment, and combine it with the stored parameters
(using live parameter values caused failures). However, this resulted in
failures in the case that the template in the parent stack's environment
differed from the one that was last used to update the resource if the
parameter schema had been modified in an incompatible way.

It transpires that we already determine what outputs are available at
object instantiation time in order to populate the attributes_schema. So we
can just use the attributes schema to infer the existence or otherwise of
the output without doing any other calculation in get_reference_id() that
could cause errors.

This method doesn't fail-safe, in the sense that if there are any errors
then we end up with an empty schema and won't fall back to making the RPC
call. However, if there are any errors then probably all bets are off for
the reference ID anyway. In common with the old method, it also has the
drawback of using the latest template rather than the existing one
(although again, once you do an update removing the OS::stack_id output
then all bets are off in terms of continuing to see that value as the
reference ID).

Unlike the previous method, this doesn't take into account disabled outputs
(since calculating conditions requires access to the parameters, which were
the cause of the problem). Also, the code that calculates the attributes
schema doesn't use a proper API but hackily dives into the raw template
data, and fixing it would raise all of the same issues that we've had with
trying to load the template properly here. So we are kicking the can down
the road a bit or, alternatively, consolidating our issues into a single
place, depending on your point of view.

Change-Id: Ic63fe290249dba5bc00abbde1f4df608181d6a9c
Closes-Bug: #1742646
Related-Bug: #1719333
This commit is contained in:
Zane Bitter 2018-01-11 21:44:27 -05:00
parent 63969533ea
commit f965ff615e
1 changed files with 10 additions and 13 deletions

View File

@ -312,14 +312,11 @@ class TemplateResource(stack_resource.StackResource):
return self._reference_id
stack_identity = self.nested_identifier()
with self.frozen_properties():
nest_defn = self.child_definition(nested_identifier=stack_identity)
if STACK_ID_OUTPUT in nest_defn.enabled_output_names():
try:
if self._outputs is not None:
self._reference_id = self.get_output(STACK_ID_OUTPUT)
return self._reference_id
try:
if self._outputs is not None:
self._reference_id = self.get_output(STACK_ID_OUTPUT)
elif STACK_ID_OUTPUT in self.attributes:
output = self.rpc_client().show_output(self.context,
dict(stack_identity),
STACK_ID_OUTPUT)
@ -328,13 +325,13 @@ class TemplateResource(stack_resource.StackResource):
resource=self.name,
attribute=STACK_ID_OUTPUT,
message=output[rpc_api.OUTPUT_ERROR])
except exception.TemplateOutputError as err:
LOG.info('%s', err)
except exception.NotFound:
pass
else:
self._reference_id = output[rpc_api.OUTPUT_VALUE]
return self._reference_id
except exception.TemplateOutputError as err:
LOG.info('%s', err)
except exception.NotFound:
pass
else:
return self._reference_id
return stack_identity.arn()