Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Resolve #1451] Stop suppressing ClientError in describe_outputs #1452

Merged
23 changes: 0 additions & 23 deletions integration-tests/features/describe-stack-group-resources.feature

This file was deleted.

25 changes: 0 additions & 25 deletions integration-tests/features/describe-stack-group.feature

This file was deleted.

11 changes: 0 additions & 11 deletions integration-tests/features/describe-stack-resources.feature

This file was deleted.

7 changes: 0 additions & 7 deletions integration-tests/steps/stack_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,6 @@ def step_impl(context, stack_group_name, status):
assert response in expected_response


@then("no resources are described")
zaro0508 marked this conversation as resolved.
Show resolved Hide resolved
def step_impl(context):
for stack_resources in context.response:
stack_name = next(iter(stack_resources))
assert stack_resources == {stack_name: []}


@then('stack "{stack_name}" is described as "{status}"')
def step_impl(context, stack_name, status):
response = next(
Expand Down
10 changes: 7 additions & 3 deletions sceptre/diffing/stack_differ.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
from sceptre.plan.actions import StackActions
from sceptre.stack import Stack

from botocore.exceptions import ClientError

DiffType = TypeVar("DiffType")

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -192,10 +194,12 @@ def _extract_parameters_from_generated_stack(self, stack: Stack) -> dict:
def _create_deployed_stack_config(
self, stack_actions: StackActions
) -> Optional[StackConfiguration]:
description = stack_actions.describe()
if description is None:
try:
description = stack_actions.describe()
except ClientError as err:
# This means the stack has not been deployed yet
return None
if err.response["Error"]["Message"].endswith("does not exist"):
return None

stacks = description["Stacks"]
for stack in stacks:
Expand Down
32 changes: 8 additions & 24 deletions sceptre/plan/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,16 +303,11 @@ def describe(self):
:returns: A Stack description.
:rtype: dict
"""
try:
return self.connection_manager.call(
service="cloudformation",
command="describe_stacks",
kwargs={"StackName": self.stack.external_name},
)
except botocore.exceptions.ClientError as e:
if e.response["Error"]["Message"].endswith("does not exist"):
return
raise
return self.connection_manager.call(
service="cloudformation",
command="describe_stacks",
kwargs={"StackName": self.stack.external_name},
)

def describe_events(self):
"""
Expand Down Expand Up @@ -364,15 +359,11 @@ def describe_outputs(self):
"""
Returns the Stack's outputs.

:returns: The Stack's outputs.
:returns: The stack's outputs.
:rtype: list
"""
self.logger.debug("%s - Describing stack outputs", self.stack.name)

try:
response = self._describe()
except botocore.exceptions.ClientError:
return []
response = self.describe()

return {self.stack.name: response["Stacks"][0].get("Outputs", [])}

Expand Down Expand Up @@ -784,16 +775,9 @@ def timed_out(elapsed):

return status

def _describe(self):
return self.connection_manager.call(
service="cloudformation",
command="describe_stacks",
kwargs={"StackName": self.stack.external_name},
)

def _get_status(self):
try:
status = self._describe()["Stacks"][0]["StackStatus"]
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"])
Expand Down
11 changes: 6 additions & 5 deletions tests/test_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,14 +556,15 @@ def test_describe_resources_sends_correct_request(self):
]
}

@patch("sceptre.plan.actions.StackActions._describe")
@patch("sceptre.plan.actions.StackActions.describe")
def test_describe_outputs_sends_correct_request(self, mock_describe):
mock_describe.return_value = {"Stacks": [{"Outputs": sentinel.outputs}]}
response = self.actions.describe_outputs()

mock_describe.assert_called_once_with()
assert response == {self.stack.name: sentinel.outputs}

@patch("sceptre.plan.actions.StackActions._describe")
@patch("sceptre.plan.actions.StackActions.describe")
def test_describe_outputs_handles_stack_with_no_outputs(self, mock_describe):
mock_describe.return_value = {"Stacks": [{}]}
response = self.actions.describe_outputs()
Expand Down Expand Up @@ -892,13 +893,13 @@ def test_format_parameters_with_none_list_and_string_values(self):
{"ParameterKey": "key2", "ParameterValue": "value4"},
]

@patch("sceptre.plan.actions.StackActions._describe")
@patch("sceptre.plan.actions.StackActions.describe")
def test_get_status_with_created_stack(self, mock_describe):
mock_describe.return_value = {"Stacks": [{"StackStatus": "CREATE_COMPLETE"}]}
status = self.actions.get_status()
assert status == "CREATE_COMPLETE"

@patch("sceptre.plan.actions.StackActions._describe")
@patch("sceptre.plan.actions.StackActions.describe")
def test_get_status_with_non_existent_stack(self, mock_describe):
mock_describe.side_effect = ClientError(
{
Expand All @@ -911,7 +912,7 @@ def test_get_status_with_non_existent_stack(self, mock_describe):
)
assert self.actions.get_status() == "PENDING"

@patch("sceptre.plan.actions.StackActions._describe")
@patch("sceptre.plan.actions.StackActions.describe")
def test_get_status_with_unknown_clinet_error(self, mock_describe):
mock_describe.side_effect = ClientError(
{"Error": {"Code": "DoesNotExistException", "Message": "Boom!"}},
Expand Down
14 changes: 12 additions & 2 deletions tests/test_diffing/test_stack_differ.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
from sceptre.plan.actions import StackActions
from sceptre.stack import Stack

from botocore.exceptions import ClientError


class ImplementedStackDiffer(StackDiffer):
def __init__(self, command_capturer: Mock):
Expand Down Expand Up @@ -224,14 +226,22 @@ def test_diff__deployed_stack_exists__returns_is_deployed_as_true(self):
assert diff.is_deployed is True

def test_diff__deployed_stack_does_not_exist__returns_is_deployed_as_false(self):
self.actions.describe.return_value = self.actions.describe.side_effect = None
self.actions.describe.side_effect = ClientError(
{"Error": {"Code": "Whatevs", "Message": "Stack does not exist"}},
"DescribeStacks",
)
self.actions.describe.return_value = None
diff = self.differ.diff(self.actions)
assert diff.is_deployed is False

def test_diff__deployed_stack_does_not_exist__compares_none_to_generated_config(
self,
):
self.actions.describe.return_value = self.actions.describe.side_effect = None
self.actions.describe.side_effect = ClientError(
{"Error": {"Code": "Whatevs", "Message": "Stack does not exist"}},
"DescribeStacks",
)
self.actions.describe.return_value = None
self.differ.diff(self.actions)

self.command_capturer.compare_stack_configurations.assert_called_with(
Expand Down