diff --git a/stacker/actions/build.py b/stacker/actions/build.py index c4ef29857..bd2b91714 100644 --- a/stacker/actions/build.py +++ b/stacker/actions/build.py @@ -310,8 +310,11 @@ def _launch_stack(self, stack, **kwargs): reason = old_status.reason if 'rolling' in reason: reason = reason.replace('rolling', 'rolled') - + status_reason = provider.get_rollback_status_reason(stack.fqn) + logger.info( + "%s Stack Roll Back Reason: " + status_reason, stack.fqn) return FailedStatus(reason) + elif provider.is_stack_completed(provider_stack): stack.set_outputs( provider.get_output_dict(provider_stack)) diff --git a/stacker/providers/aws/default.py b/stacker/providers/aws/default.py index dd4d16a22..808531346 100644 --- a/stacker/providers/aws/default.py +++ b/stacker/providers/aws/default.py @@ -624,7 +624,7 @@ def _tail_print(e): e['ResourceType'], e['EventId'])) - def get_events(self, stack_name): + def get_events(self, stack_name, chronological=True): """Get the events in batches and return in chronological order""" next_token = None event_list = [] @@ -642,7 +642,25 @@ def get_events(self, stack_name): if next_token is None: break time.sleep(GET_EVENTS_SLEEP) - return reversed(sum(event_list, [])) + if chronological: + return reversed(sum(event_list, [])) + else: + return sum(event_list, []) + + def get_rollback_status_reason(self, stack_name): + """Process events and returns latest roll back reason""" + event = next((item for item in self.get_events(stack_name, + False) if item["ResourceStatus"] == + "UPDATE_ROLLBACK_IN_PROGRESS"), None) + if event: + reason = event["ResourceStatusReason"] + return reason + else: + event = next((item for item in self.get_events(stack_name) + if item["ResourceStatus"] == + "ROLLBACK_IN_PROGRESS"), None) + reason = event["ResourceStatusReason"] + return reason def tail(self, stack_name, cancel, log_func=_tail_print, sleep_time=5, include_initial=True): diff --git a/stacker/tests/actions/test_build.py b/stacker/tests/actions/test_build.py index 253a8cf12..018101401 100644 --- a/stacker/tests/actions/test_build.py +++ b/stacker/tests/actions/test_build.py @@ -244,10 +244,15 @@ def get_stack(name, *args, **kwargs): 'Outputs': [], 'Tags': []} + def get_events(name, *args, **kwargs): + return [{'ResourceStatus': 'ROLLBACK_IN_PROGRESS', + 'ResourceStatusReason': 'CFN fail'}] + patch_object(self.provider, 'get_stack', side_effect=get_stack) patch_object(self.provider, 'update_stack') patch_object(self.provider, 'create_stack') patch_object(self.provider, 'destroy_stack') + patch_object(self.provider, 'get_events', side_effect=get_events) patch_object(self.build_action, "s3_stack_push")