awspub 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,433 @@
1
+ import pathlib
2
+ from unittest.mock import patch
3
+
4
+ import pytest
5
+
6
+ from awspub import context, exceptions, image
7
+
8
+ curdir = pathlib.Path(__file__).parent.resolve()
9
+
10
+
11
+ @pytest.mark.parametrize(
12
+ "imagename,snapshotname",
13
+ [
14
+ # test-image-1 without any separate snapshot or billing products.
15
+ # so snapshotname should match source sha256sum
16
+ ("test-image-1", "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8"),
17
+ # test-image-2 with separate snapshot but without billing products.
18
+ # so snapshotname should be the shasum of the concatenated string of:
19
+ # - 6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8
20
+ # - echo -n test-image-2 | sha256sum
21
+ ("test-image-2", "0c274a96fe840cdd9cf65b0bf8e4d755d94fddf00916aa6f26ee3f08e412c88f"),
22
+ # test-image-3 with separate snapshot and billing products
23
+ ("test-image-3", "ef7c5bbbc2816c60acfa4f3954e431c849054f7370bf351055f6d665b60623e7"),
24
+ # test-image-4 without separate snapshot but with billing products
25
+ ("test-image-4", "bf795c602d53ff9c9548cc6305aa1240bd0f3d4429869abe4c96bcef65c4e48d"),
26
+ # test-image-5 without separate snapshot but with multiple billing products
27
+ ("test-image-5", "8171cd4d36d06150a5ff8bb519439c5efd4e91841be62f50736db3b82e4aaedc"),
28
+ ],
29
+ )
30
+ def test_snapshot_names(imagename, snapshotname):
31
+ """
32
+ Test the snapshot name calculation based on the image properties
33
+ """
34
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
35
+ assert ctx.conf["source"]["path"] == curdir / "fixtures/config1.vmdk"
36
+ assert ctx.source_sha256 == "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8"
37
+
38
+ img = image.Image(ctx, imagename)
39
+ assert img.snapshot_name == snapshotname
40
+
41
+
42
+ @pytest.mark.parametrize(
43
+ "imagename,regions",
44
+ [
45
+ # test-image-1 has 2 regions defined
46
+ ("test-image-1", ["region1", "region2"]),
47
+ # test-image-2 has no regions defined, so whatever the ec2 client returns should be valid
48
+ ("test-image-2", ["all-region-1", "all-region-2"]),
49
+ ],
50
+ )
51
+ @patch("awspub.s3.S3.bucket_region", return_value="region1")
52
+ def test_image_regions(s3_region_mock, imagename, regions):
53
+ """
54
+ Test the regions for a given image
55
+ """
56
+ with patch("boto3.client") as bclient_mock:
57
+ instance = bclient_mock.return_value
58
+ instance.describe_regions.return_value = {
59
+ "Regions": [{"RegionName": "all-region-1"}, {"RegionName": "all-region-2"}]
60
+ }
61
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
62
+ img = image.Image(ctx, imagename)
63
+ assert img.image_regions == regions
64
+
65
+
66
+ @pytest.mark.parametrize(
67
+ "imagename,cleanup",
68
+ [
69
+ ("test-image-1", True),
70
+ ("test-image-2", False),
71
+ ],
72
+ )
73
+ def test_image_cleanup(imagename, cleanup):
74
+ """
75
+ Test the cleanup for a given image
76
+ """
77
+ with patch("boto3.client") as bclient_mock:
78
+ instance = bclient_mock.return_value
79
+ instance.describe_images.return_value = {"Images": [{"Name": imagename, "Public": False, "ImageId": "ami-123"}]}
80
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
81
+ img = image.Image(ctx, imagename)
82
+ img.cleanup()
83
+ assert instance.deregister_image.called == cleanup
84
+
85
+
86
+ @pytest.mark.parametrize(
87
+ "root_device_name,block_device_mappings,snapshot_id",
88
+ [
89
+ ("", [], None),
90
+ ("/dev/sda1", [], None),
91
+ (
92
+ "/dev/sda1",
93
+ [
94
+ {
95
+ "DeviceName": "/dev/sda1",
96
+ "Ebs": {
97
+ "DeleteOnTermination": True,
98
+ "SnapshotId": "snap-0be0763f84af34e05",
99
+ "VolumeSize": 17,
100
+ "VolumeType": "gp2",
101
+ "Encrypted": False,
102
+ },
103
+ },
104
+ {"DeviceName": "/dev/sdb", "VirtualName": "ephemeral0"},
105
+ ],
106
+ "snap-0be0763f84af34e05",
107
+ ),
108
+ ],
109
+ )
110
+ def test_image___get_root_device_snapshot_id(root_device_name, block_device_mappings, snapshot_id):
111
+ """
112
+ Test the _get_root_device_snapshot_id() method
113
+ """
114
+ i = {"RootDeviceName": root_device_name, "BlockDeviceMappings": block_device_mappings}
115
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
116
+ img = image.Image(ctx, "test-image-1")
117
+ assert img._get_root_device_snapshot_id(i) == snapshot_id
118
+
119
+
120
+ @pytest.mark.parametrize(
121
+ "imagename,partition,called_mod_image,called_mod_snapshot,called_start_change_set,called_put_parameter",
122
+ [
123
+ ("test-image-6", "aws", True, True, False, False),
124
+ ("test-image-7", "aws", False, False, False, False),
125
+ ("test-image-8", "aws", True, True, True, True),
126
+ ("test-image-8", "aws-cn", True, True, False, True),
127
+ ],
128
+ )
129
+ def test_image_publish(
130
+ imagename, partition, called_mod_image, called_mod_snapshot, called_start_change_set, called_put_parameter
131
+ ):
132
+ """
133
+ Test the publish() for a given image
134
+ """
135
+ with patch("boto3.client") as bclient_mock:
136
+ instance = bclient_mock.return_value
137
+ instance.meta.partition = partition
138
+ instance.describe_images.return_value = {
139
+ "Images": [
140
+ {
141
+ "Name": imagename,
142
+ "ImageId": "ami-abc",
143
+ "RootDeviceName": "/dev/sda1",
144
+ "BlockDeviceMappings": [
145
+ {
146
+ "DeviceName": "/dev/sda1",
147
+ "Ebs": {
148
+ "DeleteOnTermination": True,
149
+ "SnapshotId": "snap-0be0763f84af34e05",
150
+ },
151
+ },
152
+ ],
153
+ }
154
+ ]
155
+ }
156
+ instance.get_parameters.return_value = {"Parameters": []}
157
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
158
+ img = image.Image(ctx, imagename)
159
+ img.publish()
160
+ assert instance.modify_image_attribute.called == called_mod_image
161
+ assert instance.modify_snapshot_attribute.called == called_mod_snapshot
162
+ assert instance.start_change_set.called == called_start_change_set
163
+ assert instance.put_parameter.called == called_put_parameter
164
+
165
+
166
+ def test_image__get_zero_images():
167
+ """
168
+ Test the Image._get() method with zero matching image
169
+ """
170
+ with patch("boto3.client") as bclient_mock:
171
+ instance = bclient_mock.return_value
172
+ instance.describe_images.return_value = {"Images": []}
173
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
174
+ img = image.Image(ctx, "test-image-1")
175
+ assert img._get(instance) is None
176
+
177
+
178
+ def test_image__get_one_images():
179
+ """
180
+ Test the Image._get() method with a single matching image
181
+ """
182
+ with patch("boto3.client") as bclient_mock:
183
+ instance = bclient_mock.return_value
184
+ instance.describe_images.return_value = {
185
+ "Images": [
186
+ {
187
+ "Name": "test-image-1",
188
+ "ImageId": "ami-abc",
189
+ "RootDeviceName": "/dev/sda1",
190
+ "BlockDeviceMappings": [
191
+ {
192
+ "DeviceName": "/dev/sda1",
193
+ "Ebs": {
194
+ "DeleteOnTermination": True,
195
+ "SnapshotId": "snap-abc",
196
+ },
197
+ },
198
+ ],
199
+ }
200
+ ]
201
+ }
202
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
203
+ img = image.Image(ctx, "test-image-1")
204
+ assert img._get(instance) == image._ImageInfo("ami-abc", "snap-abc")
205
+
206
+
207
+ def test_image__get_multiple_images():
208
+ """
209
+ Test the Image._get() method with a multiple matching image
210
+ """
211
+ with patch("boto3.client") as bclient_mock:
212
+ instance = bclient_mock.return_value
213
+ instance.describe_images.return_value = {
214
+ "Images": [
215
+ {
216
+ "Name": "test-image-1",
217
+ "ImageId": "ami-1,",
218
+ },
219
+ {
220
+ "Name": "test-image-1",
221
+ "ImageId": "ami-2,",
222
+ },
223
+ ]
224
+ }
225
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
226
+ img = image.Image(ctx, "test-image-1")
227
+ with pytest.raises(exceptions.MultipleImagesException):
228
+ img._get(instance)
229
+
230
+
231
+ @pytest.mark.parametrize(
232
+ "imagename,expected_tags",
233
+ [
234
+ # no image specific tags - assume the common tags
235
+ (
236
+ "test-image-1",
237
+ [
238
+ {"Key": "awspub:source:filename", "Value": "config1.vmdk"},
239
+ {"Key": "awspub:source:architecture", "Value": "x86_64"},
240
+ {
241
+ "Key": "awspub:source:sha256",
242
+ "Value": "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8",
243
+ },
244
+ {"Key": "name", "Value": "foobar"},
245
+ ],
246
+ ),
247
+ # with image specific tag but no override
248
+ (
249
+ "test-image-6",
250
+ [
251
+ {"Key": "awspub:source:filename", "Value": "config1.vmdk"},
252
+ {"Key": "awspub:source:architecture", "Value": "x86_64"},
253
+ {
254
+ "Key": "awspub:source:sha256",
255
+ "Value": "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8",
256
+ },
257
+ {"Key": "name", "Value": "foobar"},
258
+ {"Key": "key1", "Value": "value1"},
259
+ ],
260
+ ),
261
+ # with image specific tag which overrides common tag
262
+ (
263
+ "test-image-7",
264
+ [
265
+ {"Key": "awspub:source:filename", "Value": "config1.vmdk"},
266
+ {"Key": "awspub:source:architecture", "Value": "x86_64"},
267
+ {
268
+ "Key": "awspub:source:sha256",
269
+ "Value": "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8",
270
+ },
271
+ {"Key": "name", "Value": "not-foobar"},
272
+ {"Key": "key2", "Value": "name"},
273
+ ],
274
+ ),
275
+ ],
276
+ )
277
+ def test_image__tags(imagename, expected_tags):
278
+ """
279
+ Test the Image._tags() method
280
+ """
281
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
282
+ img = image.Image(ctx, imagename)
283
+ assert img._tags == expected_tags
284
+
285
+
286
+ @pytest.mark.parametrize(
287
+ "available_images,expected",
288
+ [
289
+ # image available
290
+ ([{"Name": "test-image-6", "ImageId": "ami-123"}], {"eu-central-1": image._ImageInfo("ami-123", None)}),
291
+ # image not available
292
+ ([], {}),
293
+ ],
294
+ )
295
+ def test_image_list(available_images, expected):
296
+ """
297
+ Test the list for a given image
298
+ """
299
+ with patch("boto3.client") as bclient_mock:
300
+ instance = bclient_mock.return_value
301
+ instance.describe_images.return_value = {"Images": available_images}
302
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
303
+ img = image.Image(ctx, "test-image-6")
304
+ assert img.list() == expected
305
+
306
+
307
+ @patch("awspub.s3.S3.bucket_region", return_value="region1")
308
+ def test_image_create_existing(s3_bucket_mock):
309
+ """
310
+ Test the create() method for a given image that already exist
311
+ """
312
+ with patch("boto3.client") as bclient_mock:
313
+ instance = bclient_mock.return_value
314
+ instance.describe_snapshots.return_value = {"Snapshots": [{"SnapshotId": "snap-123"}]}
315
+ instance.describe_images.return_value = {
316
+ "Images": [
317
+ {
318
+ "Name": "test-image-6",
319
+ "ImageId": "ami-123",
320
+ "RootDeviceName": "/dev/sda1",
321
+ "BlockDeviceMappings": [
322
+ {
323
+ "DeviceName": "/dev/sda1",
324
+ "Ebs": {
325
+ "DeleteOnTermination": True,
326
+ "SnapshotId": "snap-123",
327
+ },
328
+ },
329
+ ],
330
+ }
331
+ ]
332
+ }
333
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
334
+ img = image.Image(ctx, "test-image-6")
335
+ assert img.create() == {"eu-central-1": image._ImageInfo(image_id="ami-123", snapshot_id="snap-123")}
336
+ # register and create_tags shouldn't be called given that the image was already there
337
+ assert not instance.register_image.called
338
+ assert not instance.create_tags.called
339
+
340
+
341
+ @pytest.mark.parametrize(
342
+ "imagename,describe_images,get_parameters,get_parameters_called,put_parameter_called",
343
+ [
344
+ # no image, no parameters (this should actually never happen but test it anyway)
345
+ ("test-image-8", [], [], False, False),
346
+ # with image, no parameter, no overwrite
347
+ ("test-image-8", [{"Name": "test-image-8", "ImageId": "ami-123"}], [], True, True),
348
+ # with image, with parameter, no overwrite
349
+ (
350
+ "test-image-8",
351
+ [{"Name": "test-image-8", "ImageId": "ami-123"}],
352
+ [{"Name": "/awspub-test/param1", "Value": "ami-123"}],
353
+ True,
354
+ False,
355
+ ),
356
+ # with image, no parameter, with overwrite
357
+ ("test-image-9", [{"Name": "test-image-8", "ImageId": "ami-123"}], [], False, True),
358
+ # with image, with parameter, with overwrite
359
+ (
360
+ "test-image-9",
361
+ [{"Name": "test-image-8", "ImageId": "ami-123"}],
362
+ [{"Name": "/awspub-test/param1", "Value": "ami-123"}],
363
+ False,
364
+ True,
365
+ ),
366
+ ],
367
+ )
368
+ def test_image__put_ssm_parameters(
369
+ imagename, describe_images, get_parameters, get_parameters_called, put_parameter_called
370
+ ):
371
+ """
372
+ Test the _put_ssm_parameters() method
373
+ """
374
+ with patch("boto3.client") as bclient_mock:
375
+ instance = bclient_mock.return_value
376
+ instance.describe_images.return_value = {"Images": describe_images}
377
+ instance.get_parameters.return_value = {"Parameters": get_parameters}
378
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
379
+ img = image.Image(ctx, imagename)
380
+ img._put_ssm_parameters()
381
+ assert instance.get_parameters.called == get_parameters_called
382
+ assert instance.put_parameter.called == put_parameter_called
383
+
384
+
385
+ @pytest.mark.parametrize(
386
+ "image_found,config,config_image_name, expected_problems",
387
+ [
388
+ # image not available
389
+ ([], "fixtures/config1.yaml", "test-image-6", [image.ImageVerificationErrors.NOT_EXIST]),
390
+ # image matches expectations from config
391
+ (
392
+ [
393
+ {
394
+ "Name": "test-image-6",
395
+ "State": "available",
396
+ "ImageId": "ami-123",
397
+ "RootDeviceName": "/dev/sda1",
398
+ "RootDeviceType": "ebs",
399
+ "BootMode": "uefi-preferred",
400
+ "BlockDeviceMappings": [
401
+ {
402
+ "DeviceName": "/dev/sda1",
403
+ "Ebs": {
404
+ "DeleteOnTermination": True,
405
+ "VolumeType": "gp3",
406
+ "VolumeSize": 8,
407
+ "SnapshotId": "snap-123",
408
+ },
409
+ },
410
+ ],
411
+ "Tags": [
412
+ {"Key": "name", "Value": "foobar"},
413
+ ],
414
+ }
415
+ ],
416
+ "fixtures/config1.yaml",
417
+ "test-image-6",
418
+ [],
419
+ ),
420
+ ],
421
+ )
422
+ def test_image__verify(image_found, config, config_image_name, expected_problems):
423
+ """
424
+ Test _verify() for a given image and configuration
425
+ """
426
+ with patch("boto3.client") as bclient_mock:
427
+ instance = bclient_mock.return_value
428
+ instance.describe_images.return_value = {"Images": image_found}
429
+ instance.describe_snapshots.return_value = {"Snapshots": [{"State": "completed"}]}
430
+ ctx = context.Context(curdir / config, None)
431
+ img = image.Image(ctx, config_image_name)
432
+ problems = img._verify("eu-central-1")
433
+ assert problems == expected_problems
@@ -0,0 +1,44 @@
1
+ import pathlib
2
+ from unittest.mock import patch
3
+
4
+ import pytest
5
+
6
+ from awspub import context, image_marketplace
7
+
8
+ curdir = pathlib.Path(__file__).parent.resolve()
9
+
10
+
11
+ @pytest.mark.parametrize(
12
+ "imagename,new_version,called_start_change_set",
13
+ [
14
+ # same version that already exists
15
+ ("test-image-8", "1.0.0", False),
16
+ # new version
17
+ ("test-image-8", "2.0.0", True),
18
+ ],
19
+ )
20
+ def test_image_marketplace_request_new_version(imagename, new_version, called_start_change_set):
21
+ """
22
+ Test the request_new_version logic
23
+ """
24
+ with patch("boto3.client") as bclient_mock:
25
+ instance = bclient_mock.return_value
26
+ instance.describe_entity.return_value = {"DetailsDocument": {"Versions": [{"VersionTitle": new_version}]}}
27
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
28
+ img = image_marketplace.ImageMarketplace(ctx, imagename)
29
+ img.request_new_version("ami-123")
30
+ assert instance.start_change_set.called == called_start_change_set
31
+
32
+
33
+ @pytest.mark.parametrize(
34
+ "name,expected",
35
+ [
36
+ ("1.0.0", "1.0.0"),
37
+ ("1.0.0 (testing)", "1.0.0 testing"),
38
+ ("a sentence with spaces", "a sentence with spaces"),
39
+ ("_+=.:@-", "_+=.:@-"),
40
+ ("(parens) [brackets] |pipes|", "parens brackets pipes"),
41
+ ],
42
+ )
43
+ def test_changeset_name_sanitization(name, expected):
44
+ assert image_marketplace.ImageMarketplace.sanitize_changeset_name(name) == expected
@@ -0,0 +1,74 @@
1
+ import pathlib
2
+ from unittest.mock import patch
3
+
4
+ import pytest
5
+
6
+ from awspub import context, s3
7
+ from awspub.exceptions import BucketDoesNotExistException
8
+
9
+ curdir = pathlib.Path(__file__).parent.resolve()
10
+
11
+
12
+ @pytest.mark.parametrize(
13
+ "list_multipart_uploads_resp,create_multipart_upload_called",
14
+ [
15
+ # no available uploads - create one
16
+ ([], True),
17
+ # one available upload with non-matching key
18
+ ([{"UploadId": "abc", "Key": "does-not-match"}], True),
19
+ # multiple available upload with non-matching key
20
+ ([{"UploadId": "abc", "Key": "does-not-match"}, {"UploadId": "def", "Key": "does-not-match2"}], True),
21
+ # one available upload with matching key
22
+ ([{"UploadId": "abc", "Key": "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8"}], False),
23
+ # multiple available upload with one matching key
24
+ (
25
+ [
26
+ {"UploadId": "abc", "Key": "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8"},
27
+ {"UploadId": "abc", "Key": "does-not-match"},
28
+ ],
29
+ False,
30
+ ),
31
+ # multiple available upload with multiple matching keys
32
+ (
33
+ [
34
+ {"UploadId": "abc", "Key": "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8"},
35
+ {"UploadId": "def", "Key": "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8"},
36
+ ],
37
+ False,
38
+ ),
39
+ ],
40
+ )
41
+ def test_s3__get_multipart_upload_id(list_multipart_uploads_resp, create_multipart_upload_called):
42
+ """
43
+ test the _get_multipart_upload_id() function
44
+ """
45
+
46
+ with patch("boto3.client") as bclient_mock:
47
+ instance = bclient_mock.return_value
48
+ instance.list_multipart_uploads.return_value = {"Uploads": list_multipart_uploads_resp}
49
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
50
+ sthree = s3.S3(ctx)
51
+ sthree._get_multipart_upload_id()
52
+ assert instance.create_multipart_upload.called == create_multipart_upload_called
53
+
54
+
55
+ @patch("awspub.s3.S3._bucket_exists", return_value=True)
56
+ @patch("awspub.s3.boto3")
57
+ def test_s3_bucket_region_bucket_exists(boto3_mock, bucket_exists_mock):
58
+ region_name = "sample-region-1"
59
+ head_bucket = {"BucketRegion": region_name}
60
+ boto3_mock.client.return_value.head_bucket.return_value = head_bucket
61
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
62
+ sthree = s3.S3(ctx)
63
+
64
+ assert sthree.bucket_region == region_name
65
+
66
+
67
+ @patch("awspub.s3.S3._bucket_exists", return_value=False)
68
+ @patch("boto3.client")
69
+ def test_s3_bucket_region_bucket_not_exists(bclient_mock, bucket_exists_mock):
70
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
71
+ sthree = s3.S3(ctx)
72
+
73
+ with pytest.raises(BucketDoesNotExistException):
74
+ sthree.bucket_region()
@@ -0,0 +1,122 @@
1
+ import pathlib
2
+ from unittest.mock import MagicMock
3
+
4
+ import pytest
5
+
6
+ from awspub import context, snapshot
7
+
8
+ curdir = pathlib.Path(__file__).parent.resolve()
9
+
10
+
11
+ def test_snapshot__get_none_exist():
12
+ """
13
+ No snapshot exist - should return None
14
+ """
15
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
16
+ s = snapshot.Snapshot(ctx)
17
+ client_mock = MagicMock()
18
+ assert s._get(client_mock, "snapshot-name") is None
19
+ client_mock.describe_snapshots.assert_called_with(
20
+ Filters=[
21
+ {"Name": "tag:Name", "Values": ["snapshot-name"]},
22
+ {"Name": "status", "Values": ["pending", "completed"]},
23
+ ],
24
+ OwnerIds=["self"],
25
+ )
26
+
27
+
28
+ def test_snapshot__get_one_exist():
29
+ """
30
+ One snapshot exist with the same name - should return the snapshot id
31
+ """
32
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
33
+ s = snapshot.Snapshot(ctx)
34
+ client_mock = MagicMock()
35
+ client_mock.describe_snapshots = MagicMock(return_value={"Snapshots": [{"SnapshotId": "snap-1"}]})
36
+ assert s._get(client_mock, "snapshot-name") == "snap-1"
37
+ client_mock.describe_snapshots.assert_called_with(
38
+ Filters=[
39
+ {"Name": "tag:Name", "Values": ["snapshot-name"]},
40
+ {"Name": "status", "Values": ["pending", "completed"]},
41
+ ],
42
+ OwnerIds=["self"],
43
+ )
44
+
45
+
46
+ def test_snapshot__get_multiple_exist():
47
+ """
48
+ Multiple snapshots exist - _get() should raise an Exception
49
+ """
50
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
51
+ s = snapshot.Snapshot(ctx)
52
+ client_mock = MagicMock()
53
+ client_mock.describe_snapshots = MagicMock(
54
+ return_value={"Snapshots": [{"SnapshotId": "snap-1"}, {"SnapshotId": "snap-2"}]}
55
+ )
56
+ with pytest.raises(Exception):
57
+ s._get(client_mock, "snapshot-name")
58
+ client_mock.describe_snapshots.assert_called_with(
59
+ Filters=[
60
+ {"Name": "tag:Name", "Values": ["snapshot-name"]},
61
+ {"Name": "status", "Values": ["pending", "completed"]},
62
+ ],
63
+ OwnerIds=["self"],
64
+ )
65
+
66
+
67
+ def test_snapshot__get_import_snapshot_task_completed():
68
+ """
69
+ Test the Snapshot._get_import_snapshot_task() method
70
+ """
71
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
72
+ s = snapshot.Snapshot(ctx)
73
+ client_mock = MagicMock()
74
+ client_mock.describe_import_snapshot_tasks = MagicMock(
75
+ return_value={
76
+ "ImportSnapshotTasks": [
77
+ {
78
+ "ImportTaskId": "import-snap-08b79d7b5d382d56b",
79
+ "SnapshotTaskDetail": {
80
+ "SnapshotId": "snap-0e0f3407a1b541c40",
81
+ "Status": "completed",
82
+ },
83
+ "Tags": [
84
+ {"Key": "Name", "Value": "021abb3f2338b5e57b5d870816565429659bc70769d71c486234ad60fe6aec67"},
85
+ ],
86
+ }
87
+ ],
88
+ }
89
+ )
90
+ assert (
91
+ s._get_import_snapshot_task(client_mock, "021abb3f2338b5e57b5d870816565429659bc70769d71c486234ad60fe6aec67")
92
+ is None
93
+ )
94
+
95
+
96
+ def test_snapshot__get_import_snapshot_task_active():
97
+ """
98
+ Test the Snapshot._get_import_snapshot_task() method
99
+ """
100
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
101
+ s = snapshot.Snapshot(ctx)
102
+ client_mock = MagicMock()
103
+ client_mock.describe_import_snapshot_tasks = MagicMock(
104
+ return_value={
105
+ "ImportSnapshotTasks": [
106
+ {
107
+ "ImportTaskId": "import-snap-08b79d7b5d382d56b",
108
+ "SnapshotTaskDetail": {
109
+ "SnapshotId": "snap-0e0f3407a1b541c40",
110
+ "Status": "active",
111
+ },
112
+ "Tags": [
113
+ {"Key": "Name", "Value": "021abb3f2338b5e57b5d870816565429659bc70769d71c486234ad60fe6aec67"},
114
+ ],
115
+ }
116
+ ],
117
+ }
118
+ )
119
+ assert (
120
+ s._get_import_snapshot_task(client_mock, "021abb3f2338b5e57b5d870816565429659bc70769d71c486234ad60fe6aec67")
121
+ == "import-snap-08b79d7b5d382d56b"
122
+ )