Skip to content

Commit

Permalink
Fix update command with change sets for multiple stacks
Browse files Browse the repository at this point in the history
Previously the update command would exit if any change sets status
was not equal to READY. However, when a stack does not contain
any updates, it will not be READY since there is nothing to execute.
This should not prevent other change sets to be executed.

[Resolves Sceptre#723]
  • Loading branch information
henrist authored and harkylton committed Jan 13, 2022
1 parent b44797a commit 5e1efe5
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
23 changes: 19 additions & 4 deletions sceptre/cli/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,31 +52,46 @@ def update_command(ctx, path, change_set, verbose, yes):
plan = SceptrePlan(context)

if change_set:
delete_change_set = True

change_set_name = "-".join(["change-set", uuid1().hex])
plan.create_change_set(change_set_name)
try:
# Wait for change set to be created
statuses = plan.wait_for_cs_completion(change_set_name)
# Exit if change set fails to create
atleast_one_ready = False
for status in list(statuses.values()):
if status != StackChangeSetStatus.READY:
if status != StackChangeSetStatus.READY \
and status != StackChangeSetStatus.NO_CHANGES:
# TODO: Print an informative message to the user.
exit(1)
if status == StackChangeSetStatus.READY:
atleast_one_ready = True

if not atleast_one_ready:
write("No changes detected", context.output_format)
exit(0)

# Describe changes
descriptions = plan.describe_change_set(change_set_name)
for description in list(descriptions.values()):
status = description.get("Status")
reason = description.get("StatusReason")
if status == "FAILED" and "submitted information didn't contain changes" in reason:
continue
if not verbose:
description = simplify_change_set_description(description)
write(description, context.output_format)

# Execute change set if happy with changes
if yes or click.confirm("Proceed with stack update?"):
plan.execute_change_set(change_set_name)
except Exception as e:
raise e
delete_change_set = False
finally:
# Clean up by deleting change set
plan.delete_change_set(change_set_name)
if delete_change_set:
plan.delete_change_set(change_set_name)
else:
confirmation("update", yes, command_path=path)
responses = plan.update()
Expand Down
7 changes: 7 additions & 0 deletions sceptre/plan/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,7 @@ def _get_cs_status(self, change_set_name):
cs_description = self.describe_change_set(change_set_name)

cs_status = cs_description["Status"]
cs_reason = cs_description.get("StatusReason")
cs_exec_status = cs_description["ExecutionStatus"]
possible_statuses = [
"CREATE_PENDING", "CREATE_IN_PROGRESS",
Expand Down Expand Up @@ -915,6 +916,12 @@ def _get_cs_status(self, change_set_name):
cs_exec_status in ["UNAVAILABLE", "AVAILABLE"]
):
return StackChangeSetStatus.PENDING
elif (
cs_status == "FAILED" and
cs_reason is not None and
"submitted information didn't contain changes" in cs_reason
):
return StackChangeSetStatus.NO_CHANGES
elif (
cs_status in ["DELETE_COMPLETE", "FAILED"] or
cs_exec_status in [
Expand Down
1 change: 1 addition & 0 deletions sceptre/stack_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ class StackChangeSetStatus(object):
PENDING = "pending"
READY = "ready"
DEFUNCT = "defunct"
NO_CHANGES = "no changes"
11 changes: 11 additions & 0 deletions tests/test_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,17 @@ def test_get_cs_status_handles_all_statuses(
)
assert response == returns[i]

mock_describe_change_set.return_value = {
"Status": "FAILED",
"StatusReason": "The submitted information didn't contain changes. "
"Submit different information to create a change set.",
"ExecutionStatus": "UNAVAILABLE"
}
response = self.actions._get_cs_status(
sentinel.change_set_name
)
assert response == scss.NO_CHANGES

for status in return_values['Status']:
mock_describe_change_set.return_value = {
"Status": status,
Expand Down

0 comments on commit 5e1efe5

Please sign in to comment.