Skip to content

Commit

Permalink
[Resolves #1388] Handle failures gracefully in stack outputs
Browse files Browse the repository at this point in the history
This adds exception handling in the case of failures to parse the given
arguments to !stack_output and !stack_output_external.
  • Loading branch information
alex-harvey-z3q committed Nov 27, 2023
1 parent 763d9f2 commit 67d40d4
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
42 changes: 31 additions & 11 deletions sceptre/resolvers/stack_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

from botocore.exceptions import ClientError

from sceptre.exceptions import DependencyStackMissingOutputError, StackDoesNotExistError
from sceptre.exceptions import DependencyStackMissingOutputError, StackDoesNotExistError, \
SceptreException

from sceptre.helpers import normalise_path, sceptreise_path
from sceptre.resolvers import Resolver

Expand Down Expand Up @@ -108,7 +110,11 @@ def setup(self):
"""
Adds dependency to a Stack.
"""
dep_stack_name, self.output_key = self.argument.split("::")
try:
dep_stack_name, self.output_key = self.argument.split("::")
except ValueError as err:
raise SceptreException("StackOutput argument should match STACK_NAME::OUTPUT_KEY") from err

self.dependency_stack_name = sceptreise_path(normalise_path(dep_stack_name))
self.stack.dependencies.append(self.dependency_stack_name)

Expand All @@ -120,14 +126,16 @@ def resolve(self):
:rtype: str
"""
self.logger.debug("Resolving Stack output: {0}".format(self.argument))

friendly_stack_name = self.dependency_stack_name.replace(TEMPLATE_EXTENSION, "")

stack = next(
stack
for stack in self.stack.dependencies
if stack.name == friendly_stack_name
)
try:
stack = next(
stack
for stack in self.stack.dependencies
if stack.name == friendly_stack_name
)
except StopIteration as err:
raise SceptreException(f"Stack '{friendly_stack_name}' not found in dependencies") from err

stack_name = "-".join(
[stack.project_code, friendly_stack_name.replace("/", "-")]
Expand Down Expand Up @@ -170,10 +178,22 @@ def resolve(self):

stack_argument = arguments[0]
if len(arguments) > 1:
extra_args = arguments[1].split("::", 2)
profile, region, sceptre_role = extra_args + (3 - len(extra_args)) * [None]
try:
extra_args = arguments[1].split("::", 2)
profile, region, sceptre_role = extra_args + (3 - len(extra_args)) * [None]
except ValueError as err:
message = (
"!stack_output_external second arg should be "
"in the format 'profile::region::sceptre_role'"
)
raise SceptreException(message) from err

try:
dependency_stack_name, output_key = stack_argument.split("::")
except ValueError as err:
message = "!stack_output_external arg should match STACK_NAME::OUTPUT_KEY"
raise SceptreException(message) from err

dependency_stack_name, output_key = stack_argument.split("::")
return self._get_output_value(
dependency_stack_name,
output_key,
Expand Down
5 changes: 3 additions & 2 deletions tests/test_resolvers/test_stack_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from sceptre.exceptions import DependencyStackMissingOutputError
from sceptre.exceptions import StackDoesNotExistError
from sceptre.exceptions import SceptreException

from botocore.exceptions import ClientError

Expand Down Expand Up @@ -58,7 +59,7 @@ def test_resolver__badly_formatted(self, mock_get_output_value):

stack_output_resolver = StackOutput("not_a_valid_stack_output", stack)

with pytest.raises(ValueError, match="not enough values to unpack"):
with pytest.raises(SceptreException, match="STACK_NAME::OUTPUT_KEY"):
stack_output_resolver.setup()

@patch("sceptre.resolvers.stack_output.StackOutput._get_output_value")
Expand Down Expand Up @@ -191,7 +192,7 @@ def test_resolve__badly_formatted(self, mock_get_output_value):
"not_a_valid_stack_output", stack
)

with pytest.raises(ValueError, match="not enough values to unpack"):
with pytest.raises(SceptreException, match="STACK_NAME::OUTPUT_KEY"):
stack_output_external_resolver.resolve()

@patch("sceptre.resolvers.stack_output.StackOutputExternal._get_output_value")
Expand Down

0 comments on commit 67d40d4

Please sign in to comment.