Esempio n. 1
0
def test_describes_change_set(session, change_set):
    client_mock = Mock()
    session.return_value.client.return_value = client_mock
    cli.main(['describe', '--stack', STACK])
    session.return_value.client.assert_called_with('cloudformation')
    change_set.assert_called_with(stack=STACK, client=client_mock)
    change_set.return_value.describe.assert_called_once()
Esempio n. 2
0
def test_template_calls_template_with_yaml(tmpdir, logger):
    with Path(tmpdir):
        with open('test.template.json', 'w') as f:
            f.write('{"Description": "{{ \'test\' | title }}"}')
        cli.main(['template', '--yaml'])
        logger.info.assert_called()
        assert {"Description": "Test"} == yaml.safe_load(logger.info.call_args[0][0])
Esempio n. 3
0
def test_with_organization_variables(aws_client, tmpdir, logger, paginators):
    aws_client.get_paginator.side_effect = paginators(list_accounts=[ACCOUNTS])
    aws_client.describe_regions.return_value = EC2_REGIONS
    aws_client.get_caller_identity.return_value = {'Account': '1234'}
    example = '{"Resources": {"ModuleAccounts": {{ AWSAccounts | tojson }}, "ModuleSubAccounts": {{ AWSSubAccounts | tojson }}, "ModuleRegions": {{ AWSRegions | tojson }}, "ModuleMainAccount": {{ AWSMainAccount | tojson }}}}'
    with Path(tmpdir):
        os.mkdir('moduledir')
        with open('moduledir/test.template.json', 'w') as f:
            f.write(example)
        with open('test.template.json', 'w') as f:
            f.write(
                '{"Resources": {"AccountsRegionsTest": {"From": "Moduledir"}, "Accounts": {{ AWSAccounts | tojson}}, "SubAccounts": {{ AWSSubAccounts | tojson}}, "Regions": {{ AWSRegions | tojson }} }}')
        cli.main(['template', '--organization-variables'])
        logger.info.assert_called()
        output = logger.info.call_args[0][0]

        actual = yaml.safe_load(output)
        expected = {'Resources': {'Accounts': [{'Email': '*****@*****.**', 'Id': '1234', 'Name': 'TestName1'},
                                               {'Email': '*****@*****.**', 'Id': '5678', 'Name': 'TestName2'}],
                                  'SubAccounts': [{'Email': '*****@*****.**', 'Id': '5678', 'Name': 'TestName2'}],
                                  'ModuleAccounts': [{'Email': '*****@*****.**', 'Id': '1234', 'Name': 'TestName1'},
                                                     {'Email': '*****@*****.**', 'Id': '5678', 'Name': 'TestName2'}],
                                  'ModuleSubAccounts': [
                                      {'Email': '*****@*****.**', 'Id': '5678', 'Name': 'TestName2'}],
                                  'ModuleMainAccount': {'Email': '*****@*****.**',
                                                        'Id': '1234',
                                                        'Name': 'TestName1'},
                                  'ModuleRegions': ['us-west-1', 'us-west-2'], 'Regions': ['us-west-1', 'us-west-2']}}
    assert actual == expected
Esempio n. 4
0
def test_remove_stack_set_instances(client, loader, wait, input):
    cli.main([
        'stack-set',
        'remove-instances',
        '--stack-set',
        STACK,
        '--accounts',
        '123456789',
        '987654321',
        '--regions',
        'eu-central-1',
        'eu-west-1',
        '--retain',
        '--region-order',
        'eu-central-1',
        'eu-west-1',
        '--max-concurrent-percentage',
        '1',
        '--failure-tolerance-percentage',
        '1',
    ])

    client.delete_stack_instances.assert_called_with(
        StackSetName=STACK,
        Accounts=['123456789', '987654321'],
        Regions=['eu-central-1', 'eu-west-1'],
        RetainStacks=True,
        OperationPreferences={
            'RegionOrder': ['eu-central-1', 'eu-west-1'],
            'FailureTolerancePercentage': 1,
            'MaxConcurrentPercentage': 1
        })

    wait.assert_called_with(STACK, OPERATION_ID)
Esempio n. 5
0
def test_update_stack_set_with_main_account(session, client, logger, tmpdir,
                                            input, compare, wait):
    client.update_stack_set.return_value = {'OperationId': '12345'}
    accountid = str(uuid4())
    client.get_caller_identity.return_value = {'Account': accountid}
    with Path(tmpdir):
        with open('test.template.json', 'w') as f:
            f.write('')
        cli.main([
            'stack-set', 'update', '--stack-set', STACK,
            '--main-account-parameter'
        ])

    session.return_value.client.assert_any_call('sts')
    session.return_value.client.assert_any_call('cloudformation')

    client.update_stack_set.assert_called_with(StackSetName=STACK,
                                               TemplateBody=dump_template({
                                                   'Parameters': {
                                                       'MainAccount': {
                                                           'Type': 'String',
                                                           'Default': accountid
                                                       }
                                                   }
                                               }))
Esempio n. 6
0
def test_add_stack_set_instances_with_operation_preferences(
        client, loader, wait, input):
    cli.main([
        'stack-set',
        'add-instances',
        '--accounts',
        '123456789',
        '987654321',
        '--regions',
        'eu-central-1',
        'eu-west-1',
        '--stack-set',
        STACK,
        '--max-concurrent-percentage',
        '1',
        '--failure-tolerance-percentage',
        '1',
    ])

    client.create_stack_instances.assert_called_with(
        StackSetName=STACK,
        Accounts=['123456789', '987654321'],
        Regions=['eu-central-1', 'eu-west-1'],
        OperationPreferences={
            'FailureTolerancePercentage': 1,
            'MaxConcurrentPercentage': 1
        })
Esempio n. 7
0
def test_loads_empty_config_file(mocker, tmpdir, session):
    stacks = mocker.patch('formica.cli.stacks')
    file_name = 'test.config.yaml'
    with Path(tmpdir):
        with open(file_name, 'w') as f:
            f.write('')
        cli.main(['stacks', '-c', file_name])
Esempio n. 8
0
def test_print_stacks(session, logger):
    client_mock = Mock()
    session.return_value.client.return_value = client_mock
    client_mock.get_paginator.return_value.paginate.return_value = [
        LIST_STACK_RESOURCES
    ]
    cli.main(['resources', '--stack', STACK])

    client_mock.get_paginator.assert_called_with('list_stack_resources')
    client_mock.get_paginator.return_value.paginate.assert_called_with(
        StackName=STACK)

    logger.info.assert_called_with(mock.ANY)
    args = logger.info.call_args[0]

    to_search = []
    to_search.extend(RESOURCE_HEADERS)
    to_search.extend(['AWS::Route53::HostedZone'])
    to_search.extend(['FlomotlikMe'])
    to_search.extend(['CREATE_COMPLETE'])
    to_search.extend(['ZAYGDOKFPYFK6'])
    change_set_output = args[0]
    for term in to_search:
        assert term in change_set_output
    assert 'None' not in change_set_output
Esempio n. 9
0
def test_create_stack_set(client, logger, loader):
    cli.main([
        'stack-set',
        'create',
        '--stack-set',
        STACK,
        '--parameters',
        'A=B',
        'B=C',
        '--tags',
        'A=B',
        'B=C',
        '--capabilities',
        'CAPABILITY_IAM',
        '--execution-role-name',
        'ExecutionRole',
        '--administration-role-arn',
        'AdministrationRole',
    ])

    client.create_stack_set.assert_called_with(
        StackSetName=STACK,
        TemplateBody=TEMPLATE,
        Parameters=CLOUDFORMATION_PARAMETERS,
        Tags=CLOUDFORMATION_TAGS,
        Capabilities=['CAPABILITY_IAM'],
        ExecutionRoleName='ExecutionRole',
        AdministrationRoleARN='AdministrationRole')
Esempio n. 10
0
def test_new_uses_tags_for_creation(change_set, client, loader):
    loader.return_value.template.return_value = TEMPLATE
    cli.main([
        'new',
        '--stack',
        STACK,
        '--tags',
        'A=C',
        'C=D',
        '--profile',
        PROFILE,
        '--region',
        REGION,
    ])
    change_set.assert_called_with(stack=STACK, nested_change_sets=False)
    change_set.return_value.create.assert_called_once_with(
        template=TEMPLATE,
        change_set_type='CREATE',
        parameters={},
        tags={
            'A': 'C',
            'C': 'D'
        },
        capabilities=None,
        resource_types=False,
        role_arn=None,
        s3=False)
Esempio n. 11
0
def test_does_not_execute_changeset_if_in_failed_state(stack_waiter, client):
    client.describe_change_set.return_value = {'Status': 'FAILED'}
    client.describe_stack_events.return_value = {'StackEvents': [{'EventId': EVENT_ID}]}
    client.describe_stacks.return_value = {'Stacks': [{'StackId': STACK_ID}]}

    with pytest.raises(SystemExit):
        cli.main(['deploy', '--stack', STACK])
    client.execute_change_set.assert_not_called()
Esempio n. 12
0
def test_exception_with_failed_yaml_syntax(mocker, tmpdir, session, logger):
    file_name = 'test.config.yaml'
    with Path(tmpdir):
        with open(file_name, 'w') as f:
            f.write("stacks: somestack\nprofile testprofile")
        with pytest.raises(SystemExit):
            cli.main(['stacks', '-c', file_name])
        logger.error.assert_called()
Esempio n. 13
0
def test_change_tests_tag_format(capsys):
    with pytest.raises(SystemExit) as pytest_wrapped_e:
        cli.main(['change', '--stack', STACK, '--parameters', 'A=B', '--profile', PROFILE, '--region', REGION,
                  '--tags', 'CD'])
    out, err = capsys.readouterr()

    assert "argument --tags: CD needs to be in format KEY=VALUE" in err
    assert pytest_wrapped_e.value.code == 2
Esempio n. 14
0
def test_wait(client, stack_waiter):
    client.describe_stacks.return_value = {'Stacks': [{'StackId': STACK_ID}]}
    client.describe_stack_events.return_value = {
        'StackEvents': [{
            'EventId': EVENT_ID
        }]
    }
    cli.main(['wait', '--stack', STACK])
Esempio n. 15
0
def test_change_uses_capabilities_for_creation(change_set, client, loader):
    loader.return_value.template.return_value = TEMPLATE
    cli.main(['change', '--stack', STACK, '--capabilities', 'A', 'B'])
    change_set.assert_called_with(stack=STACK, client=client)
    change_set.return_value.create.assert_called_once_with(template=TEMPLATE, change_set_type='UPDATE',
                                                           parameters={},
                                                           tags={}, capabilities=['A', 'B'], role_arn=None, s3=False,
                                                           resource_types=False)
Esempio n. 16
0
def test_change_with_role_arn(change_set, client, loader):
    loader.return_value.template.return_value = TEMPLATE
    cli.main(['change', '--stack', STACK, '--role-arn', ROLE_ARN])
    change_set.assert_called_with(stack=STACK, client=client)
    change_set.return_value.create.assert_called_once_with(template=TEMPLATE, change_set_type='UPDATE',
                                                           parameters={},
                                                           tags={}, capabilities=None, role_arn=ROLE_ARN, s3=False,
                                                           resource_types=False)
Esempio n. 17
0
def test_executes_change_set_with_timeout(stack_waiter, client):
    client.describe_change_set.return_value = {'Status': 'CREATE_COMPLETE'}
    client.describe_stack_events.return_value = {'StackEvents': [{'EventId': EVENT_ID}]}
    client.describe_stacks.return_value = {'Stacks': [{'StackId': STACK_ID}]}

    cli.main(['deploy', '--stack', STACK, '--profile', PROFILE, '--region', REGION, '--timeout', '15'])
    stack_waiter.assert_called_with(STACK_ID, timeout=15)
    stack_waiter.return_value.wait.assert_called_with(EVENT_ID)
Esempio n. 18
0
def test_cancel_stack_update(client, stack_waiter):
    client.describe_stacks.return_value = {'Stacks': [{'StackId': STACK_ID}]}
    client.describe_stack_events.return_value = {
        'StackEvents': [{
            'EventId': EVENT_ID
        }]
    }
    cli.main(['cancel', '--stack', STACK])
    client.cancel_update_stack.assert_called_with(StackName=STACK)
Esempio n. 19
0
def test_exception_with_wrong_config_type(mocker, tmpdir, session, logger):
    file_name = 'test.config.yaml'
    with Path(tmpdir):
        with open(file_name, 'w') as f:
            f.write(yaml.dump({'stack': ['test', 'test2']}))
        with pytest.raises(SystemExit):
            cli.main(['stacks', '-c', file_name])
        logger.error.assert_called_with(
            'Config file parameter stack needs to be of type str')
Esempio n. 20
0
def test_fails_if_no_stack_given(logger):
    with pytest.raises(SystemExit) as pytest_wrapped_e:
        cli.main(['deploy'])
    assert pytest_wrapped_e.value.code == 1

    logger.error.assert_called()
    out = logger.error.call_args[0][0]
    assert '--stack' in out
    assert '--config-file' in out
Esempio n. 21
0
def test_remove_stack_set(client, loader):
    cli.main([
        'stack-set',
        'remove',
        '--stack-set',
        STACK,
    ])

    client.delete_stack_set.assert_called_with(StackSetName=STACK)
Esempio n. 22
0
def test_change_with_role_name_and_arn(change_set, client, loader):
    client.get_caller_identity.return_value = {'Account': ACCOUNT_ID}
    loader.return_value.template.return_value = TEMPLATE
    cli.main(['change', '--stack', STACK, '--role-name', 'UnusedRole', '--role-arn', ROLE_ARN])
    change_set.assert_called_with(stack=STACK, client=client)
    change_set.return_value.create.assert_called_once_with(template=TEMPLATE, change_set_type='UPDATE',
                                                           parameters={},
                                                           tags={}, capabilities=None, role_arn=ROLE_ARN, s3=False,
                                                           resource_types=False)
Esempio n. 23
0
def test_change_creates_update_change_set(change_set, client, loader):
    loader.return_value.template.return_value = TEMPLATE
    cli.main(['change', '--stack', STACK, '--profile', PROFILE, '--region', REGION])
    change_set.assert_called_with(stack=STACK, client=client)
    change_set.return_value.create.assert_called_once_with(template=TEMPLATE, change_set_type='UPDATE',
                                                           parameters={},
                                                           tags={}, capabilities=None, role_arn=None, s3=False,
                                                           resource_types=False)
    change_set.return_value.describe.assert_called_once()
Esempio n. 24
0
def test_diff_cli_with_vars(template, mocker):
    diff = mocker.patch('formica.diff.compare_stack')
    cli.main([
        'diff', '--stack', STACK, '--vars', 'V=1', '--parameters', 'P=2',
        '--tags', 'T=3'
    ])
    diff.assert_called_with(stack=STACK,
                            vars={'V': '1'},
                            parameters={'P': '2'},
                            tags={'T': '3'})
Esempio n. 25
0
def test_diff_cli_with_vars(mocker, session):
    aws = mocker.patch('formica.cli.AWS')
    aws.current_session.return_value = session

    diff = mocker.patch('formica.cli.Diff')

    cli.main(['diff', '--stack', STACK, '--vars', 'abc=def'])

    diff.assert_called_with(session)
    diff.return_value.run.assert_called_with(STACK, {'abc': 'def'})
Esempio n. 26
0
def test_diff_cli_call(template, mocker, client, session):
    diff = mocker.patch('formica.diff.compare_stack_set')
    cli.main([
        'stack-set', 'diff', '--stack-set', STACK, '--main-account-parameter'
    ])
    diff.assert_called_with(stack=STACK,
                            parameters={},
                            vars={},
                            tags={},
                            main_account_parameter=True)
Esempio n. 27
0
def test_exception_with_forbiddeng_config_argument(mocker, tmpdir, session,
                                                   logger):
    file_name = 'test.config.yaml'
    with Path(tmpdir):
        with open(file_name, 'w') as f:
            f.write(yaml.dump({'stacks': 'somestack'}))
        with pytest.raises(SystemExit):
            cli.main(['stacks', '-c', file_name])
        logger.error.assert_called_with(
            'Config file parameter stacks is not supported')
Esempio n. 28
0
def test_diff_cli_call(mocker, session):
    aws = mocker.patch('formica.cli.AWS')
    aws.current_session.return_value = session

    diff = mocker.patch('formica.cli.Diff')

    cli.main(['diff', '--stack', STACK])

    diff.assert_called_with(session)
    diff.return_value.run.assert_called_with(STACK, mocker.ANY)
Esempio n. 29
0
def test_does_not_execute_changeset_if_no_changes(stack_waiter, client):
    client.describe_change_set.return_value = {'Status': 'FAILED',
                                               "StatusReason": "The submitted information didn't contain changes. Submit different information to create a change set."}
    client.describe_stack_events.return_value = {'StackEvents': [{'EventId': EVENT_ID}]}
    client.describe_stacks.return_value = {'Stacks': [{'StackId': STACK_ID}]}

    cli.main(['deploy', '--stack', STACK])
    client.execute_change_set.assert_not_called()
    stack_waiter.assert_called_with(STACK_ID)
    stack_waiter.return_value.wait.assert_called_with(EVENT_ID)
Esempio n. 30
0
def test_new_tests_parameter_format(capsys):
    with pytest.raises(SystemExit) as pytest_wrapped_e:
        cli.main([
            'new', '--stack', STACK, '--parameters', 'A=B', 'CD', '--profile',
            PROFILE, '--region', REGION
        ])
    assert pytest_wrapped_e.value.code == 2
    out, err = capsys.readouterr()
    assert 'needs to be in format KEY=VALUE' in err
    assert pytest_wrapped_e.value.code == 2