Пример #1
0
    def describe_stack_set_operation(self):
        self.logger.info("Executing: " + self.__class__.__name__ + "/" +
                         inspect.stack()[0][3])
        self.logger.info(self.params)
        self.event.update({'RetryDeleteFlag': False})

        stack_set = StackSet(self.logger)
        response = stack_set.describe_stack_set_operation(
            self.params.get('StackSetName'), self.event.get('OperationId'))
        self.logger.info(response)
        operation_status = response.get('StackSetOperation', {}).get('Status')
        self.logger.info("Operation Status: {}".format(operation_status))
        if operation_status == 'FAILED':
            account_id = self.params.get('AccountList')[0] \
                            if type(self.params.get('AccountList')) is list \
                            else None
            if account_id:
                for region in self.params.get('RegionList'):
                    self.logger.info("Account: {} - describing stack "
                                     "instance in {} region".format(
                                         account_id, region))
                    try:
                        resp = stack_set.describe_stack_instance(
                            self.params.get('StackSetName'), account_id,
                            region)
                        self.event.update({
                            region:
                            resp.get('StackInstance', {}).get('StatusReason')
                        })
                    except ClientError as e:
                        # When CFN has triggered StackInstance delete and
                        # the SCP is still attached (due to race condition)
                        # , then it fails to delete the stack and StackSet
                        # throws the StackInstanceNotFoundException
                        # exception back, the CFN stack in target account
                        # ends up with 'DELETE_FAILED' state
                        # so it should try again
                        if e.response['Error']['Code'] ==  \
                            'StackInstanceNotFoundException' and \
                                self.event.get('RequestType') == 'Delete':
                            self.logger.exception(
                                "Caught exception"
                                "'StackInstanceNotFoundException',"
                                "sending the flag to go back to "
                                " Delete Stack Instances stage...")
                            self.event.update({'RetryDeleteFlag': True})

        operation_status = response.get('StackSetOperation', {}).get('Status')
        self.event.update({'OperationStatus': operation_status})
        return self.event
Пример #2
0
    def export_cfn_output(self):
        self.logger.info("Executing: " + self.__class__.__name__ + "/" +
                         inspect.stack()[0][3])
        self.logger.info(self.params)

        regions = self.params.get('RegionList')
        accounts = self.params.get('AccountList')
        stack_set_name = self.params.get('StackSetName')
        stack_set = StackSet(self.logger)

        if len(accounts) == 0 or len(regions) == 0:
            self.logger.info("Either AccountList or RegionList empty; so "
                             "skipping the export_cfn_output ")
            return self.event

        self.logger.info("Picking the first account from AccountList")
        account = accounts[0]

        self.logger.info("Picking the first region from RegionList")
        region = regions[0]

        # First retrieve the Stack ID from the target account,
        # region deployed via the StackSet
        response = stack_set.describe_stack_instance(stack_set_name, account,
                                                     region)

        stack_id, stack_name = self._retrieve_stack_info(
            response, stack_set_name, account, region)

        # instantiate STS class
        _assume_role = AssumeRole()
        cfn = Stacks(self.logger,
                     region,
                     credentials=_assume_role(self.logger, account))
        response = cfn.describe_stacks(stack_id)
        stacks = response.get('Stacks')

        if stacks is not None and type(stacks) is list:
            for stack in stacks:
                self._update_event_with_stack_output(stack, stack_id, account,
                                                     region)
        return self.event