def _get_simplified_status(status): """ Returns the simplified Stack Status. The simplified Stack status is represented by the struct ``sceptre.StackStatus()`` and can take one of the following options: * complete * in_progress * failed :param status: The CloudFormation Stack status to simplify. :type status: str :returns: The Stack's simplified status :rtype: sceptre.stack_status.StackStatus """ if status.endswith("ROLLBACK_COMPLETE"): return StackStatus.FAILED elif status.endswith("_COMPLETE"): return StackStatus.COMPLETE elif status.endswith("_IN_PROGRESS"): return StackStatus.IN_PROGRESS elif status.endswith("_FAILED"): return StackStatus.FAILED else: raise UnknownStackStatusError("{0} is unknown".format(status))
def launch(self): """ Launches the Stack. If the Stack status is create_failed or rollback_complete, the Stack is deleted. Launch then tries to create or update the Stack, depending if it already exists. If there are no updates to be performed, launch exits gracefully. :returns: The Stack's status. :rtype: sceptre.stack_status.StackStatus """ self._protect_execution() self.logger.info("%s - Launching Stack", self.stack.name) try: existing_status = self._get_status() except StackDoesNotExistError: existing_status = "PENDING" self.logger.info( "%s - Stack is in the %s state", self.stack.name, existing_status ) if existing_status == "PENDING": status = self.create() elif existing_status in ["CREATE_FAILED", "ROLLBACK_COMPLETE"]: self.delete() status = self.create() elif existing_status.endswith("COMPLETE"): try: status = self.update() except botocore.exceptions.ClientError as exp: error_message = exp.response["Error"]["Message"] if error_message == "No updates are to be performed.": self.logger.info( "%s - No updates to perform.", self.stack.name ) status = StackStatus.COMPLETE else: raise status = status elif existing_status.endswith("IN_PROGRESS"): self.logger.info( "%s - Stack action is already in progress state and cannot " "be updated", self.stack.name ) status = StackStatus.IN_PROGRESS elif existing_status.endswith("FAILED"): status = StackStatus.FAILED raise CannotUpdateFailedStackError( "'{0}' is in a the state '{1}' and cannot be updated".format( self.stack.name, existing_status ) ) else: raise UnknownStackStatusError( "{0} is unknown".format(existing_status) ) return status
def launch(self, wait_action): """ Launches the Stack. If the Stack status is create_failed or rollback_complete, the Stack is deleted. Launch then tries to create or update the Stack, depending if it already exists. If there are no updates to be performed, launch exits gracefully. :returns: The Stack's status. :rtype: sceptre.stack_status.StackStatus """ self._protect_execution() self.logger.info("%s - Launching Stack", self.stack.name) try: existing_status = self._get_status() except StackDoesNotExistError: existing_status = "PENDING" self.logger.info("%s - Stack is in the %s state", self.stack.name, existing_status) if existing_status.endswith( "UPDATE_IN_PROGRESS") or existing_status.endswith( "CREATE_IN_PROGRESS") or existing_status.endswith( "UPDATE_ROLLBACK_IN_PROGRESS" ) or existing_status.endswith( "CLEANUP_IN_PROGRESS") or existing_status.endswith( "DELETE_IN_PROGRESS") or existing_status.endswith( "ROLLBACK_IN_PROGRESS"): # wait until it finalize then lets proceed.. self.logger.info( "%s - Stack is %s, waiting before launching stack action.", self.stack.name, existing_status) existing_status = self._wait_for_completion() try: existing_status = self._get_status() time.sleep(4) existing_status = self._get_status() except StackDoesNotExistError: existing_status = "PENDING" self.logger.info( "%s - Stack is now in the following state: %s. Will proceed with command action.", self.stack.name, existing_status) if existing_status.endswith("ROLLBACK_COMPLETE"): existing_status = "PENDING" elif existing_status.endswith("DELETE_IN_PROGRESS"): # Force dlete / create existing_status = "PENDING" elif existing_status.endswith("CREATE_IN_PROGRESS"): existing_status = "CREATE_IN_PROGRESS" elif existing_status.endswith("UPDATE_IN_PROGRESS"): existing_status = "UPDATE_IN_PROGRESS" else: existing_status = "UPDATE_ROLLBACK_COMPLETE" if existing_status == "PENDING": status = self.create(wait_action) elif existing_status in [ "CREATE_FAILED", "ROLLBACK_COMPLETE", "ROLLBACK_FAILED" ]: self.delete() status = self.create(wait_action) elif existing_status.endswith("COMPLETE") or ( existing_status.endswith("IN_PROGRESS") and wait_action == 'wait_only'): try: status = self.update(wait_action) except botocore.exceptions.ClientError as exp: error_message = exp.response["Error"]["Message"] if error_message == "No updates are to be performed.": self.logger.info("%s - No updates to perform.", self.stack.name) status = StackStatus.COMPLETE else: raise # status = self.create() #elif existing_status.endswith("COMPLETE"): # status = self.update() elif existing_status.endswith("IN_PROGRESS"): self.logger.info( "%s - Stack action is already in progress state and cannot " "be updated", self.stack.name) status = StackStatus.IN_PROGRESS elif existing_status.endswith("FAILED"): status = StackStatus.FAILED raise CannotUpdateFailedStackError( "'{0}' is in a the state '{1}' and cannot be updated".format( self.stack.name, existing_status)) else: raise UnknownStackStatusError( "{0} is unknown".format(existing_status)) return status