awspub 0.0.5__py3-none-any.whl → 0.0.6__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/common.py +18 -0
- awspub/configmodels.py +21 -2
- awspub/image.py +21 -2
- awspub/s3.py +1 -1
- awspub/tests/fixtures/config1.yaml +5 -0
- awspub/tests/test_common.py +16 -0
- awspub/tests/test_image.py +20 -0
- {awspub-0.0.5.dist-info → awspub-0.0.6.dist-info}/METADATA +1 -1
- {awspub-0.0.5.dist-info → awspub-0.0.6.dist-info}/RECORD +12 -10
- {awspub-0.0.5.dist-info → awspub-0.0.6.dist-info}/LICENSE +0 -0
- {awspub-0.0.5.dist-info → awspub-0.0.6.dist-info}/WHEEL +0 -0
- {awspub-0.0.5.dist-info → awspub-0.0.6.dist-info}/entry_points.txt +0 -0
awspub/common.py
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
from typing import Tuple
|
2
|
+
|
3
|
+
|
4
|
+
def _split_partition(val: str) -> Tuple[str, str]:
|
5
|
+
"""
|
6
|
+
Split a string into partition and resource, separated by a colon. If no partition is given, assume "aws"
|
7
|
+
:param val: the string to split
|
8
|
+
:type val: str
|
9
|
+
:return: the partition and the resource
|
10
|
+
:rtype: Tuple[str, str]
|
11
|
+
"""
|
12
|
+
if ":" in val:
|
13
|
+
partition, resource = val.split(":")
|
14
|
+
else:
|
15
|
+
# if no partition is given, assume default commercial partition "aws"
|
16
|
+
partition = "aws"
|
17
|
+
resource = val
|
18
|
+
return partition, resource
|
awspub/configmodels.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
import pathlib
|
2
2
|
from typing import Dict, List, Literal, Optional
|
3
3
|
|
4
|
-
from pydantic import BaseModel, ConfigDict, Field
|
4
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
5
|
+
|
6
|
+
from awspub.common import _split_partition
|
5
7
|
|
6
8
|
|
7
9
|
class ConfigS3Model(BaseModel):
|
@@ -124,7 +126,9 @@ class ConfigImageModel(BaseModel):
|
|
124
126
|
)
|
125
127
|
imds_support: Optional[Literal["v2.0"]] = Field(description="Optional IMDS support", default=None)
|
126
128
|
share: Optional[List[str]] = Field(
|
127
|
-
description="Optional list of account IDs the image and snapshot will be shared with"
|
129
|
+
description="Optional list of account IDs the image and snapshot will be shared with. The account"
|
130
|
+
"ID can be prefixed with the partition and separated by ':'. Eg 'aws-cn:123456789123'",
|
131
|
+
default=None,
|
128
132
|
)
|
129
133
|
temporary: Optional[bool] = Field(
|
130
134
|
description="Optional boolean field indicates that a image is only temporary", default=False
|
@@ -145,6 +149,21 @@ class ConfigImageModel(BaseModel):
|
|
145
149
|
groups: Optional[List[str]] = Field(description="Optional list of groups this image is part of", default=[])
|
146
150
|
tags: Optional[Dict[str, str]] = Field(description="Optional Tags to apply to this image only", default={})
|
147
151
|
|
152
|
+
@field_validator("share")
|
153
|
+
@classmethod
|
154
|
+
def check_share(cls, v: Optional[List[str]]) -> Optional[List[str]]:
|
155
|
+
"""
|
156
|
+
Make sure the account IDs are valid and if given the partition is correct
|
157
|
+
"""
|
158
|
+
if v is not None:
|
159
|
+
for val in v:
|
160
|
+
partition, account_id = _split_partition(val)
|
161
|
+
if len(account_id) != 12:
|
162
|
+
raise ValueError("Account ID must be 12 characters long")
|
163
|
+
if partition not in ["aws", "aws-cn", "aws-us-gov"]:
|
164
|
+
raise ValueError("Partition must be one of 'aws', 'aws-cn', 'aws-us-gov'")
|
165
|
+
return v
|
166
|
+
|
148
167
|
|
149
168
|
class ConfigModel(BaseModel):
|
150
169
|
"""
|
awspub/image.py
CHANGED
@@ -9,6 +9,7 @@ from mypy_boto3_ec2.client import EC2Client
|
|
9
9
|
from mypy_boto3_ssm import SSMClient
|
10
10
|
|
11
11
|
from awspub import exceptions
|
12
|
+
from awspub.common import _split_partition
|
12
13
|
from awspub.context import Context
|
13
14
|
from awspub.image_marketplace import ImageMarketplace
|
14
15
|
from awspub.s3 import S3
|
@@ -159,16 +160,34 @@ class Image:
|
|
159
160
|
tags.append({"Key": name, "Value": value})
|
160
161
|
return tags
|
161
162
|
|
163
|
+
def _share_list_filtered(self, share_conf: List[str]) -> List[Dict[str, str]]:
|
164
|
+
"""
|
165
|
+
Get a filtered list of share configurations based on the current partition
|
166
|
+
:param share_conf: the share configuration
|
167
|
+
:type share_conf: List[str]
|
168
|
+
:return: a List of share configurations that is usable by modify_image_attribute()
|
169
|
+
:rtype: List[Dict[str, str]]
|
170
|
+
"""
|
171
|
+
# the current partition
|
172
|
+
partition_current = boto3.client("ec2").meta.partition
|
173
|
+
|
174
|
+
share_list: List[Dict[str, str]] = []
|
175
|
+
for share in share_conf:
|
176
|
+
partition, account_id = _split_partition(share)
|
177
|
+
if partition == partition_current:
|
178
|
+
share_list.append({"UserId": account_id})
|
179
|
+
return share_list
|
180
|
+
|
162
181
|
def _share(self, share_conf: List[str], images: Dict[str, _ImageInfo]):
|
163
182
|
"""
|
164
183
|
Share images with accounts
|
165
184
|
|
166
|
-
:param share_conf: the share configuration
|
185
|
+
:param share_conf: the share configuration containing list
|
167
186
|
:type share_conf: List[str]
|
168
187
|
:param images: a Dict with region names as keys and _ImageInfo objects as values
|
169
188
|
:type images: Dict[str, _ImageInfo]
|
170
189
|
"""
|
171
|
-
share_list
|
190
|
+
share_list = self._share_list_filtered(share_conf)
|
172
191
|
|
173
192
|
for region, image_info in images.items():
|
174
193
|
ec2client: EC2Client = boto3.client("ec2", region_name=region)
|
awspub/s3.py
CHANGED
@@ -78,6 +78,11 @@ awspub:
|
|
78
78
|
public: true
|
79
79
|
tags:
|
80
80
|
key1: value1
|
81
|
+
share:
|
82
|
+
- "123456789123"
|
83
|
+
- "221020170000"
|
84
|
+
- "aws:290620200000"
|
85
|
+
- "aws-cn:334455667788"
|
81
86
|
marketplace:
|
82
87
|
entity_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
83
88
|
access_role_arn: "arn:aws:iam::xxxxxxxxxxxx:role/AWSMarketplaceAccess"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from awspub.common import _split_partition
|
4
|
+
|
5
|
+
|
6
|
+
@pytest.mark.parametrize(
|
7
|
+
"input,expected_output",
|
8
|
+
[
|
9
|
+
("123456789123", ("aws", "123456789123")),
|
10
|
+
("aws:123456789123", ("aws", "123456789123")),
|
11
|
+
("aws-cn:123456789123", ("aws-cn", "123456789123")),
|
12
|
+
("aws-us-gov:123456789123", ("aws-us-gov", "123456789123")),
|
13
|
+
],
|
14
|
+
)
|
15
|
+
def test_common__split_partition(input, expected_output):
|
16
|
+
assert _split_partition(input) == expected_output
|
awspub/tests/test_image.py
CHANGED
@@ -456,3 +456,23 @@ def test_image__verify(image_found, config, config_image_name, expected_problems
|
|
456
456
|
img = image.Image(ctx, config_image_name)
|
457
457
|
problems = img._verify("eu-central-1")
|
458
458
|
assert problems == expected_problems
|
459
|
+
|
460
|
+
|
461
|
+
@pytest.mark.parametrize(
|
462
|
+
"partition,imagename,share_list_expected",
|
463
|
+
[
|
464
|
+
("aws", "test-image-8", [{"UserId": "123456789123"}, {"UserId": "221020170000"}, {"UserId": "290620200000"}]),
|
465
|
+
("aws-cn", "test-image-8", [{"UserId": "334455667788"}]),
|
466
|
+
("aws-us-gov", "test-image-8", []),
|
467
|
+
],
|
468
|
+
)
|
469
|
+
def test_image__share_list_filtered(partition, imagename, share_list_expected):
|
470
|
+
"""
|
471
|
+
Test _share_list_filtered() for a given image
|
472
|
+
"""
|
473
|
+
with patch("boto3.client") as bclient_mock:
|
474
|
+
instance = bclient_mock.return_value
|
475
|
+
instance.meta.partition = partition
|
476
|
+
ctx = context.Context(curdir / "fixtures/config1.yaml", None)
|
477
|
+
img = image.Image(ctx, imagename)
|
478
|
+
assert img._share_list_filtered(img.conf["share"]) == share_list_expected
|
@@ -1,31 +1,33 @@
|
|
1
1
|
awspub/__init__.py,sha256=7hgLrq6k53yaJrjFe7X5Cm45z3SIc1Vxocb5k3G8xPc,124
|
2
2
|
awspub/api.py,sha256=d1gx9LdqdYXRLf8yZ_spIz_93WhB2GNnCG_x3ABrMkI,6497
|
3
3
|
awspub/cli/__init__.py,sha256=-zCBEbnt5zbvSZ8PxQALpPAy0CiQUf-qZnikJ7U4Sf0,5621
|
4
|
-
awspub/
|
4
|
+
awspub/common.py,sha256=M_Ibw8DoAHG3oLoK5qRUggEjI7kJSSslC7r9VySe8vk,562
|
5
|
+
awspub/configmodels.py,sha256=DMrC3N8V_zj2SuBRJu27dxxY4Um5rcemWFFqMlA6j9E,7824
|
5
6
|
awspub/context.py,sha256=LDkp9Sz5AqRxQq70ICgFIJn5g2qrc5qiVawTyS_rXZE,4064
|
6
7
|
awspub/exceptions.py,sha256=SbGf9XyiGlj6estlraAwWAKLtuEfzwEuAbHXYiCiJD0,447
|
7
|
-
awspub/image.py,sha256=
|
8
|
+
awspub/image.py,sha256=1oJ5x4WljJt4C119qj7b0n9HRXAb3Mi_d_2g5_vRT8o,27451
|
8
9
|
awspub/image_marketplace.py,sha256=oiD7yNU5quG5CQG9Ql5Ut9hLWA1yewg6qVwTbyadGwc,5314
|
9
|
-
awspub/s3.py,sha256=
|
10
|
+
awspub/s3.py,sha256=ivR8DuAkYilph73EjFkTgUelkXxU7pZfosnsHHyoZkQ,11274
|
10
11
|
awspub/snapshot.py,sha256=V5e_07SnmCwEPjRmwZh43spWparhH8X4ugG16uQfGuo,10040
|
11
12
|
awspub/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
13
|
awspub/tests/fixtures/config-invalid-s3-extra.yaml,sha256=TdgqE-quxgueXS9L8ixsRuG6eTVfqalZ41G3JNCWn58,288
|
13
14
|
awspub/tests/fixtures/config-minimal.yaml,sha256=oHupXHYQXxmqgN2qFCAwvxzR7Bch-3yScrmMXeMIICE,176
|
14
15
|
awspub/tests/fixtures/config-valid-nonawspub.yaml,sha256=Md-YINQQRo3kveikUxk8Co9BYIZfDftmPT2LmIqoTL4,330
|
15
16
|
awspub/tests/fixtures/config1.vmdk,sha256=YlJHVAi5-e5kRSthHXBqB4gxqZsSPbadFE2HigSIoKg,65536
|
16
|
-
awspub/tests/fixtures/config1.yaml,sha256=
|
17
|
+
awspub/tests/fixtures/config1.yaml,sha256=QUxX7j7SNP40CeSIRFcXm54Ef2CmzgDeWfYYy_THlM0,3256
|
17
18
|
awspub/tests/fixtures/config2-mapping.yaml,sha256=lqJE0ej9DdGsE8O5dqG5PX7bOJrY4nMciXoOzMzV-so,31
|
18
19
|
awspub/tests/fixtures/config2.yaml,sha256=m2v-n1T-XPGDHyrJXArC_rYV-ZPMr9cgzHkLXiSRuDs,1250
|
19
20
|
awspub/tests/fixtures/config3-duplicate-keys.yaml,sha256=Cn0tTQawpEFocDNpWxDz1651uQa7aw88XjNyPcCG4iQ,324
|
20
21
|
awspub/tests/test_api.py,sha256=7MKm2aCtcvHJ0x_o2qinljfL9xFBWnasUnVpBxB37w8,2504
|
21
22
|
awspub/tests/test_cli.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
|
+
awspub/tests/test_common.py,sha256=kytMUU47uZYYe302XswdO15qX_i1vO2LS5n96--TcSU,478
|
22
24
|
awspub/tests/test_context.py,sha256=wMXQqj4vi2U3q5w1xPV-stB3mp3K6puUyXhsShJG4wA,3115
|
23
|
-
awspub/tests/test_image.py,sha256=
|
25
|
+
awspub/tests/test_image.py,sha256=tMcMx8rnx0q3oeRBA3JSeOHVxnnUGG_AAHVsZ7DWNYw,19083
|
24
26
|
awspub/tests/test_image_marketplace.py,sha256=JP7PrFjix1AyQg7eEaQ-wCROVoIOb873koseniOqGQQ,1456
|
25
27
|
awspub/tests/test_s3.py,sha256=UJL8CQDEvhA42MwPGeSvSbQFj8h86c1LrLFDvcMcRws,2857
|
26
28
|
awspub/tests/test_snapshot.py,sha256=8KPTqGVyzrpivWuq3HE7ZhgtLllcr3rA_3hZcxu2xjg,4123
|
27
|
-
awspub-0.0.
|
28
|
-
awspub-0.0.
|
29
|
-
awspub-0.0.
|
30
|
-
awspub-0.0.
|
31
|
-
awspub-0.0.
|
29
|
+
awspub-0.0.6.dist-info/LICENSE,sha256=9GbrzFQ3rWjVKj-IZnX1kGDsIGIdjc25KGRmAp03Jn0,35150
|
30
|
+
awspub-0.0.6.dist-info/METADATA,sha256=0Dk6LfbKHJXh--WbmzrPtLtK75hJNs_G6bpqzN6D2iM,1773
|
31
|
+
awspub-0.0.6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
32
|
+
awspub-0.0.6.dist-info/entry_points.txt,sha256=hrQzy9P5yO58nj6W0UDPdQPUTqEkQLpMvuyDDRu7LRQ,42
|
33
|
+
awspub-0.0.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|