Exemple #1
0
def test_deploy_failed_only_existing_changes(client, config):
    config._config['ExistingChanges'] = 'FAILED_ONLY'

    runner = Runner(client, config)
    with pytest.raises(
            ValidationError,
            match=
            'Creation of new ChangeSet not allowed when existing valid ChangeSets found'
    ):
        runner.deploy()

    client.list_change_sets.assert_called_once_with(StackName='TestStack')
Exemple #2
0
def test_deploy_client_error(client, config):
    client.configure_mock(**{
        'create_change_set.side_effect':
        ClientError({}, 'create_change_set')
    })
    runner = Runner(client, config)
    with pytest.raises(
            StackError,
            match=
            'An error occurred \\(Unknown\\) when calling the create_change_set .*'
    ):
        runner.deploy()
Exemple #3
0
def test_deploy_rollback_complete(client, config):
    describe_stacks = {
        'Stacks': [{
            'StackName': 'TestStack',
            'StackStatus': StackStatus.ROLLBACK_COMPLETE.name,
            'CreationTime': '2019-12-31T18:30:11.12345+0000'
        }]
    }
    client.configure_mock(**{'describe_stacks.return_value': describe_stacks})

    runner = Runner(client, config)
    runner.deploy()

    client.delete_stack.assert_called_once_with(StackName='TestStack',
                                                RetainResources=[])
Exemple #4
0
def test_deploy_waiter_failed(client, config):
    # Configure waiter to throw WaiterError for some unknown other reasons
    waiter_error = WaiterError('change_set_create_complete', 'Other reason', {
        'Status': 'FAILED',
        'StatusReason': 'Some other reason'
    })
    waiter_mock = MagicMock(**{'wait.side_effect': waiter_error})
    client.configure_mock(**{'get_waiter.return_value': waiter_mock})

    runner = Runner(client, config)

    with pytest.raises(
            StackError,
            match=
            'ChangeSet creation failed - Status: FAILED, Reason: Some other reason'
    ):
        runner.deploy()
Exemple #5
0
def test_deploy_invalid_status(client, config):
    describe_stacks = {
        'Stacks': [{
            'StackName': 'TestStack',
            'StackStatus': StackStatus.UPDATE_IN_PROGRESS.name,
            'CreationTime': '2019-12-31T18:30:11.12345+0000'
        }]
    }
    client.configure_mock(**{'describe_stacks.return_value': describe_stacks})

    runner = Runner(client, config)
    with pytest.raises(
            ValidationError,
            match=
            'Stack TestStack is not in a deployable status: UPDATE_IN_PROGRESS'
    ):
        runner.deploy()
Exemple #6
0
def test_deploy(client, config, capsys, monkeypatch):
    # Prevent differences in format depending upon where this runs
    monkeypatch.setenv('STACKMANAGER_TIMEZONE', 'UTC')

    runner = Runner(client, config)
    runner.deploy()

    client.list_change_sets.assert_called_once_with(StackName='TestStack')
    client.create_change_set.assert_called_once_with(
        StackName='TestStack',
        ChangeSetName='TestChangeSet',
        ChangeSetType='UPDATE',
        Parameters=[{
            'ParameterKey': 'Param1',
            'ParameterValue': 'Value1'
        }, {
            'ParameterKey': 'Param2',
            'UsePreviousValue': True
        }],
        Tags=[{
            'Key': 'Tag1',
            'Value': 'Value1'
        }],
        Capabilities=['CAPABILITY_IAM'],
        TemplateBody='AWSTemplateFormatVersion : "2010-09-09"')
    client.get_waiter.assert_called_once_with('change_set_create_complete')
    client.get_waiter().wait.assert_called_once_with(
        StackName='TestStack',
        ChangeSetName='TestChangeSet',
        WaiterConfig={
            'Delay': 5,
            'MaxAttempts': 120
        })
    client.describe_change_set.assert_called_once_with(
        ChangeSetName='TestChangeSet', StackName='TestStack')

    captured = capsys.readouterr()
    assert 'Stack: TestStack, Status: CREATE_COMPLETE' in captured.out
    assert 'Existing ChangeSets:\n  2020-01-01 00:00:00: ExistingChangeSet (CREATE_COMPLETE)' in captured.out
    assert 'Creating ChangeSet TestChangeSet' in captured.out
    assert 'Action    LogicalResourceId    ResourceType     Replacement' in captured.out
    assert 'Add       Queue                AWS::SQS::Queue  -' in captured.out
    assert 'ChangeSet TestChangeSet is ready to run' in captured.out
Exemple #7
0
def test_deploy_no_changes(client, config, capsys):
    # Configure waiter to throw WaiterError for FAILURE due to no changes
    waiter_error = WaiterError('change_set_create_complete', 'No Changes', {
        'Status': 'FAILED',
        'StatusReason': 'No updates are to be performed'
    })
    waiter_mock = MagicMock(**{'wait.side_effect': waiter_error})
    client.configure_mock(**{'get_waiter.return_value': waiter_mock})

    runner = Runner(client, config)
    runner.deploy()

    client.list_change_sets.assert_called_once_with(StackName='TestStack')
    client.create_change_set.assert_called_once()
    client.get_waiter.assert_called_once_with('change_set_create_complete')
    client.describe_change_set.assert_not_called()
    client.update_termination_protection.assert_not_called()

    captured = capsys.readouterr()
    assert 'No changes to Stack TestStack' in captured.out
Exemple #8
0
def test_deploy_no_changes_enable_termination_protection(
        client, config, capsys):
    describe_stacks = {
        'Stacks': [{
            'StackName': 'TestStack',
            'StackStatus': StackStatus.CREATE_COMPLETE.name,
            'CreationTime': '2019-12-31T18:30:11.12345+0000',
            'EnableTerminationProtection': False
        }]
    }
    # Configure waiter to throw WaiterError for FAILURE due to no changes
    waiter_error = WaiterError('change_set_create_complete', 'No Changes', {
        'Status': 'FAILED',
        'StatusReason': 'No updates are to be performed'
    })
    waiter_mock = MagicMock(**{'wait.side_effect': waiter_error})
    client.configure_mock(
        **{
            'get_waiter.return_value': waiter_mock,
            'describe_stacks.return_value': describe_stacks
        })

    runner = Runner(client, config)
    runner.deploy()

    client.list_change_sets.assert_called_once_with(StackName='TestStack')
    client.create_change_set.assert_called_once()
    client.get_waiter.assert_called_once_with('change_set_create_complete')
    client.describe_change_set.assert_not_called()

    client.update_termination_protection.assert_called_once_with(
        StackName='TestStack', EnableTerminationProtection=True)

    captured = capsys.readouterr()
    assert 'No changes to Stack TestStack' in captured.out
    assert 'Enabled Termination Protection' in captured.out