From 2f04eb56db540a5216ddc5d9dc814c859b784a2d Mon Sep 17 00:00:00 2001 From: Sriram Madapusi Vasudevan Date: Tue, 11 Feb 2020 16:24:18 -0800 Subject: [PATCH] fix: display no outputs if outputs are not defined. Why is this change necessary? * bug from previous PR which always looked for outputs in deployed templates. How does it address the issue? * Explicitly check for outputs, before attempting to display them. * Added extra tests to verify so that it does not cause regressions in the future. What side effects does this change have? * None. --- samcli/lib/deploy/deployer.py | 7 ++++--- tests/unit/lib/deploy/test_deployer.py | 28 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/samcli/lib/deploy/deployer.py b/samcli/lib/deploy/deployer.py index b484d6f609..d5776574ac 100644 --- a/samcli/lib/deploy/deployer.py +++ b/samcli/lib/deploy/deployer.py @@ -401,7 +401,8 @@ def wait_for_execute(self, stack_name, changeset_type): raise deploy_exceptions.DeployFailedError(stack_name=stack_name, msg=str(ex)) outputs = self.get_stack_outputs(stack_name=stack_name, echo=False) - self._stack_outputs(outputs) + if outputs: + self._display_stack_outputs(outputs) def create_and_wait_for_changeset( self, stack_name, cfn_template, parameter_values, capabilities, role_arn, notification_arns, s3_uploader, tags @@ -419,7 +420,7 @@ def create_and_wait_for_changeset( @pprint_column_names( format_string=OUTPUTS_FORMAT_STRING, format_kwargs=OUTPUTS_DEFAULTS_ARGS, table_header=OUTPUTS_TABLE_HEADER_NAME ) - def _stack_outputs(self, stack_outputs, **kwargs): + def _display_stack_outputs(self, stack_outputs, **kwargs): for counter, output in enumerate(stack_outputs): for k, v in [ ("Key", output.get("OutputKey")), @@ -448,7 +449,7 @@ def get_stack_outputs(self, stack_name, echo=True): if echo: sys.stdout.write("\nStack {stack_name} outputs:\n".format(stack_name=stack_name)) sys.stdout.flush() - self._stack_outputs(stack_outputs=outputs) + self._display_stack_outputs(stack_outputs=outputs) return outputs except KeyError: return None diff --git a/tests/unit/lib/deploy/test_deployer.py b/tests/unit/lib/deploy/test_deployer.py index 38d8267d3b..592585bc26 100644 --- a/tests/unit/lib/deploy/test_deployer.py +++ b/tests/unit/lib/deploy/test_deployer.py @@ -598,3 +598,31 @@ def test_get_stack_outputs_exception(self): with self.assertRaises(DeployStackOutPutFailedError): self.deployer.get_stack_outputs(stack_name="test") + + @patch("time.sleep") + def test_wait_for_execute_no_outputs(self, patched_time): + self.deployer.describe_stack_events = MagicMock() + self.deployer._client.get_waiter = MagicMock(return_value=MockCreateUpdateWaiter()) + self.deployer._display_stack_outputs = MagicMock() + self.deployer.get_stack_outputs = MagicMock(return_value=None) + self.deployer.wait_for_execute("test", "CREATE") + self.assertEqual(self.deployer._display_stack_outputs.call_count, 0) + + @patch("time.sleep") + def test_wait_for_execute_with_outputs(self, patched_time): + self.deployer.describe_stack_events = MagicMock() + outputs = { + "Stacks": [ + { + "Outputs": [ + {"OutputKey": "Key1", "OutputValue": "Value1", "Description": "output for s3"}, + {"OutputKey": "Key2", "OutputValue": "Value2", "Description": "output for kms"}, + ] + } + ] + } + self.deployer._client.get_waiter = MagicMock(return_value=MockCreateUpdateWaiter()) + self.deployer._display_stack_outputs = MagicMock() + self.deployer.get_stack_outputs = MagicMock(return_value=outputs["Stacks"][0]["Outputs"]) + self.deployer.wait_for_execute("test", "CREATE") + self.assertEqual(self.deployer._display_stack_outputs.call_count, 1)