diff options
-rw-r--r-- | heat/engine/api.py | 13 | ||||
-rw-r--r-- | heat/engine/parser.py | 3 | ||||
-rw-r--r-- | heat/rpc/api.py | 2 | ||||
-rw-r--r-- | heat/tests/test_engine_api_utils.py | 34 | ||||
-rw-r--r-- | heat/tests/test_parser.py | 3 |
5 files changed, 50 insertions, 5 deletions
diff --git a/heat/engine/api.py b/heat/engine/api.py index d0df38984..382c36f77 100644 --- a/heat/engine/api.py +++ b/heat/engine/api.py @@ -68,10 +68,15 @@ def format_stack_outputs(stack, outputs): that matches the API output expectations. ''' def format_stack_output(k): - return {api.OUTPUT_DESCRIPTION: outputs[k].get('Description', - 'No description given'), - api.OUTPUT_KEY: k, - api.OUTPUT_VALUE: stack.output(k)} + output = { + api.OUTPUT_DESCRIPTION: outputs[k].get('Description', + 'No description given'), + api.OUTPUT_KEY: k, + api.OUTPUT_VALUE: stack.output(k) + } + if outputs[k].get('error_msg'): + output.update({api.OUTPUT_ERROR: outputs[k].get('error_msg')}) + return output return [format_stack_output(key) for key in outputs] diff --git a/heat/engine/parser.py b/heat/engine/parser.py index b863c60b9..d1e66e920 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -800,7 +800,8 @@ class Stack(collections.Mapping): value = self.outputs[key].get('Value', '') try: return function.resolve(value) - except Exception: + except Exception as ex: + self.outputs[key]['error_msg'] = six.text_type(ex) return None def restart_resource(self, resource_name): diff --git a/heat/rpc/api.py b/heat/rpc/api.py index 95e63e6c1..1b5495829 100644 --- a/heat/rpc/api.py +++ b/heat/rpc/api.py @@ -42,9 +42,11 @@ STACK_KEYS = ( STACK_OUTPUT_KEYS = ( OUTPUT_DESCRIPTION, OUTPUT_KEY, OUTPUT_VALUE, + OUTPUT_ERROR, ) = ( 'description', 'output_key', 'output_value', + 'output_error', ) RES_KEYS = ( diff --git a/heat/tests/test_engine_api_utils.py b/heat/tests/test_engine_api_utils.py index 772c95aa2..fdb2e6077 100644 --- a/heat/tests/test_engine_api_utils.py +++ b/heat/tests/test_engine_api_utils.py @@ -216,6 +216,40 @@ class FormatTest(HeatTestCase): info = api.format_stack(self.stack) self.assertEqual('foobar', info[rpc_api.STACK_OUTPUTS]) + def test_format_stack_outputs(self): + template = parser.Template({ + 'HeatTemplateFormatVersion': '2012-12-12', + 'Resources': { + 'generic': {'Type': 'GenericResourceType'} + }, + 'Outputs': { + 'correct_output': { + 'Description': 'Good output', + 'Value': {'Fn::GetAtt': ['generic', 'Foo']} + }, + 'incorrect_output': { + 'Value': {'Fn::GetAtt': ['generic', 'Bar']} + } + } + }) + stack = parser.Stack(utils.dummy_context(), 'test_stack', + template, stack_id=str(uuid.uuid4())) + stack.action = 'CREATE' + stack.status = 'COMPLETE' + stack['generic'].action = 'CREATE' + stack['generic'].status = 'COMPLETE' + info = api.format_stack_outputs(stack, stack.outputs) + expected = [{'description': 'No description given', + 'output_error': 'The Referenced Attribute (generic Bar) ' + 'is incorrect.', + 'output_key': 'incorrect_output', + 'output_value': None}, + {'description': 'Good output', + 'output_key': 'correct_output', + 'output_value': 'generic'}] + + self.assertEqual(expected, info) + class FormatValidateParameterTest(HeatTestCase): diff --git a/heat/tests/test_parser.py b/heat/tests/test_parser.py index 123e0c34c..e7820b704 100644 --- a/heat/tests/test_parser.py +++ b/heat/tests/test_parser.py @@ -3089,6 +3089,9 @@ class StackTest(HeatTestCase): self.stack.state) self.assertIsNone(self.stack.output('Resource_attr')) + self.assertEqual('The Referenced Attribute (AResource Bar) is ' + 'incorrect.', + self.stack.outputs['Resource_attr']['error_msg']) self.stack.delete() |