diff --git a/heat/engine/stack.py b/heat/engine/stack.py index fbe1c4b256..3a69319e89 100644 --- a/heat/engine/stack.py +++ b/heat/engine/stack.py @@ -480,22 +480,22 @@ class Stack(collections.Mapping): if result: raise exception.StackValidationFailed(message=result) - for val in self.outputs.values(): - try: - if not val or not val.get('Value'): - message = _('Each Output must contain ' - 'a Value key.') - raise exception.StackValidationFailed(message=message) - function.validate(val.get('Value')) - except AttributeError: - message = _('Output validation error: ' - 'Outputs must contain Output. ' - 'Found a [%s] instead') % type(val) + for val in self.outputs.values(): + try: + if not val or not val.get('Value'): + message = _('Each Output must contain ' + 'a Value key.') raise exception.StackValidationFailed(message=message) - except Exception as ex: - reason = _('Output validation error: ' - '%s') % six.text_type(ex) - raise exception.StackValidationFailed(message=reason) + function.validate(val.get('Value')) + except AttributeError: + message = _('Output validation error: ' + 'Outputs must contain Output. ' + 'Found a [%s] instead') % type(val) + raise exception.StackValidationFailed(message=message) + except Exception as ex: + reason = _('Output validation error: ' + '%s') % six.text_type(ex) + raise exception.StackValidationFailed(message=reason) def requires_deferred_auth(self): ''' diff --git a/heat/tests/test_parser.py b/heat/tests/test_parser.py index 7326743ad7..b6e89b99f6 100644 --- a/heat/tests/test_parser.py +++ b/heat/tests/test_parser.py @@ -4268,6 +4268,41 @@ class StackTest(common.HeatTestCase): '(AResource Bar) is incorrect.', six.text_type(ex)) + def test_incorrect_outputs_cfn_incorrect_reference(self): + tmpl = template_format.parse(""" + HeatTemplateFormatVersion: '2012-12-12' + Outputs: + Output: + Value: + Fn::GetAtt: + - Resource + - Foo + """) + self.stack = parser.Stack(self.ctx, 'stack_with_incorrect_outputs', + template.Template(tmpl)) + + ex = self.assertRaises(exception.StackValidationFailed, + self.stack.validate) + + self.assertIn('The specified reference "Resource" ' + '(in unknown) is incorrect.', six.text_type(ex)) + + def test_incorrect_outputs_incorrect_reference(self): + tmpl = template_format.parse(""" + heat_template_version: 2013-05-23 + outputs: + output: + value: { get_attr: [resource, foo] } + """) + self.stack = parser.Stack(self.ctx, 'stack_with_incorrect_outputs', + template.Template(tmpl)) + + ex = self.assertRaises(exception.StackValidationFailed, + self.stack.validate) + + self.assertIn('The specified reference "resource" ' + '(in unknown) is incorrect.', six.text_type(ex)) + def test_incorrect_outputs_cfn_empty_output(self): tmpl = template_format.parse(""" HeatTemplateFormatVersion: '2012-12-12'