Pass on outputs errors to parent stacks
If getting an output from a child stack fails with an error, we didn't pass
on the error message to the parent stack that was requesting it but instead
reported essentially that the given output did not exist.
Change-Id: I5653baf310a29dc4829ad570c769cf67ce12695e
Partial-Bug: #1599114
(cherry picked from commit b90991e00b
)
This commit is contained in:
parent
33c5eee231
commit
e5cd344025
|
@ -154,6 +154,10 @@ class InvalidTemplateReference(HeatException):
|
|||
' is incorrect.')
|
||||
|
||||
|
||||
class TemplateOutputError(HeatException):
|
||||
msg_fmt = _('Error in %(resource)s output %(attribute)s: %(message)s')
|
||||
|
||||
|
||||
class InvalidExternalResourceDependency(HeatException):
|
||||
msg_fmt = _("Invalid dependency with external %(resource_type)s "
|
||||
"resource: %(external_id)s")
|
||||
|
|
|
@ -587,8 +587,10 @@ class StackResource(resource.Resource):
|
|||
particular exception, not KeyError, being raised if the key does not
|
||||
exist.)
|
||||
"""
|
||||
if self._outputs is None or self._outputs.get(op,
|
||||
NotImplemented) is None:
|
||||
if (self._outputs is None or
|
||||
(op in self._outputs and
|
||||
rpc_api.OUTPUT_ERROR not in self._outputs[op] and
|
||||
self._outputs[op].get(rpc_api.OUTPUT_VALUE) is None)):
|
||||
stack_identity = self.nested_identifier()
|
||||
if stack_identity is None:
|
||||
return
|
||||
|
@ -597,14 +599,20 @@ class StackResource(resource.Resource):
|
|||
if not stack:
|
||||
return
|
||||
outputs = stack[0].get(rpc_api.STACK_OUTPUTS) or {}
|
||||
self._outputs = {o[rpc_api.OUTPUT_KEY]: o[rpc_api.OUTPUT_VALUE]
|
||||
for o in outputs if rpc_api.OUTPUT_ERROR not in o}
|
||||
self._outputs = {o[rpc_api.OUTPUT_KEY]: o for o in outputs}
|
||||
|
||||
try:
|
||||
return self._outputs[op]
|
||||
except KeyError:
|
||||
if op not in self._outputs:
|
||||
raise exception.InvalidTemplateAttribute(resource=self.name,
|
||||
key=op)
|
||||
|
||||
output_data = self._outputs[op]
|
||||
if rpc_api.OUTPUT_ERROR in output_data:
|
||||
raise exception.TemplateOutputError(
|
||||
resource=self.name,
|
||||
attribute=op,
|
||||
message=output_data[rpc_api.OUTPUT_ERROR])
|
||||
|
||||
return output_data[rpc_api.OUTPUT_VALUE]
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
return self.get_output(name)
|
||||
|
|
|
@ -319,7 +319,7 @@ class ProviderTemplateTest(common.HeatTestCase):
|
|||
output = {'outputs': [{'output_key': 'Foo', 'output_value': None,
|
||||
'output_error': 'it is all bad'}]}
|
||||
temp_res._rpc_client.show_stack.return_value = [output]
|
||||
self.assertRaises(exception.InvalidTemplateAttribute,
|
||||
self.assertRaises(exception.TemplateOutputError,
|
||||
temp_res.FnGetAtt, 'Foo')
|
||||
|
||||
def test_properties_normal(self):
|
||||
|
|
Loading…
Reference in New Issue