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
This commit is contained in:
parent
b0d725bdb8
commit
b90991e00b
@ -158,6 +158,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")
|
||||
|
@ -585,8 +585,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
|
||||
@ -595,14 +597,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…
x
Reference in New Issue
Block a user