awspub 0.0.10__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ )
@@ -0,0 +1,189 @@
1
+ import pathlib
2
+ from unittest.mock import patch
3
+
4
+ import botocore.exceptions
5
+ import pytest
6
+
7
+ from awspub import context, exceptions, sns
8
+
9
+ curdir = pathlib.Path(__file__).parent.resolve()
10
+
11
+
12
+ @pytest.mark.parametrize(
13
+ "imagename,called_sns_publish, publish_call_count",
14
+ [
15
+ ("test-image-10", True, 1),
16
+ ("test-image-11", True, 2),
17
+ ("test-image-12", True, 2),
18
+ ],
19
+ )
20
+ def test_sns_publish(imagename, called_sns_publish, publish_call_count):
21
+ """
22
+ Test the send_notification logic
23
+ """
24
+ with patch("boto3.client") as bclient_mock:
25
+ instance = bclient_mock.return_value
26
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
27
+ instance.describe_regions.return_value = {
28
+ "Regions": [{"RegionName": "eu-central-1"}, {"RegionName": "us-east-1"}]
29
+ }
30
+ instance.list_buckets.return_value = {"Buckets": [{"Name": "bucket1"}]}
31
+
32
+ sns.SNSNotification(ctx, imagename).publish()
33
+ assert instance.publish.called == called_sns_publish
34
+ assert instance.publish.call_count == publish_call_count
35
+
36
+
37
+ @pytest.mark.parametrize(
38
+ "imagename",
39
+ [
40
+ ("test-image-10"),
41
+ ("test-image-11"),
42
+ ("test-image-12"),
43
+ ],
44
+ )
45
+ def test_sns_publish_fail_with_invalid_topic(imagename):
46
+ """
47
+ Test the send_notification logic
48
+ """
49
+ with patch("boto3.client") as bclient_mock:
50
+ instance = bclient_mock.return_value
51
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
52
+ instance.describe_regions.return_value = {
53
+ "Regions": [{"RegionName": "eu-central-1"}, {"RegionName": "us-east-1"}]
54
+ }
55
+ instance.list_buckets.return_value = {"Buckets": [{"Name": "bucket1"}]}
56
+
57
+ # topic1 is invalid topic
58
+ def side_effect(*args, **kwargs):
59
+ topic_arn = kwargs.get("TopicArn")
60
+ if "topic1" in topic_arn and "us-east-1" in topic_arn:
61
+ error_reponse = {
62
+ "Error": {
63
+ "Code": "NotFoundException",
64
+ "Message": "An error occurred (NotFound) when calling the Publish operation: "
65
+ "Topic does not exist.",
66
+ }
67
+ }
68
+ raise botocore.exceptions.ClientError(error_reponse, "")
69
+
70
+ instance.publish.side_effect = side_effect
71
+
72
+ with pytest.raises(exceptions.AWSNotificationException):
73
+ sns.SNSNotification(ctx, imagename).publish()
74
+
75
+
76
+ @pytest.mark.parametrize(
77
+ "imagename",
78
+ [
79
+ ("test-image-10"),
80
+ ("test-image-11"),
81
+ ("test-image-12"),
82
+ ],
83
+ )
84
+ def test_sns_publish_fail_with_unauthorized_user(imagename):
85
+ """
86
+ Test the send_notification logic
87
+ """
88
+ with patch("boto3.client") as bclient_mock:
89
+ instance = bclient_mock.return_value
90
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
91
+ instance.describe_regions.return_value = {
92
+ "Regions": [{"RegionName": "eu-central-1"}, {"RegionName": "us-east-1"}]
93
+ }
94
+ instance.list_buckets.return_value = {"Buckets": [{"Name": "bucket1"}]}
95
+
96
+ error_reponse = {
97
+ "Error": {
98
+ "Code": "AuthorizationError",
99
+ "Message": "User are not authorized perform SNS Notification service",
100
+ }
101
+ }
102
+ instance.publish.side_effect = botocore.exceptions.ClientError(error_reponse, "")
103
+
104
+ with pytest.raises(exceptions.AWSAuthorizationException):
105
+ sns.SNSNotification(ctx, imagename).publish()
106
+
107
+
108
+ @pytest.mark.parametrize(
109
+ "imagename, partition, regions_in_partition, expected",
110
+ [
111
+ (
112
+ "test-image-10",
113
+ "aws-cn",
114
+ ["cn-north1", "cn-northwest-1"],
115
+ [],
116
+ ),
117
+ (
118
+ "test-image-11",
119
+ "aws",
120
+ ["us-east-1", "eu-central-1"],
121
+ [
122
+ "arn:aws:sns:us-east-1:1234:topic1",
123
+ "arn:aws:sns:eu-central-1:1234:topic2",
124
+ ],
125
+ ),
126
+ (
127
+ "test-image-12",
128
+ "aws",
129
+ ["us-east-1", "eu-central-1"],
130
+ [
131
+ "arn:aws:sns:us-east-1:1234:topic1",
132
+ "arn:aws:sns:eu-central-1:1234:topic1",
133
+ ],
134
+ ),
135
+ ],
136
+ )
137
+ def test_sns__get_topic_arn(imagename, partition, regions_in_partition, expected):
138
+ """
139
+ Test the send_notification logic
140
+ """
141
+ with patch("boto3.client") as bclient_mock:
142
+ instance = bclient_mock.return_value
143
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
144
+ sns_conf = ctx.conf["images"][imagename]["sns"]
145
+ instance.describe_regions.return_value = {"Regions": [{"RegionName": r} for r in regions_in_partition]}
146
+ instance.list_buckets.return_value = {"Buckets": [{"Name": "bucket1"}]}
147
+
148
+ instance.get_caller_identity.return_value = {"Account": "1234", "Arn": f"arn:{partition}:iam::1234:user/test"}
149
+
150
+ topic_arns = []
151
+ for topic in sns_conf:
152
+ for topic_name, topic_conf in topic.items():
153
+ sns_regions = sns.SNSNotification(ctx, imagename)._sns_regions(topic_conf)
154
+ for region in sns_regions:
155
+ res_arn = sns.SNSNotification(ctx, imagename)._get_topic_arn(topic_name, region)
156
+ topic_arns.append(res_arn)
157
+
158
+ assert topic_arns == expected
159
+
160
+
161
+ @pytest.mark.parametrize(
162
+ "imagename,regions_in_partition,regions_expected",
163
+ [
164
+ ("test-image-10", ["us-east-1", "eu-west-1"], {"topic1": ["us-east-1"]}),
165
+ (
166
+ "test-image-11",
167
+ ["us-east-1", "eu-west-1"],
168
+ {"topic1": ["us-east-1"], "topic2": []},
169
+ ),
170
+ ("test-image-12", ["eu-northwest-1", "ap-southeast-1"], {"topic1": ["eu-northwest-1", "ap-southeast-1"]}),
171
+ ],
172
+ )
173
+ def test_sns_regions(imagename, regions_in_partition, regions_expected):
174
+ """
175
+ Test the regions for a given image
176
+ """
177
+ with patch("boto3.client") as bclient_mock:
178
+ instance = bclient_mock.return_value
179
+ instance.describe_regions.return_value = {"Regions": [{"RegionName": r} for r in regions_in_partition]}
180
+ ctx = context.Context(curdir / "fixtures/config1.yaml", None)
181
+ sns_conf = ctx.conf["images"][imagename]["sns"]
182
+ instance.list_buckets.return_value = {"Buckets": [{"Name": "bucket1"}]}
183
+
184
+ sns_regions = {}
185
+ for topic in sns_conf:
186
+ for topic_name, topic_conf in topic.items():
187
+ sns_regions[topic_name] = sns.SNSNotification(ctx, imagename)._sns_regions(topic_conf)
188
+
189
+ assert sns_regions == regions_expected