Exemplo n.º 1
0
def test_do_not_remove_changeset_if_non_existent():
    cf_client_mock = Mock()
    change_set = ChangeSet(STACK, cf_client_mock)
    exception = ClientError(dict(Error=dict(Code='ChangeSetNotFound')), "DescribeChangeSet")
    cf_client_mock.describe_change_set.side_effect = exception
    change_set.remove_existing_changeset()
    cf_client_mock.delete_change_set.assert_not_called()
Exemplo n.º 2
0
def test_creates_and_removes_bucket_for_s3_flag(client, uuid):
    change_set = ChangeSet(STACK, client)

    change_set.create(template=TEMPLATE,
                      change_set_type=CHANGE_SET_TYPE,
                      s3=True)
    bucket_name = 'formica-deploy-{}'.format(UUID)
    bucket_path = '{}-template.json'.format(STACK)
    template_url = 'https://{}.s3.amazonaws.com/{}'.format(
        bucket_name, bucket_path)

    client.create_bucket.assert_called_with(
        Bucket=bucket_name,
        CreateBucketConfiguration=dict(LocationConstraint=REGION))
    client.put_object.assert_called_with(Bucket=bucket_name,
                                         Key=bucket_path,
                                         Body=TEMPLATE)

    client.create_change_set.assert_called_with(StackName=STACK,
                                                TemplateURL=template_url,
                                                ChangeSetName=CHANGESETNAME,
                                                ChangeSetType=CHANGE_SET_TYPE)

    client.delete_object.assert_called_with(Bucket=bucket_name,
                                            Key=bucket_path)
    client.delete_bucket.assert_called_with(Bucket=bucket_name)
Exemplo n.º 3
0
def test_reraises_exception_when_not_change_set_not_found(client):
    change_set = ChangeSet(STACK)
    exception = ClientError(dict(Error=dict(
        Code='ValidationError')), "DescribeChangeSet")
    client.describe_change_set.side_effect = exception
    with pytest.raises(ClientError):
        change_set.remove_existing_changeset()
Exemplo n.º 4
0
def test_submits_changeset_with_parameters():
    cf_client_mock = Mock()
    change_set = ChangeSet(STACK, cf_client_mock)

    change_set.create(template=TEMPLATE,
                      change_set_type=CHANGE_SET_TYPE,
                      parameters=CHANGE_SET_PARAMETERS)

    Parameters = [{
        'ParameterKey': 'A',
        'ParameterValue': 'B',
        'UsePreviousValue': False
    }, {
        'ParameterKey': 'B',
        'ParameterValue': 'C',
        'UsePreviousValue': False
    }]
    cf_client_mock.create_change_set.assert_called_with(
        StackName=STACK,
        TemplateBody=TEMPLATE,
        ChangeSetName=CHANGESETNAME,
        ChangeSetType=CHANGE_SET_TYPE,
        Parameters=Parameters)

    cf_client_mock.get_waiter.assert_called_with('change_set_create_complete')
    cf_client_mock.get_waiter.return_value.wait.assert_called_with(
        StackName=STACK, ChangeSetName=CHANGESETNAME)
Exemplo n.º 5
0
def test_remove_existing_changeset_for_update_type(mocker, capsys):
    mocker.patch.object(ChangeSet, 'describe')
    cf_client_mock = Mock()
    change_set = ChangeSet(STACK, cf_client_mock)
    change_set.create(template=TEMPLATE, change_set_type='UPDATE')
    cf_client_mock.describe_change_set.assert_called_with(StackName=STACK, ChangeSetName=CHANGESETNAME)
    cf_client_mock.delete_change_set.assert_called_with(StackName=STACK, ChangeSetName=CHANGESETNAME)
Exemplo n.º 6
0
def test_prints_changes(logger):
    cf_client_mock = Mock()
    cf_client_mock.describe_change_set.return_value = CHANGESETCHANGES
    change_set = ChangeSet(STACK, cf_client_mock)

    change_set.describe()

    change_set_output = '\n'.join([call[1][0] for call in logger.info.mock_calls])

    to_search = []
    to_search.extend(CHANGE_SET_HEADER)
    to_search.extend(['Remove', 'Modify', 'Add'])
    to_search.extend(['DeploymentBucket', 'DeploymentBucket2', 'DeploymentBucket3'])
    to_search.extend(['simpleteststack-deploymentbucket-1l7p61v6fxpry ',
                      'simpleteststack-deploymentbucket2-11ngaeftydtn7 '])
    to_search.extend(['AWS::S3::Bucket'])
    to_search.extend(['True'])
    to_search.extend(['BucketName, Tags'])
    # Parameters
    to_search.extend(['bucketname=formicatestbucketname, bucketname2=formicatestbucketname2'])
    # Capabilities
    to_search.extend(['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM'])
    # Stack Tags
    to_search.extend(['StackKey=StackValue, StackKey2=StackValue2'])
    for term in to_search:
        assert term in change_set_output

    assert 'None' not in change_set_output
Exemplo n.º 7
0
def test_change_set_with_previous_template(client):
    change_set = ChangeSet(STACK)

    change_set.create(change_set_type=CHANGE_SET_TYPE, use_previous_template=True)

    client.create_change_set.assert_called_with(
        StackName=STACK,
        ChangeSetName=CHANGESETNAME, ChangeSetType=CHANGE_SET_TYPE, UsePreviousTemplate=True, IncludeNestedStacks=False)
Exemplo n.º 8
0
def test_only_prints_unique_changed_parameters(logger, client):
    client.describe_change_set.return_value = CHANGESETCHANGES_WITH_DUPLICATE_CHANGED_PARAMETER
    change_set = ChangeSet(STACK)

    change_set.describe()

    change_set_output = logger.info.call_args[0][0]

    assert change_set_output.count('BucketName') == 1
Exemplo n.º 9
0
def test_remove_existing_changeset_for_update_type(mocker, capsys, client, change_set_not_found, time):
    mocker.patch.object(ChangeSet, 'describe')
    change_set = ChangeSet(STACK)
    client.describe_change_set.side_effect = [
        {"ChangeSetId": CHANGESETNAME}, {}, change_set_not_found]
    change_set.create(template=TEMPLATE, change_set_type='UPDATE')
    client.describe_change_set.assert_called_with(StackName=STACK, ChangeSetName=CHANGESETNAME)
    client.delete_change_set.assert_called_with(ChangeSetName=CHANGESETNAME)
    time.sleep.assert_called_with(5)
Exemplo n.º 10
0
def test_prints_error_message_but_exits_successfully_for_no_changes(capsys, logger, mocker, client):
    change_set = ChangeSet(STACK)
    status_reason = "The submitted information didn't contain changes. " \
                    "Submit different information to create a change set."

    error = WaiterError('name', 'reason', {'StatusReason': status_reason})
    client.get_waiter.return_value.wait.side_effect = error

    change_set.create(template=TEMPLATE, change_set_type=CHANGE_SET_TYPE)
    logger.info.assert_called_with(status_reason)
Exemplo n.º 11
0
def test_prints_error_message_and_does_not_fail_without_StatusReason(capsys, logger, client):
    change_set = ChangeSet(STACK)

    error = WaiterError('name', 'reason', {})
    client.get_waiter.return_value.wait.side_effect = error

    with pytest.raises(SystemExit) as pytest_wrapped_e:
        change_set.create(template=TEMPLATE, change_set_type=CHANGE_SET_TYPE)
    logger.info.assert_called()
    assert pytest_wrapped_e.value.code == 1
Exemplo n.º 12
0
def test_prints_error_message_for_failed_submit_and_exits(capsys, logger):
    cf_client_mock = Mock()
    change_set = ChangeSet(STACK, cf_client_mock)

    error = WaiterError('name', 'reason', {'StatusReason': 'StatusReason'})
    cf_client_mock.get_waiter.return_value.wait.side_effect = error

    with pytest.raises(SystemExit) as pytest_wrapped_e:
        change_set.create(template=TEMPLATE, change_set_type=CHANGE_SET_TYPE)
    logger.info.assert_called_with('StatusReason')
    assert pytest_wrapped_e.value.code == 1
Exemplo n.º 13
0
def test_submits_changeset_and_waits(client):
    change_set = ChangeSet(STACK)

    change_set.create(template=TEMPLATE, change_set_type=CHANGE_SET_TYPE)

    client.create_change_set.assert_called_with(
        StackName=STACK, TemplateBody=TEMPLATE,
        ChangeSetName=CHANGESETNAME, ChangeSetType=CHANGE_SET_TYPE, IncludeNestedStacks=False)

    client.get_waiter.assert_called_with(
        'change_set_create_complete')
    client.get_waiter.return_value.wait.assert_called_with(
        StackName=STACK, ChangeSetName=CHANGESETNAME, WaiterConfig={'Delay': 10, 'MaxAttempts': 120})
Exemplo n.º 14
0
def test_change_set_with_resource_types():
    resources = {
        'Resources': {resource: {'Type': resource} for resource in RESOURCES}
    }
    template = json.dumps(resources)
    cf_client_mock = Mock()
    change_set = ChangeSet(STACK, cf_client_mock)

    change_set.create(template=template, change_set_type=CHANGE_SET_TYPE, resource_types=True)

    cf_client_mock.create_change_set.assert_called_with(
        StackName=STACK, TemplateBody=template,
        ChangeSetName=CHANGESETNAME, ChangeSetType=CHANGE_SET_TYPE, ResourceTypes=list(set(RESOURCES)))
Exemplo n.º 15
0
def test_submits_changeset_and_waits():
    cf_client_mock = Mock()
    change_set = ChangeSet(STACK, cf_client_mock)

    change_set.create(template=TEMPLATE, change_set_type=CHANGE_SET_TYPE)

    cf_client_mock.create_change_set.assert_called_with(
        StackName=STACK, TemplateBody=TEMPLATE,
        ChangeSetName=CHANGESETNAME, ChangeSetType=CHANGE_SET_TYPE)

    cf_client_mock.get_waiter.assert_called_with(
        'change_set_create_complete')
    cf_client_mock.get_waiter.return_value.wait.assert_called_with(
        StackName=STACK, ChangeSetName=CHANGESETNAME)
Exemplo n.º 16
0
def test_change_set_without_named_properties(client):
    CHANGESET = copy.deepcopy(CHANGESETCHANGES)

    # Find a property change in the changeset
    PROPERTY_CHANGE = CHANGESET['Changes'][1]['ResourceChange']['Details'][1]
    assert PROPERTY_CHANGE['Target']['Attribute'] == 'Properties'
    assert PROPERTY_CHANGE['Target']['Name'] == 'BucketName'

    # Remove the "Name" attribute
    del PROPERTY_CHANGE['Target']['Name']

    client.describe_change_set.return_value = CHANGESET

    change_set = ChangeSet(STACK)
    change_set.describe()
Exemplo n.º 17
0
def test_creates_and_removes_bucket_for_s3_flag(client, temp_bucket_function, temp_bucket):
    change_set = ChangeSet(STACK)
    bucket_name = 'formica-deploy-{}'.format("test")
    bucket_path = '{}-template.json'.format(STACK)
    template_url = 'https://{}.s3.amazonaws.com/{}'.format(bucket_name, bucket_path)
    temp_bucket.add.return_value = bucket_path
    temp_bucket.name = bucket_name

    change_set.create(template=TEMPLATE, change_set_type=CHANGE_SET_TYPE, s3=True)

    temp_bucket.add.assert_called_with(TEMPLATE)
    temp_bucket_function.assert_called_with(STACK)

    client.create_change_set.assert_called_with(
        StackName=STACK, TemplateURL=template_url,
        ChangeSetName=CHANGESETNAME, ChangeSetType=CHANGE_SET_TYPE, IncludeNestedStacks=False)
Exemplo n.º 18
0
def test_submits_changeset_with_stack_tags(client):
    change_set = ChangeSet(STACK)

    change_set.create(template=TEMPLATE, change_set_type=CHANGE_SET_TYPE, tags=CHANGE_SET_STACK_TAGS)

    Tags = [
        {'Key': 'T1', 'Value': 'TV1'},
        {'Key': 'T2', 'Value': 'TV2'}
    ]
    client.create_change_set.assert_called_with(
        StackName=STACK, TemplateBody=TEMPLATE,
        ChangeSetName=CHANGESETNAME, ChangeSetType=CHANGE_SET_TYPE, Tags=Tags, IncludeNestedStacks=False)

    client.get_waiter.assert_called_with(
        'change_set_create_complete')
    client.get_waiter.return_value.wait.assert_called_with(
        StackName=STACK, ChangeSetName=CHANGESETNAME, WaiterConfig={'Delay': 10, 'MaxAttempts': 120})
Exemplo n.º 19
0
def test_submits_changeset_with_stack_tags():
    cf_client_mock = Mock()
    change_set = ChangeSet(STACK, cf_client_mock)

    change_set.create(template=TEMPLATE, change_set_type=CHANGE_SET_TYPE, tags=CHANGE_SET_STACK_TAGS)

    Tags = [
        {'Key': 'T1', 'Value': 'TV1'},
        {'Key': 'T2', 'Value': 'TV2'}
    ]
    cf_client_mock.create_change_set.assert_called_with(
        StackName=STACK, TemplateBody=TEMPLATE,
        ChangeSetName=CHANGESETNAME, ChangeSetType=CHANGE_SET_TYPE, Tags=Tags)

    cf_client_mock.get_waiter.assert_called_with(
        'change_set_create_complete')
    cf_client_mock.get_waiter.return_value.wait.assert_called_with(
        StackName=STACK, ChangeSetName=CHANGESETNAME)
Exemplo n.º 20
0
def test_submits_changeset_with_parameters(client):
    change_set = ChangeSet(STACK)

    change_set.create(template=TEMPLATE, change_set_type=CHANGE_SET_TYPE, parameters=CHANGE_SET_PARAMETERS)

    Parameters = [
        {'ParameterKey': 'A', 'ParameterValue': 'B', 'UsePreviousValue': False},
        {'ParameterKey': 'B', 'ParameterValue': '2', 'UsePreviousValue': False},
        {'ParameterKey': 'C', 'ParameterValue': 'True', 'UsePreviousValue': False},
    ]
    client.create_change_set.assert_called_with(
        StackName=STACK, TemplateBody=TEMPLATE,
        ChangeSetName=CHANGESETNAME, ChangeSetType=CHANGE_SET_TYPE, Parameters=Parameters, IncludeNestedStacks=False)

    client.get_waiter.assert_called_with(
        'change_set_create_complete')
    client.get_waiter.return_value.wait.assert_called_with(
        StackName=STACK, ChangeSetName=CHANGESETNAME, WaiterConfig={'Delay': 10, 'MaxAttempts': 120})
Exemplo n.º 21
0
def test_change_set_with_previous_parameters(client):
    Parameters = [
        {'ParameterKey': 'A', 'UsePreviousValue': True},
        {'ParameterKey': 'B', 'UsePreviousValue': True},
        {'ParameterKey': 'C', 'ParameterValue': '12345', 'UsePreviousValue': False},
        {'ParameterKey': 'D', 'ParameterValue': '7890', 'UsePreviousValue': False},
    ]

    client.describe_stacks.return_value = {
        'Stacks': [{'Parameters': [{'ParameterKey': 'A'}, {'ParameterKey': 'B'}]}]
    }
    change_set = ChangeSet(STACK)

    change_set.create(change_set_type=CHANGE_SET_TYPE, use_previous_template=True, use_previous_parameters=True,
                      parameters={'C': '12345', 'D': '7890'})
    client.describe_stacks.assert_called_once_with(StackName=STACK)

    client.create_change_set.assert_called_with(
        StackName=STACK,
        ChangeSetName=CHANGESETNAME, ChangeSetType=CHANGE_SET_TYPE, Parameters=Parameters, UsePreviousTemplate=True,
        IncludeNestedStacks=False)
Exemplo n.º 22
0
def test_prints_nested_changes(logger, client):
    client.describe_change_set.side_effect = [CHANGESET_NESTED_CHANGES, CHANGESETCHANGES]
    change_set = ChangeSet(STACK)

    change_set.describe()

    change_set_output = '\n'.join([call[1][0] for call in logger.info.mock_calls])
    print(change_set_output)

    to_search = []
    to_search.extend(CHANGE_SET_HEADER)
    to_search.extend(['Changes for nested Stack: NestedStack'])
    to_search.extend(['NestedStack'])
    to_search.extend(['Remove', 'Modify', 'Add'])
    to_search.extend(['DeploymentBucket', 'DeploymentBucket2', 'DeploymentBucket3'])
    to_search.extend(['simpleteststack-deploymentbucket-1l7p61v6fxpry ',
                      'simpleteststack-deploymentbucket2-11ngaeftydtn7 '])
    to_search.extend(['AWS::S3::Bucket'])
    to_search.extend(['True'])
    to_search.extend(['BucketName, Tags'])
    for term in to_search:
        assert term in change_set_output

    assert 'None' not in change_set_output
Exemplo n.º 23
0
def change(args):
    client = AWS.current_session().client('cloudformation')
    loader = Loader()
    loader.load()

    change_set = ChangeSet(stack=args.stack, client=client)
    change_set.create(template=loader.template(),
                      change_set_type='UPDATE',
                      parameters=args.parameters,
                      tags=args.tags,
                      capabilities=args.capabilities)
    change_set.describe()
Exemplo n.º 24
0
def new(args):
    client = AWS.current_session().client('cloudformation')
    loader = Loader()
    loader.load()
    logger.info('Creating change set for new stack, ...')
    change_set = ChangeSet(stack=args.stack, client=client)
    change_set.create(template=loader.template(),
                      change_set_type='CREATE',
                      parameters=args.parameters,
                      tags=args.tags,
                      capabilities=args.capabilities)
    change_set.describe()
    logger.info('Change set created, please deploy')
Exemplo n.º 25
0
def describe(args):
    client = AWS.current_session().client('cloudformation')
    change_set = ChangeSet(stack=args.stack, client=client)
    change_set.describe()
Exemplo n.º 26
0
def test_do_not_remove_changeset_if_non_existent(client, change_set_not_found):
    change_set = ChangeSet(STACK)
    client.describe_change_set.side_effect = change_set_not_found
    change_set.remove_existing_changeset()
    client.delete_change_set.assert_not_called()
Exemplo n.º 27
0
def test_exception_if_change_set_not_deleted(client, time):
    change_set = ChangeSet(STACK)
    with pytest.raises(Exception) as pytest_exception:
        change_set.remove_existing_changeset()
Exemplo n.º 28
0
def test_prints_nested_changes(logger, client):
    client.describe_change_set.side_effect = [CHANGESET_NESTED_STACK_NO_NESTED_CHANGESET]
    change_set = ChangeSet(STACK)
    change_set.describe()