Пример #1
0
def test_delete_no_stack(config):
    attrs = {'describe_stacks.side_effect': STACK_DOES_NOT_EXIST}
    mock = MagicMock(**attrs)
    runner = Runner(mock, config)

    with pytest.raises(ValidationError, match='Stack TestStack not found'):
        runner.delete()
Пример #2
0
def test_delete_client_error(client, config):
    client.configure_mock(
        **{'delete_stack.side_effect': ClientError({}, 'delete_stack')})
    runner = Runner(client, config)
    with pytest.raises(
            StackError,
            match=
            'An error occurred \\(Unknown\\) when calling the delete_stack operation.*'
    ):
        runner.delete()
Пример #3
0
def test_delete(client, config, capsys):
    runner = Runner(client, config)
    runner.delete()

    assert runner.stack is None

    client.describe_stack_events.assert_called_once_with(StackName='TestStack')
    client.delete_stack.assert_called_once_with(StackName='TestStack',
                                                RetainResources=[])
    client.get_waiter.assert_called_once_with('stack_delete_complete')
    client.get_waiter().wait.assert_called_once_with(StackName='TestStack',
                                                     WaiterConfig={
                                                         'Delay': 10,
                                                         'MaxAttempts': 360
                                                     })
Пример #4
0
def test_delete_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 deletable status: UPDATE_IN_PROGRESS'
    ):
        runner.delete()
Пример #5
0
def test_delete_waiter_error(client, config, capsys, monkeypatch):
    # Prevent differences in format depending upon where this runs
    monkeypatch.setenv('STACKMANAGER_TIMEZONE', 'UTC')

    # Configure waiter
    waiter_error = WaiterError('stack_delete_complete', 'Delete Failed', {
        'Status': 'FAILED',
        'StatusReason': 'Delete failed'
    })
    waiter_mock = MagicMock(**{'wait.side_effect': waiter_error})

    # Override Stack events
    stack_events = {
        'StackEvents': [{
            'Timestamp':
            datetime(2020, 1, 1, 13, 35, 11, 0, tzinfo=timezone.utc),
            'LogicalResourceId':
            'Topic',
            'ResourceType':
            'AWS::SNS::Topic',
            'ResourceStatus':
            'DELETE_FAILED',
            'ResourceStatusReason':
            'Something went wrong'
        }, {
            'Timestamp':
            datetime(2020, 1, 1, 12, 0, 0, 0, tzinfo=timezone.utc),
            'LogicalResourceId':
            'TestStack',
            'ResourceType':
            'AWS::CloudFormation::Stack',
            'ResourceStatus':
            'CREATE_COMPLETE'
        }, {
            'Timestamp':
            datetime(2020, 1, 1, 11, 58, 20, 12436, tzinfo=timezone.utc),
            'LogicalResourceId':
            'Topic',
            'ResourceType':
            'AWS::SNS::Topic',
            'ResourceStatus':
            'CREATE_COMPLETE'
        }]
    }
    paginator_mock = MagicMock(**{'paginate.return_value': [stack_events]})

    client.configure_mock(
        **{
            'get_waiter.return_value': waiter_mock,
            'get_paginator.return_value': paginator_mock
        })

    runner = Runner(client, config)
    with pytest.raises(
            StackError,
            match='Waiter stack_delete_complete failed: Delete Failed'):
        runner.delete()

    captured = capsys.readouterr()
    assert 'Deletion of Stack TestStack failed:' in captured.err
    assert '2020-01-01 13:35:11  Topic                AWS::SNS::Topic  DELETE_FAILED     Something went wrong' \
           in captured.out