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.
- 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)
|