def _get_stack_outputs(self, stack_name): """ Communicates with AWS Cloudformation to fetch outputs from a specific stack. :param stack_name: Name of the stack to collect output for. :type stack_name: str :returns: A formatted version of the stack outputs. :rtype: dict :raises: sceptre.stack.DependencyStackNotLaunchedException """ self.logger.debug( "Collecting outputs from '{0}'...".format(stack_name)) connection_manager = self.stack.connection_manager try: response = connection_manager.call( service="cloudformation", command="describe_stacks", kwargs={"StackName": stack_name}) except ClientError as e: if "does not exist" in e.response["Error"]["Message"]: raise StackDoesNotExistError(e.response["Error"]["Message"]) else: raise e else: outputs = response["Stacks"][0]["Outputs"] self.logger.debug("Outputs: {0}".format(outputs)) formatted_outputs = dict( (output["OutputKey"], output["OutputValue"]) for output in outputs) return formatted_outputs
def test_launch_with_stack_that_does_not_exist(self, mock_get_status, mock_create): mock_get_status.side_effect = StackDoesNotExistError() mock_create.return_value = sentinel.launch_response response = self.actions.launch() mock_create.assert_called_once_with() assert response == sentinel.launch_response
def test_delete_when_wait_for_completion_raises_stack_does_not_exist_error( self, mock_get_status, mock_wait_for_completion ): mock_get_status.return_value = "CREATE_COMPLETE" mock_wait_for_completion.side_effect = StackDoesNotExistError() status = self.actions.delete() assert status == StackStatus.COMPLETE
def test_delete_with_non_existent_stack( self, mock_get_status, mock_hooks, mock_wait_for_completion ): self.stack._config = {"protect": False} mock_get_status.side_effect = StackDoesNotExistError() status = self.stack.delete() assert status == StackStatus.PENDING
def test_delete_when_wait_for_completion_raises_stack_does_not_exist_error( self, mock_get_status, mock_hooks, mock_wait_for_completion): self.stack._config = {"protect": False} mock_get_status.return_value = "CREATE_COMPLETE" self.stack.config["role_arn"] = sentinel.role_arn mock_wait_for_completion.side_effect = StackDoesNotExistError() status = self.stack.delete() assert status == StackStatus.COMPLETE
def test_launch_with_stack_that_does_not_exist(self, mock_get_status, mock_create, mock_hooks): self.stack._config = {"protect": False} mock_get_status.side_effect = StackDoesNotExistError() mock_create.return_value = sentinel.launch_response response = self.stack.launch() mock_create.assert_called_once_with() assert response == sentinel.launch_response
def test_describe_with_missing_stack(self): mock_stack = MagicMock(spec=Stack) mock_stack.name = "stack" mock_stack.get_status.side_effect = StackDoesNotExistError() self.stack_group.stacks = [mock_stack] response = self.stack_group.describe() assert response == {"stack": "PENDING"}
def _get_status(self): try: status = self._describe()["Stacks"][0]["StackStatus"] except botocore.exceptions.ClientError as exp: if exp.response["Error"]["Message"].endswith("does not exist"): raise StackDoesNotExistError(exp.response["Error"]["Message"]) else: raise exp return status
def test_delete_with_non_existent_stack(self, mock_get_status, mock_wait_for_completion): mock_get_status.side_effect = StackDoesNotExistError() status = self.actions.delete() assert status == StackStatus.COMPLETE
def resolve(self): raise StackDoesNotExistError()