awspub 0.0.10__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,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