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.
- awspub/__init__.py +3 -0
- awspub/api.py +165 -0
- awspub/cli/__init__.py +146 -0
- awspub/common.py +64 -0
- awspub/configmodels.py +216 -0
- awspub/context.py +108 -0
- awspub/exceptions.py +28 -0
- awspub/image.py +656 -0
- awspub/image_marketplace.py +120 -0
- awspub/s3.py +262 -0
- awspub/snapshot.py +241 -0
- awspub/sns.py +105 -0
- awspub/tests/__init__.py +0 -0
- awspub/tests/fixtures/config-invalid-s3-extra.yaml +12 -0
- awspub/tests/fixtures/config-minimal.yaml +12 -0
- awspub/tests/fixtures/config-valid-nonawspub.yaml +13 -0
- awspub/tests/fixtures/config1.vmdk +0 -0
- awspub/tests/fixtures/config1.yaml +171 -0
- awspub/tests/fixtures/config2-mapping.yaml +2 -0
- awspub/tests/fixtures/config2.yaml +48 -0
- awspub/tests/fixtures/config3-duplicate-keys.yaml +18 -0
- awspub/tests/test_api.py +89 -0
- awspub/tests/test_cli.py +0 -0
- awspub/tests/test_common.py +34 -0
- awspub/tests/test_context.py +88 -0
- awspub/tests/test_image.py +556 -0
- awspub/tests/test_image_marketplace.py +44 -0
- awspub/tests/test_s3.py +74 -0
- awspub/tests/test_snapshot.py +122 -0
- awspub/tests/test_sns.py +189 -0
- awspub-0.0.10.dist-info/LICENSE +675 -0
- awspub-0.0.10.dist-info/METADATA +46 -0
- awspub-0.0.10.dist-info/RECORD +35 -0
- awspub-0.0.10.dist-info/WHEEL +4 -0
- awspub-0.0.10.dist-info/entry_points.txt +3 -0
awspub/sns.py
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
"""
|
2
|
+
Methods used to handle notifications for AWS using SNS
|
3
|
+
"""
|
4
|
+
|
5
|
+
import json
|
6
|
+
import logging
|
7
|
+
from typing import Any, Dict, List
|
8
|
+
|
9
|
+
import boto3
|
10
|
+
from botocore.exceptions import ClientError
|
11
|
+
from mypy_boto3_sns.client import SNSClient
|
12
|
+
from mypy_boto3_sts.client import STSClient
|
13
|
+
|
14
|
+
from awspub.common import _get_regions
|
15
|
+
from awspub.context import Context
|
16
|
+
from awspub.exceptions import AWSAuthorizationException, AWSNotificationException
|
17
|
+
from awspub.s3 import S3
|
18
|
+
|
19
|
+
logger = logging.getLogger(__name__)
|
20
|
+
|
21
|
+
|
22
|
+
class SNSNotification(object):
|
23
|
+
"""
|
24
|
+
A data object that contains validation logic and
|
25
|
+
structuring rules for SNS notification JSON
|
26
|
+
"""
|
27
|
+
|
28
|
+
def __init__(self, context: Context, image_name: str):
|
29
|
+
"""
|
30
|
+
Construct a message and verify that it is valid
|
31
|
+
"""
|
32
|
+
self._ctx: Context = context
|
33
|
+
self._image_name: str = image_name
|
34
|
+
self._s3: S3 = S3(context)
|
35
|
+
|
36
|
+
@property
|
37
|
+
def conf(self) -> List[Dict[str, Any]]:
|
38
|
+
"""
|
39
|
+
The sns configuration for the current image (based on "image_name") from context
|
40
|
+
"""
|
41
|
+
return self._ctx.conf["images"][self._image_name]["sns"]
|
42
|
+
|
43
|
+
def _sns_regions(self, topic_config: Dict[Any, Any]) -> List[str]:
|
44
|
+
"""
|
45
|
+
Get the sns regions. Either configured in the sns configuration
|
46
|
+
or all available regions.
|
47
|
+
If a region is listed that is not available in the currently used partition,
|
48
|
+
that region will be ignored (eg. having us-east-1 configured but running in the aws-cn
|
49
|
+
partition doesn't include us-east-1 here).
|
50
|
+
"""
|
51
|
+
|
52
|
+
regions_configured = topic_config["regions"] if "regions" in topic_config else []
|
53
|
+
sns_regions = _get_regions(self._s3.bucket_region, regions_configured)
|
54
|
+
|
55
|
+
return sns_regions
|
56
|
+
|
57
|
+
def _get_topic_arn(self, topic_name: str, region_name: str) -> str:
|
58
|
+
"""
|
59
|
+
Calculate topic ARN based on partition, region, account and topic name
|
60
|
+
:param topic_name: Name of topic
|
61
|
+
:type topic_name: str
|
62
|
+
:param region_name: name of region
|
63
|
+
:type region_name: str
|
64
|
+
:return: return topic ARN
|
65
|
+
:rtype: str
|
66
|
+
"""
|
67
|
+
|
68
|
+
stsclient: STSClient = boto3.client("sts", region_name=region_name)
|
69
|
+
resp = stsclient.get_caller_identity()
|
70
|
+
|
71
|
+
account = resp["Account"]
|
72
|
+
# resp["Arn"] has string format "arn:partition:iam::accountnumber:user/iam_role"
|
73
|
+
partition = resp["Arn"].rsplit(":")[1]
|
74
|
+
|
75
|
+
return f"arn:{partition}:sns:{region_name}:{account}:{topic_name}"
|
76
|
+
|
77
|
+
def publish(self) -> None:
|
78
|
+
"""
|
79
|
+
send notification to subscribers
|
80
|
+
"""
|
81
|
+
|
82
|
+
for topic in self.conf:
|
83
|
+
for topic_name, topic_config in topic.items():
|
84
|
+
for region_name in self._sns_regions(topic_config):
|
85
|
+
snsclient: SNSClient = boto3.client("sns", region_name=region_name)
|
86
|
+
try:
|
87
|
+
snsclient.publish(
|
88
|
+
TopicArn=self._get_topic_arn(topic_name, region_name),
|
89
|
+
Subject=topic_config["subject"],
|
90
|
+
Message=json.dumps(topic_config["message"]),
|
91
|
+
MessageStructure="json",
|
92
|
+
)
|
93
|
+
except ClientError as e:
|
94
|
+
exception_code: str = e.response["Error"]["Code"]
|
95
|
+
if exception_code == "AuthorizationError":
|
96
|
+
raise AWSAuthorizationException(
|
97
|
+
"Profile does not have a permission to send the SNS notification."
|
98
|
+
" Please review the policy."
|
99
|
+
)
|
100
|
+
else:
|
101
|
+
raise AWSNotificationException(str(e))
|
102
|
+
logger.info(
|
103
|
+
f"The SNS notification {topic_config['subject']}"
|
104
|
+
f" for the topic {topic_name} in {region_name} has been sent."
|
105
|
+
)
|
awspub/tests/__init__.py
ADDED
File without changes
|
@@ -0,0 +1,12 @@
|
|
1
|
+
awspub:
|
2
|
+
s3:
|
3
|
+
bucket_name: "bucket1"
|
4
|
+
invalid_field: "not allowed" # This is an invalid field
|
5
|
+
source:
|
6
|
+
path: "config1.vmdk"
|
7
|
+
architecture: "x86_64"
|
8
|
+
images:
|
9
|
+
test-image:
|
10
|
+
description: "Test Image"
|
11
|
+
separate_snapshot: "False"
|
12
|
+
boot_mode: "uefi-preferred"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
awspub:
|
2
|
+
s3:
|
3
|
+
bucket_name: "bucket1"
|
4
|
+
source:
|
5
|
+
path: "config1.vmdk"
|
6
|
+
architecture: "x86_64"
|
7
|
+
images:
|
8
|
+
test-image:
|
9
|
+
description: "Test Image"
|
10
|
+
separate_snapshot: "False"
|
11
|
+
boot_mode: "uefi-preferred"
|
12
|
+
notawspub: # to make sure config outside of toplevel `awspub` dict is allowed
|
13
|
+
foo_bar: "irrelevant"
|
Binary file
|
@@ -0,0 +1,171 @@
|
|
1
|
+
awspub:
|
2
|
+
s3:
|
3
|
+
bucket_name: "bucket1"
|
4
|
+
|
5
|
+
source:
|
6
|
+
# config1.vmdk generated with
|
7
|
+
# dd if=/dev/zero of=config1.raw bs=1K count=1
|
8
|
+
# qemu-img convert -f raw -O vmdk -o subformat=streamOptimized config1.raw config1.vmdk
|
9
|
+
path: "config1.vmdk"
|
10
|
+
architecture: "x86_64"
|
11
|
+
|
12
|
+
images:
|
13
|
+
"test-image-1":
|
14
|
+
description: |
|
15
|
+
A test image
|
16
|
+
boot_mode: "uefi"
|
17
|
+
regions:
|
18
|
+
- region1
|
19
|
+
- region2
|
20
|
+
temporary: true
|
21
|
+
groups:
|
22
|
+
- group1
|
23
|
+
- group2
|
24
|
+
"test-image-2":
|
25
|
+
description: |
|
26
|
+
A test image with a separate snapshot
|
27
|
+
boot_mode: "uefi"
|
28
|
+
separate_snapshot: true
|
29
|
+
groups:
|
30
|
+
- group1
|
31
|
+
"test-image-3":
|
32
|
+
description: |
|
33
|
+
A test image with a separate snapshot and a billing code
|
34
|
+
boot_mode: "uefi"
|
35
|
+
separate_snapshot: true
|
36
|
+
billing_products:
|
37
|
+
- billingcode
|
38
|
+
"test-image-4":
|
39
|
+
description: |
|
40
|
+
A test image without a separate snapshot but a billing product
|
41
|
+
boot_mode: "uefi-preferred"
|
42
|
+
billing_products:
|
43
|
+
- billingcode
|
44
|
+
"test-image-5":
|
45
|
+
description: |
|
46
|
+
A test image without a separate snapshot but multiple billing products
|
47
|
+
boot_mode: "uefi-preferred"
|
48
|
+
billing_products:
|
49
|
+
- billingcode1
|
50
|
+
- billingcode2
|
51
|
+
"test-image-6":
|
52
|
+
description: |
|
53
|
+
A test image without a separate snapshot but multiple billing products
|
54
|
+
boot_mode: "uefi-preferred"
|
55
|
+
regions:
|
56
|
+
- "eu-central-1"
|
57
|
+
public: true
|
58
|
+
tags:
|
59
|
+
key1: value1
|
60
|
+
"test-image-7":
|
61
|
+
description: |
|
62
|
+
A test image without a separate snapshot but multiple billing products
|
63
|
+
boot_mode: "uefi-preferred"
|
64
|
+
regions:
|
65
|
+
- "eu-central-1"
|
66
|
+
public: true
|
67
|
+
temporary: true
|
68
|
+
tags:
|
69
|
+
key2: name
|
70
|
+
name: "not-foobar"
|
71
|
+
"test-image-8":
|
72
|
+
description: |
|
73
|
+
A test image without a separate snapshot but multiple billing products
|
74
|
+
boot_mode: "uefi-preferred"
|
75
|
+
regions:
|
76
|
+
- "eu-central-1"
|
77
|
+
- "us-east-1"
|
78
|
+
public: true
|
79
|
+
tags:
|
80
|
+
key1: value1
|
81
|
+
share:
|
82
|
+
- "123456789123"
|
83
|
+
- "221020170000"
|
84
|
+
- "aws:290620200000"
|
85
|
+
- "aws-cn:334455667788"
|
86
|
+
marketplace:
|
87
|
+
entity_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
88
|
+
access_role_arn: "arn:aws:iam::xxxxxxxxxxxx:role/AWSMarketplaceAccess"
|
89
|
+
version_title: "1.0.0"
|
90
|
+
release_notes: "N/A"
|
91
|
+
user_name: "ubuntu"
|
92
|
+
scanning_port: 22
|
93
|
+
os_name: "UBUNTU"
|
94
|
+
os_version: "22.04"
|
95
|
+
usage_instructions: |
|
96
|
+
You can use me
|
97
|
+
recommended_instance_type: "m5.large"
|
98
|
+
security_groups:
|
99
|
+
-
|
100
|
+
from_port: 22
|
101
|
+
ip_protocol: "tcp"
|
102
|
+
ip_ranges:
|
103
|
+
- "0.0.0.0/0"
|
104
|
+
to_port: 22
|
105
|
+
ssm_parameter:
|
106
|
+
-
|
107
|
+
name: /test/image
|
108
|
+
-
|
109
|
+
name: /test/another-image
|
110
|
+
"test-image-9":
|
111
|
+
boot_mode: "uefi"
|
112
|
+
description: |
|
113
|
+
A test image without a separate snapshot but multiple billing products
|
114
|
+
regions:
|
115
|
+
- "eu-central-1"
|
116
|
+
- "us-east-1"
|
117
|
+
ssm_parameter:
|
118
|
+
-
|
119
|
+
name: /awspub-test/param2
|
120
|
+
allow_overwrite: true
|
121
|
+
"test-image-10":
|
122
|
+
boot_mode: "uefi"
|
123
|
+
description: |
|
124
|
+
A test image without a separate snapshot but single sns configs
|
125
|
+
regions:
|
126
|
+
- "us-east-1"
|
127
|
+
sns:
|
128
|
+
- "topic1":
|
129
|
+
subject: "topic1-subject"
|
130
|
+
message:
|
131
|
+
default: "default-message"
|
132
|
+
email: "email-message"
|
133
|
+
regions:
|
134
|
+
- "us-east-1"
|
135
|
+
"test-image-11":
|
136
|
+
boot_mode: "uefi"
|
137
|
+
description: |
|
138
|
+
A test image without a separate snapshot but multiple sns configs
|
139
|
+
regions:
|
140
|
+
- "us-east-1"
|
141
|
+
- "eu-central-1"
|
142
|
+
sns:
|
143
|
+
- "topic1":
|
144
|
+
subject: "topic1-subject"
|
145
|
+
message:
|
146
|
+
default: "default-message"
|
147
|
+
email: "email-message"
|
148
|
+
regions:
|
149
|
+
- "us-east-1"
|
150
|
+
- "topic2":
|
151
|
+
subject: "topic2-subject"
|
152
|
+
message:
|
153
|
+
default: "default-message"
|
154
|
+
regions:
|
155
|
+
- "us-gov-1"
|
156
|
+
- "eu-central-1"
|
157
|
+
"test-image-12":
|
158
|
+
boot_mode: "uefi"
|
159
|
+
description: |
|
160
|
+
A test image without a separate snapshot but single sns configs
|
161
|
+
regions:
|
162
|
+
- "us-east-1"
|
163
|
+
sns:
|
164
|
+
- "topic1":
|
165
|
+
subject: "topic1-subject"
|
166
|
+
message:
|
167
|
+
default: "default-message"
|
168
|
+
email: "email-message"
|
169
|
+
|
170
|
+
tags:
|
171
|
+
name: "foobar"
|
@@ -0,0 +1,48 @@
|
|
1
|
+
awspub:
|
2
|
+
s3:
|
3
|
+
bucket_name: "bucket1"
|
4
|
+
|
5
|
+
source:
|
6
|
+
# config1.vmdk generated with
|
7
|
+
# dd if=/dev/zero of=config1.raw bs=1K count=1
|
8
|
+
# qemu-img convert -f raw -O vmdk -o subformat=streamOptimized config1.raw config1.vmdk
|
9
|
+
path: "config1.vmdk"
|
10
|
+
architecture: "x86_64"
|
11
|
+
|
12
|
+
images:
|
13
|
+
"test-image-$key1":
|
14
|
+
description: |
|
15
|
+
A test image
|
16
|
+
boot_mode: "uefi"
|
17
|
+
regions:
|
18
|
+
- region1
|
19
|
+
- region2
|
20
|
+
temporary: true
|
21
|
+
"test-image-$key2":
|
22
|
+
description: |
|
23
|
+
A test image with a separate snapshot
|
24
|
+
boot_mode: "uefi"
|
25
|
+
separate_snapshot: true
|
26
|
+
"test-image-3":
|
27
|
+
description: |
|
28
|
+
A test image with a separate snapshot and a billing code
|
29
|
+
boot_mode: "uefi"
|
30
|
+
separate_snapshot: true
|
31
|
+
billing_products:
|
32
|
+
- billingcode
|
33
|
+
"test-image-4":
|
34
|
+
description: |
|
35
|
+
A test image without a separate snapshot but a billing product
|
36
|
+
boot_mode: "uefi-preferred"
|
37
|
+
billing_products:
|
38
|
+
- billingcode
|
39
|
+
"test-image-5":
|
40
|
+
description: |
|
41
|
+
A test image without a separate snapshot but multiple billing products
|
42
|
+
boot_mode: "uefi-preferred"
|
43
|
+
billing_products:
|
44
|
+
- billingcode1
|
45
|
+
- billingcode2
|
46
|
+
|
47
|
+
tags:
|
48
|
+
name: "foobar"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
awspub:
|
2
|
+
s3:
|
3
|
+
bucket_name: "bucket1"
|
4
|
+
|
5
|
+
source:
|
6
|
+
path: "config1.vmdk"
|
7
|
+
architecture: "x86_64"
|
8
|
+
|
9
|
+
images:
|
10
|
+
"test-image-1":
|
11
|
+
description: |
|
12
|
+
A test image
|
13
|
+
boot_mode: "uefi"
|
14
|
+
# second image with the same key
|
15
|
+
"test-image-1":
|
16
|
+
description: |
|
17
|
+
A test image
|
18
|
+
boot_mode: "uefi"
|
awspub/tests/test_api.py
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
import pathlib
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from awspub import api, context, image
|
6
|
+
|
7
|
+
curdir = pathlib.Path(__file__).parent.resolve()
|
8
|
+
|
9
|
+
|
10
|
+
@pytest.mark.parametrize(
|
11
|
+
"group,expected_image_names",
|
12
|
+
[
|
13
|
+
# without any group, all images should be processed
|
14
|
+
(
|
15
|
+
None,
|
16
|
+
[
|
17
|
+
"test-image-1",
|
18
|
+
"test-image-2",
|
19
|
+
"test-image-3",
|
20
|
+
"test-image-4",
|
21
|
+
"test-image-5",
|
22
|
+
"test-image-6",
|
23
|
+
"test-image-7",
|
24
|
+
"test-image-8",
|
25
|
+
"test-image-9",
|
26
|
+
"test-image-10",
|
27
|
+
"test-image-11",
|
28
|
+
"test-image-12",
|
29
|
+
],
|
30
|
+
),
|
31
|
+
# with a group that no image as, no image should be processed
|
32
|
+
(
|
33
|
+
"group-not-used",
|
34
|
+
[],
|
35
|
+
),
|
36
|
+
# with a group that an image has
|
37
|
+
(
|
38
|
+
"group2",
|
39
|
+
["test-image-1"],
|
40
|
+
),
|
41
|
+
# with a group that multiple images have
|
42
|
+
(
|
43
|
+
"group1",
|
44
|
+
["test-image-1", "test-image-2"],
|
45
|
+
),
|
46
|
+
],
|
47
|
+
)
|
48
|
+
def test_api__images_filtered(group, expected_image_names):
|
49
|
+
"""
|
50
|
+
Test the _images_filtered() function
|
51
|
+
"""
|
52
|
+
ctx = context.Context(curdir / "fixtures/config1.yaml", None)
|
53
|
+
|
54
|
+
image_names = [i[0] for i in api._images_filtered(ctx, group)]
|
55
|
+
assert image_names == expected_image_names
|
56
|
+
|
57
|
+
|
58
|
+
@pytest.mark.parametrize(
|
59
|
+
"group,expected",
|
60
|
+
[
|
61
|
+
# without any group, all images should be processed
|
62
|
+
(
|
63
|
+
None,
|
64
|
+
(
|
65
|
+
{"test-image-1": {"eu-central-1": "ami-123", "eu-central-2": "ami-456"}},
|
66
|
+
{
|
67
|
+
"group1": {"test-image-1": {"eu-central-1": "ami-123", "eu-central-2": "ami-456"}},
|
68
|
+
"group2": {"test-image-1": {"eu-central-1": "ami-123", "eu-central-2": "ami-456"}},
|
69
|
+
},
|
70
|
+
),
|
71
|
+
),
|
72
|
+
# with a group that no image as, image should be there but nothing in the group
|
73
|
+
("group-not-used", ({"test-image-1": {"eu-central-1": "ami-123", "eu-central-2": "ami-456"}}, {})),
|
74
|
+
],
|
75
|
+
)
|
76
|
+
def test_api__images_grouped(group, expected):
|
77
|
+
"""
|
78
|
+
Test the _images_grouped() function
|
79
|
+
"""
|
80
|
+
ctx = context.Context(curdir / "fixtures/config1.yaml", None)
|
81
|
+
images = [
|
82
|
+
(
|
83
|
+
"test-image-1",
|
84
|
+
image.Image(ctx, "test-image-1"),
|
85
|
+
{"eu-central-1": image._ImageInfo("ami-123", None), "eu-central-2": image._ImageInfo("ami-456", None)},
|
86
|
+
)
|
87
|
+
]
|
88
|
+
grouped = api._images_grouped(images, group)
|
89
|
+
assert grouped == expected
|
awspub/tests/test_cli.py
ADDED
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from unittest.mock import patch
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from awspub.common import _get_regions, _split_partition
|
6
|
+
|
7
|
+
|
8
|
+
@pytest.mark.parametrize(
|
9
|
+
"input,expected_output",
|
10
|
+
[
|
11
|
+
("123456789123", ("aws", "123456789123")),
|
12
|
+
("aws:123456789123", ("aws", "123456789123")),
|
13
|
+
("aws-cn:123456789123", ("aws-cn", "123456789123")),
|
14
|
+
("aws-us-gov:123456789123", ("aws-us-gov", "123456789123")),
|
15
|
+
],
|
16
|
+
)
|
17
|
+
def test_common__split_partition(input, expected_output):
|
18
|
+
assert _split_partition(input) == expected_output
|
19
|
+
|
20
|
+
|
21
|
+
@pytest.mark.parametrize(
|
22
|
+
"regions_in_partition,configured_regions,expected_output",
|
23
|
+
[
|
24
|
+
(["region-1", "region-2"], ["region-1", "region-3"], ["region-1"]),
|
25
|
+
(["region-1", "region-2", "region-3"], ["region-4", "region-5"], []),
|
26
|
+
(["region-1", "region-2"], [], ["region-1", "region-2"]),
|
27
|
+
],
|
28
|
+
)
|
29
|
+
def test_common__get_regions(regions_in_partition, configured_regions, expected_output):
|
30
|
+
with patch("boto3.client") as bclient_mock:
|
31
|
+
instance = bclient_mock.return_value
|
32
|
+
instance.describe_regions.return_value = {"Regions": [{"RegionName": r} for r in regions_in_partition]}
|
33
|
+
|
34
|
+
assert _get_regions("", configured_regions) == expected_output
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import glob
|
2
|
+
import os
|
3
|
+
import pathlib
|
4
|
+
|
5
|
+
import pytest
|
6
|
+
from pydantic import ValidationError
|
7
|
+
from ruamel.yaml.constructor import DuplicateKeyError
|
8
|
+
|
9
|
+
from awspub import context
|
10
|
+
|
11
|
+
curdir = pathlib.Path(__file__).parent.resolve()
|
12
|
+
|
13
|
+
|
14
|
+
def test_context_create():
|
15
|
+
"""
|
16
|
+
Create a Context object from a given configuration
|
17
|
+
"""
|
18
|
+
ctx = context.Context(curdir / "fixtures/config1.yaml", None)
|
19
|
+
assert ctx.conf["source"]["path"] == curdir / "fixtures/config1.vmdk"
|
20
|
+
assert ctx.source_sha256 == "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8"
|
21
|
+
assert ctx.conf["source"]["architecture"] == "x86_64"
|
22
|
+
assert ctx.conf["s3"]["bucket_name"] == "bucket1"
|
23
|
+
|
24
|
+
|
25
|
+
def test_context_create_minimal():
|
26
|
+
"""
|
27
|
+
Create a Context object from a given minimal configuration
|
28
|
+
"""
|
29
|
+
ctx = context.Context(curdir / "fixtures/config-minimal.yaml", None)
|
30
|
+
assert ctx.conf["source"]["path"] == curdir / "fixtures/config1.vmdk"
|
31
|
+
assert ctx.source_sha256 == "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8"
|
32
|
+
assert ctx.conf["source"]["architecture"] == "x86_64"
|
33
|
+
assert ctx.conf["s3"]["bucket_name"] == "bucket1"
|
34
|
+
|
35
|
+
|
36
|
+
def test_context_create_with_mapping():
|
37
|
+
"""
|
38
|
+
Create a Context object from a given configuration
|
39
|
+
"""
|
40
|
+
ctx = context.Context(curdir / "fixtures/config2.yaml", curdir / "fixtures/config2-mapping.yaml")
|
41
|
+
assert ctx.conf["source"]["path"] == curdir / "fixtures/config1.vmdk"
|
42
|
+
assert ctx.source_sha256 == "6252475408b9f9ee64452b611d706a078831a99b123db69d144d878a0488a0a8"
|
43
|
+
assert ctx.conf["images"].get("test-image-value1")
|
44
|
+
assert ctx.conf["images"].get("test-image-value$2")
|
45
|
+
|
46
|
+
|
47
|
+
def test_context_with_docs_config_samples():
|
48
|
+
"""
|
49
|
+
Create a Context object with the sample config files used for documentation
|
50
|
+
"""
|
51
|
+
config_samples_dir = curdir.parents[1] / "docs" / "config-samples"
|
52
|
+
for f in glob.glob(f"{config_samples_dir}/*.yaml"):
|
53
|
+
mapping_file = f + ".mapping"
|
54
|
+
if os.path.exists(mapping_file):
|
55
|
+
mapping = mapping_file
|
56
|
+
else:
|
57
|
+
mapping = None
|
58
|
+
context.Context(os.path.join(config_samples_dir, f), mapping)
|
59
|
+
|
60
|
+
|
61
|
+
def test_context_with_duplicate_image_name():
|
62
|
+
"""
|
63
|
+
Create a context with a configuration file that contains a duplicate image name key
|
64
|
+
"""
|
65
|
+
with pytest.raises(DuplicateKeyError):
|
66
|
+
context.Context(curdir / "fixtures/config3-duplicate-keys.yaml", None)
|
67
|
+
|
68
|
+
|
69
|
+
@pytest.mark.parametrize(
|
70
|
+
"config_file",
|
71
|
+
["fixtures/config-minimal.yaml", "fixtures/config-valid-nonawspub.yaml"],
|
72
|
+
)
|
73
|
+
def test_valid_configuration(config_file):
|
74
|
+
"""
|
75
|
+
Test with a valid configuration file (no extra fields)
|
76
|
+
"""
|
77
|
+
ctx = context.Context(curdir / config_file, None)
|
78
|
+
assert ctx.conf is not None
|
79
|
+
assert ctx.conf["s3"]["bucket_name"] == "bucket1"
|
80
|
+
assert ctx.conf["source"]["architecture"] == "x86_64"
|
81
|
+
|
82
|
+
|
83
|
+
def test_invalid_configuration_extra_field():
|
84
|
+
"""
|
85
|
+
Test with an invalid configuration file that includes an extra field
|
86
|
+
"""
|
87
|
+
with pytest.raises(ValidationError):
|
88
|
+
context.Context(curdir / "fixtures/config-invalid-s3-extra.yaml", None)
|