File: test_subscribe.py

package info (click to toggle)
awscli 2.31.35-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 156,692 kB
  • sloc: python: 213,816; xml: 14,082; makefile: 189; sh: 178; javascript: 8
file content (244 lines) | stat: -rw-r--r-- 9,809 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import botocore.session
from botocore.exceptions import ClientError

from awscli.compat import StringIO
from awscli.customizations.configservice.subscribe import (
    S3BucketHelper,
    SNSTopicHelper,
    SubscribeCommand,
)
from awscli.testutils import mock, unittest


class TestS3BucketHelper(unittest.TestCase):
    def setUp(self):
        self.session = botocore.session.get_session()
        self.s3_client = mock.Mock(self.session.create_client('s3'))
        self.helper = S3BucketHelper(self.s3_client)
        self.error_response = {
            'Error': {'Code': '404', 'Message': 'Not Found'}
        }
        self.bucket_no_exists_error = ClientError(
            self.error_response, 'HeadBucket'
        )

    def test_correct_prefix_returned(self):
        name = 'MyBucket/MyPrefix'
        bucket, prefix = self.helper.prepare_bucket(name)
        # Ensure the returned bucket and key are as expected
        self.assertEqual(bucket, 'MyBucket')
        self.assertEqual(prefix, 'MyPrefix')

    def test_bucket_exists(self):
        name = 'MyBucket'
        bucket, prefix = self.helper.prepare_bucket(name)
        # A new bucket should not have been created because no error was thrown
        self.assertFalse(self.s3_client.create_bucket.called)
        # Ensure the returned bucket and key are as expected
        self.assertEqual(bucket, name)
        self.assertEqual(prefix, '')

    def test_bucket_no_exist(self):
        name = 'MyBucket/MyPrefix'
        self.s3_client.head_bucket.side_effect = self.bucket_no_exists_error
        self.s3_client.meta.region_name = 'us-east-1'
        bucket, prefix = self.helper.prepare_bucket(name)
        # Ensure that the create bucket was called with the proper args.
        self.s3_client.create_bucket.assert_called_with(Bucket='MyBucket')
        # Ensure the returned bucket and key are as expected
        self.assertEqual(bucket, 'MyBucket')
        self.assertEqual(prefix, 'MyPrefix')

    def test_bucket_no_exist_with_location_constraint(self):
        name = 'MyBucket/MyPrefix'
        self.s3_client.head_bucket.side_effect = self.bucket_no_exists_error
        self.s3_client.meta.region_name = 'us-west-2'
        bucket, prefix = self.helper.prepare_bucket(name)
        # Ensure that the create bucket was called with the proper args.
        self.s3_client.create_bucket.assert_called_with(
            Bucket='MyBucket',
            CreateBucketConfiguration={'LocationConstraint': 'us-west-2'},
        )
        # Ensure the returned bucket and key are as expected
        self.assertEqual(bucket, 'MyBucket')
        self.assertEqual(prefix, 'MyPrefix')

    def test_bucket_client_exception_non_404(self):
        name = 'MyBucket/MyPrefix'
        self.error_response['Error']['Code'] = '403'
        self.error_response['Error']['Message'] = 'Forbidden'
        forbidden_error = ClientError(self.error_response, 'HeadBucket')
        self.s3_client.head_bucket.side_effect = forbidden_error
        self.s3_client._endpoint.region_name = 'us-east-1'
        bucket, prefix = self.helper.prepare_bucket(name)
        # A new bucket should not have been created because a 404 error
        # was not thrown
        self.assertFalse(self.s3_client.create_bucket.called)
        # Ensure the returned bucket and key are as expected
        self.assertEqual(bucket, 'MyBucket')
        self.assertEqual(prefix, 'MyPrefix')

    def test_output_use_existing_bucket(self):
        name = 'MyBucket/MyPrefix'
        with mock.patch('sys.stdout', StringIO()) as mock_stdout:
            self.helper.prepare_bucket(name)
            self.assertIn(
                'Using existing S3 bucket: MyBucket', mock_stdout.getvalue()
            )

    def test_output_create_bucket(self):
        name = 'MyBucket/MyPrefix'
        self.s3_client.head_bucket.side_effect = self.bucket_no_exists_error
        self.s3_client._endpoint.region_name = 'us-east-1'
        with mock.patch('sys.stdout', StringIO()) as mock_stdout:
            self.helper.prepare_bucket(name)
            self.assertIn(
                'Using new S3 bucket: MyBucket', mock_stdout.getvalue()
            )


class TestSNSTopicHelper(unittest.TestCase):
    def setUp(self):
        self.session = botocore.session.get_session()
        self.sns_client = mock.Mock(
            self.session.create_client('sns', 'us-east-1')
        )
        self.helper = SNSTopicHelper(self.sns_client)

    def test_sns_topic_by_name(self):
        name = 'mysnstopic'
        self.sns_client.create_topic.return_value = {'TopicArn': 'myARN'}
        sns_arn = self.helper.prepare_topic(name)
        # Ensure that the topic was create and returned the expected arn
        self.assertTrue(self.sns_client.create_topic.called)
        self.assertEqual(sns_arn, 'myARN')

    def test_sns_topic_by_arn(self):
        name = 'arn:aws:sns:us-east-1:934212987125:config'
        sns_arn = self.helper.prepare_topic(name)
        # Ensure that the topic was not created and returned the expected arn
        self.assertFalse(self.sns_client.create_topic.called)
        self.assertEqual(sns_arn, name)

    def test_output_existing_topic(self):
        name = 'mysnstopic'
        self.sns_client.create_topic.return_value = {'TopicArn': 'myARN'}
        with mock.patch('sys.stdout', StringIO()) as mock_stdout:
            self.helper.prepare_topic(name)
            self.assertIn('Using new SNS topic: myARN', mock_stdout.getvalue())

    def test_output_new_topic(self):
        name = 'arn:aws:sns:us-east-1:934212987125:config'
        with mock.patch('sys.stdout', StringIO()) as mock_stdout:
            self.helper.prepare_topic(name)
            self.assertIn(
                'Using existing SNS topic: %s' % name, mock_stdout.getvalue()
            )


class TestSubscribeCommand(unittest.TestCase):
    def setUp(self):
        self.session = botocore.session.get_session()

        # Set up the client mocks.
        self.s3_client = mock.Mock(self.session.create_client('s3'))
        self.sns_client = mock.Mock(
            self.session.create_client('sns', 'us-east-1')
        )
        self.config_client = mock.Mock(
            self.session.create_client('config', 'us-east-1')
        )
        self.config_client.describe_configuration_recorders.return_value = {
            'ConfigurationRecorders': []
        }
        self.config_client.describe_delivery_channels.return_value = {
            'DeliveryChannels': []
        }

        self.session = mock.Mock(self.session)
        self.session.create_client.side_effect = [
            self.s3_client,
            self.sns_client,
            self.config_client,
        ]

        self.parsed_args = mock.Mock()
        self.parsed_args.s3_bucket = 'MyBucket/MyPrefix'
        self.parsed_args.sns_topic = (
            'arn:aws:sns:us-east-1:934212987125:config'
        )
        self.parsed_args.iam_role = 'arn:aws:iam::1234556789:role/config'

        self.parsed_globals = mock.Mock()

        self.cmd = SubscribeCommand(self.session)

    def test_setup_clients(self):
        self.parsed_globals.verify_ssl = True
        self.parsed_globals.region = 'us-east-1'
        self.parsed_globals.endpoint_url = 'http://myendpoint.com'

        self.cmd._run_main(self.parsed_args, self.parsed_globals)

        # Check to see that the clients were created correctly
        self.session.create_client.assert_any_call(
            's3',
            verify=self.parsed_globals.verify_ssl,
            region_name=self.parsed_globals.region,
        )
        self.session.create_client.assert_any_call(
            'sns',
            verify=self.parsed_globals.verify_ssl,
            region_name=self.parsed_globals.region,
        )
        self.session.create_client.assert_any_call(
            'config',
            verify=self.parsed_globals.verify_ssl,
            region_name=self.parsed_globals.region,
            endpoint_url=self.parsed_globals.endpoint_url,
        )

    def test_subscribe(self):
        self.cmd._run_main(self.parsed_args, self.parsed_globals)

        # Check the call made to put configuration recorder.
        self.config_client.put_configuration_recorder.assert_called_with(
            ConfigurationRecorder={
                'name': 'default',
                'roleARN': self.parsed_args.iam_role,
            }
        )

        # Check the call made to put delivery channel.
        self.config_client.put_delivery_channel.assert_called_with(
            DeliveryChannel={
                'name': 'default',
                's3BucketName': 'MyBucket',
                'snsTopicARN': self.parsed_args.sns_topic,
                's3KeyPrefix': 'MyPrefix',
            }
        )

        # Check the call made to start configuration recorder.
        self.config_client.start_configuration_recorder.assert_called_with(
            ConfigurationRecorderName='default'
        )

        # Check that the describe delivery channel and configuration recorder
        # methods were called.
        self.assertTrue(
            self.config_client.describe_configuration_recorders.called
        )
        self.assertTrue(self.config_client.describe_delivery_channels.called)