def test_delete_stacks_uses_the_correct_order(self,
                                                  custom_resource_mock,
                                                  stack_mock,
                                                  template_loader_mock,
                                                  dependency_resolver_mock,
                                                  parameter_resolver_mock,
                                                  cfn_mock):

        dependency_resolver_mock.return_value.get_stack_order.return_value = ['a', 'c']
        cfn_mock.return_value.get_stack_names.return_value = ['a', 'c']

        stack_a = CloudFormationStack('', [], 'a', '')
        stack_c = CloudFormationStack('', [], 'c', '')

        def stack_side_effect(*args):
            if args[2] == 'a':
                return stack_a
            if args[2] == 'c':
                return stack_c
            return None

        stack_mock.side_effect = stack_side_effect

        handler = StackActionHandler(Mock())
        handler.delete_stacks()

        expected_calls = [call(stack_c), call(stack_a)]
        six.assertCountEqual(self, expected_calls, cfn_mock.return_value.delete_stack.mock_calls)
    def test_create_or_update_tests_exits_gracefully_if_preexisting_stack_disappears(self,
                                                                                     custom_resource_mock,
                                                                                     stack_mock,
                                                                                     template_loader_mock,
                                                                                     dependency_resolver_mock,
                                                                                     parameter_resolver_mock,
                                                                                     cfn_mock,
                                                                                     config_mock):

        dependency_resolver_mock.return_value.get_stack_order.return_value = ['a', 'c']
        cfn_mock.return_value.get_stack_names.return_value = ['a', 'd']
        config_mock.return_value.tags.return_value = {}

        stack_a = CloudFormationStack('', [], 'a', '')
        stack_c = CloudFormationStack('', [], 'c', '')

        def stack_side_effect(*args, **kwargs):
            if kwargs['name'] == 'a':
                return stack_a
            if kwargs['name'] == 'c':
                return stack_c
            return None

        stack_mock.side_effect = stack_side_effect

        handler = StackActionHandler(config_mock)
        handler.create_or_update_stacks()

        # stack a needs update
        cfn_mock.return_value.validate_stack_is_ready_for_action.assert_called_once_with(stack_a)
        cfn_mock.return_value.update_stack.assert_called_once_with(stack_a)

        # stack c doesn't exist, must be created
        cfn_mock.return_value.create_stack.assert_called_once_with(stack_c)
    def test_delete_stacks(self,
                           custom_resource_mock,
                           stack_mock,
                           template_loader_mock,
                           dependency_resolver_mock,
                           parameter_resolver_mock,
                           cfn_mock):

        dependency_resolver_mock.return_value.get_stack_order.return_value = ['a', 'c']
        cfn_mock.return_value.get_stack_names.return_value = ['a', 'd']

        stack_a = CloudFormationStack('', [], 'a', '')
        stack_c = CloudFormationStack('', [], 'c', '')

        def stack_side_effect(*args):
            if args[2] == 'a':
                return stack_a
            if args[2] == 'c':
                return stack_c
            return None

        stack_mock.side_effect = stack_side_effect

        handler = StackActionHandler(Mock())
        handler.delete_stacks()

        cfn_mock.return_value.delete_stack.assert_called_once_with(stack_a)
    def test_delete_stacks(self, custom_resource_mock, stack_mock,
                           template_loader_mock, dependency_resolver_mock,
                           parameter_resolver_mock, cfn_mock):

        dependency_resolver_mock.return_value.get_stack_order.return_value = [
            'a', 'c'
        ]
        cfn_mock.return_value.get_stack_names.return_value = ['a', 'd']

        stack_a = CloudFormationStack('', [], 'a', '')
        stack_c = CloudFormationStack('', [], 'c', '')

        def stack_side_effect(*args, **kwargs):
            if args[2] == 'a':
                return stack_a
            if args[2] == 'c':
                return stack_c
            return None

        stack_mock.side_effect = stack_side_effect

        handler = StackActionHandler(Mock())
        handler.delete_stacks()

        cfn_mock.return_value.delete_stack.assert_called_once_with(stack_a)
    def test_delete_stacks_uses_the_correct_order(
            self, custom_resource_mock, stack_mock, template_loader_mock,
            dependency_resolver_mock, parameter_resolver_mock, cfn_mock):

        dependency_resolver_mock.return_value.get_stack_order.return_value = [
            'a', 'c'
        ]
        cfn_mock.return_value.get_stack_names.return_value = ['a', 'c']

        stack_a = CloudFormationStack('', [], 'a', '')
        stack_c = CloudFormationStack('', [], 'c', '')

        def stack_side_effect(*args, **kwargs):
            if args[2] == 'a':
                return stack_a
            if args[2] == 'c':
                return stack_c
            return None

        stack_mock.side_effect = stack_side_effect

        handler = StackActionHandler(Mock())
        handler.delete_stacks()

        expected_calls = [call(stack_c), call(stack_a)]
        six.assertCountEqual(self, expected_calls,
                             cfn_mock.return_value.delete_stack.mock_calls)
예제 #6
0
 def sync_stacks_with_parameters_overwrite(self, cli_params):
     config = Config(config_file=os.path.join(self.test_resources_dir,
                                              "stacks.yml"),
                     cli_params=cli_params)
     stack_handler = StackActionHandler(config)
     self.logger.info("Syncing stacks")
     stack_handler.create_or_update_stacks()
    def test_create_or_update_tests_exits_gracefully_if_preexisting_stack_disappears(
            self, custom_resource_mock, stack_mock, template_loader_mock,
            dependency_resolver_mock, parameter_resolver_mock, cfn_mock):

        dependency_resolver_mock.return_value.get_stack_order.return_value = [
            'a', 'c'
        ]
        cfn_mock.return_value.get_stack_names.return_value = ['a', 'd']

        stack_a = CloudFormationStack('', [], 'a', '')
        stack_c = CloudFormationStack('', [], 'c', '')

        def stack_side_effect(*args, **kwargs):
            if kwargs['name'] == 'a':
                return stack_a
            if kwargs['name'] == 'c':
                return stack_c
            return None

        stack_mock.side_effect = stack_side_effect

        handler = StackActionHandler(Mock())
        handler.create_or_update_stacks()

        # stack a needs update
        cfn_mock.return_value.validate_stack_is_ready_for_action.assert_called_once_with(
            stack_a)
        cfn_mock.return_value.update_stack.assert_called_once_with(stack_a)

        # stack c doesn't exist, must be created
        cfn_mock.return_value.create_stack.assert_called_once_with(stack_c)
def get_stack_action_handler(domain,
                             verification_token=None,
                             dkim_tokens=None):
    verification_token = verification_token or ""
    dkim_tokens = dkim_tokens or ["", "", ""]

    return StackActionHandler(config=Config(
        config_dict={
            'region': REGION,
            'stacks': {
                get_dns_stack_name(domain): {
                    'template-url': recordset_template.name,
                    'parameters': {
                        'dnsBaseName': domain + ".",
                        'dkimOne': dkim_tokens[0],
                        'dkimTwo': dkim_tokens[1],
                        'dkimThree': dkim_tokens[2],
                        'verifyTxt': verification_token
                    }
                },
                get_bucket_stack_name(domain): {
                    'template-url': ses_template.name,
                }
            }
        }))
예제 #9
0
def sync(config, parameter, suffix, debug, confirm, yes):
    confirm = confirm or yes
    if debug:
        LOGGER.setLevel(logging.DEBUG)
        boto3.set_stream_logger(name='boto3', level=logging.DEBUG)
        boto3.set_stream_logger(name='botocore', level=logging.DEBUG)
    else:
        LOGGER.setLevel(logging.INFO)

    if not confirm:
        check_update_available()
        click.confirm(
            'This action will modify AWS infrastructure in account: {0}\nAre you sure?'
            .format(get_first_account_alias_or_account_id()),
            abort=True)

    try:

        config = Config(config_file=config,
                        cli_params=parameter,
                        stack_name_suffix=suffix)
        StackActionHandler(config).create_or_update_stacks()
    except CfnSphereException as e:
        LOGGER.error(e)
        if debug:
            LOGGER.exception(e)
        sys.exit(1)
    except Exception as e:
        LOGGER.error("Failed with unexpected error")
        LOGGER.exception(e)
        LOGGER.info(
            "Please report at https://github.com/cfn-sphere/cfn-sphere/issues!"
        )
        sys.exit(1)
예제 #10
0
def delete(config, suffix, debug, confirm, yes):
    confirm = confirm or yes
    if debug:
        LOGGER.setLevel(logging.DEBUG)
    else:
        LOGGER.setLevel(logging.INFO)

    if not confirm:
        check_update_available()
        click.confirm(
            'This action will delete all stacks in {0} from account: {1}\nAre you sure?'
            .format(config, get_first_account_alias_or_account_id()),
            abort=True)

    try:

        config = Config(config, stack_name_suffix=suffix)
        StackActionHandler(config).delete_stacks()
    except CfnSphereException as e:
        LOGGER.error(e)
        if debug:
            LOGGER.exception(e)
        sys.exit(1)
    except Exception as e:
        LOGGER.error("Failed with unexpected error")
        LOGGER.exception(e)
        LOGGER.info(
            "Please report at https://github.com/cfn-sphere/cfn-sphere/issues!"
        )
        sys.exit(1)
    def setUpClass(cls):
        test_resources_dir = get_resources_dir()
        cls.cfn_conn = cloudformation.connect_to_region("eu-west-1")
        cls.config = Config(config_file=os.path.join(test_resources_dir, "stacks.yml"))
        cls.stack_handler = StackActionHandler(cls.config)

        LOGGER.info("Syncing stacks")
        cls.stack_handler.create_or_update_stacks()
예제 #12
0
파일: cli.py 프로젝트: rayoogmy/cfn-square
def execute_change_set(change_set, debug, confirm, yes, region):
    confirm = confirm or yes
    if debug:
        LOGGER.setLevel(logging.DEBUG)
        boto3.set_stream_logger(name='boto3', level=logging.DEBUG)
        boto3.set_stream_logger(name='botocore', level=logging.DEBUG)
    else:
        LOGGER.setLevel(logging.INFO)

    if not confirm:
        check_update_available()
        click.confirm(
            'This action will modify AWS infrastructure in account: {0}\nAre you sure?'
            .format(get_first_account_alias_or_account_id()),
            abort=True)

    try:
        matched = re.match(r'arn:aws:cloudformation:([^:]+):.*', change_set)

        if matched:
            LOGGER.info('ARN detected, setting region to {}'.format(
                matched.group(1)))
            region = matched.group(1)

        config_dict = {'change_set': change_set, 'region': str(region)}
        config = Config(config_dict=config_dict)
        StackActionHandler(config).execute_change_set()
    except CfnSphereException as e:
        LOGGER.error(e)
        if debug:
            LOGGER.exception(e)
        sys.exit(1)
    except Exception as e:
        LOGGER.error("Failed with unexpected error")
        LOGGER.exception(e)
        LOGGER.info(
            "Please report at https://github.com/KCOM-Enterprise/cfn-square/issues!"
        )
        sys.exit(1)
 def sync_stacks_with_parameters_overwrite(self, cli_params):
     config = Config(config_file=os.path.join(self.test_resources_dir, "stacks.yml"), cli_params=cli_params)
     stack_handler = StackActionHandler(config)
     self.logger.info("Syncing stacks")
     stack_handler.create_or_update_stacks()
 def sync_stacks(self):
     stack_handler = StackActionHandler(self.config)
     self.logger.info("Syncing stacks")
     stack_handler.create_or_update_stacks()
예제 #15
0
 def delete_stacks(self):
     StackActionHandler(self.config).delete_stacks()
     self.verify_stacks_are_gone()
예제 #16
0
 def sync_stacks(self):
     stack_handler = StackActionHandler(self.config)
     self.logger.info("Syncing stacks")
     stack_handler.create_or_update_stacks()