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/context.py ADDED
@@ -0,0 +1,108 @@
1
+ import hashlib
2
+ import logging
3
+ import pathlib
4
+ from string import Template
5
+ from typing import Dict
6
+
7
+ from ruamel.yaml import YAML
8
+
9
+ from awspub.configmodels import ConfigModel
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class Context:
15
+ """
16
+ Context holds the used configuration and some
17
+ automatically calculated values
18
+ """
19
+
20
+ def __init__(self, conf_path: pathlib.Path, conf_template_mapping_path: pathlib.Path):
21
+ self._conf_path = conf_path
22
+ self._conf = None
23
+ self._conf_template_mapping_path = conf_template_mapping_path
24
+ self._conf_template_mapping = {}
25
+ yaml = YAML(typ="safe")
26
+
27
+ # read the config mapping first
28
+ if self._conf_template_mapping_path:
29
+ with open(self._conf_template_mapping_path, "r") as ctm:
30
+ self._conf_template_mapping = yaml.load(ctm)
31
+ logger.debug(f"loaded config template mapping for substitution: {self._conf_template_mapping}")
32
+
33
+ # read the config itself
34
+ with open(self._conf_path, "r") as f:
35
+ template = Template(f.read())
36
+ # substitute the values in the config with values from the config template mapping
37
+ ft = template.substitute(**self._conf_template_mapping)
38
+ y = yaml.load(ft)["awspub"]
39
+ self._conf = ConfigModel(**y).model_dump()
40
+ logger.debug(f"config loaded and validated as: {self._conf}")
41
+
42
+ # handle relative paths in config files. those are relative to the config file dirname
43
+ if not self.conf["source"]["path"].is_absolute():
44
+ self.conf["source"]["path"] = pathlib.Path(self._conf_path).parent / self.conf["source"]["path"]
45
+
46
+ for image_name, props in self.conf["images"].items():
47
+ if props["uefi_data"] and not self.conf["images"][image_name]["uefi_data"].is_absolute():
48
+ self.conf["images"][image_name]["uefi_data"] = (
49
+ pathlib.Path(self._conf_path).parent / self.conf["images"][image_name]["uefi_data"]
50
+ )
51
+
52
+ # calculate the sha256 sum of the source file once
53
+ self._source_sha256_obj = self._sha256sum(self.conf["source"]["path"])
54
+ self._source_sha256 = self._source_sha256_obj.hexdigest()
55
+
56
+ @property
57
+ def conf(self):
58
+ return self._conf
59
+
60
+ @property
61
+ def source_sha256(self):
62
+ """
63
+ The sha256 sum hexdigest of the source->path value from the given
64
+ configuration. This value is used in different places (eg. to automatically
65
+ upload to S3 with this value as key)
66
+ """
67
+ return self._source_sha256
68
+
69
+ @property
70
+ def tags_dict(self) -> Dict[str, str]:
71
+ """
72
+ Common tags which will be used for all AWS resources
73
+ This includes tags defined in the configuration file
74
+ but doesn't include image group specific tags.
75
+ Usually the tags() method should be used.
76
+ """
77
+ tags = dict()
78
+ tags["awspub:source:filename"] = self.conf["source"]["path"].name
79
+ tags["awspub:source:architecture"] = self.conf["source"]["architecture"]
80
+ tags["awspub:source:sha256"] = self.source_sha256
81
+ tags.update(self.conf.get("tags", {}))
82
+ return tags
83
+
84
+ @property
85
+ def tags(self):
86
+ """
87
+ Helper to make tags directly usable by the AWS EC2 API
88
+ which requires a list of dicts with "Key" and "Value" defined.
89
+ """
90
+ tags = []
91
+ for name, value in self.tags_dict.items():
92
+ tags.append({"Key": name, "Value": value})
93
+ return tags
94
+
95
+ def _sha256sum(self, file_path: pathlib.Path):
96
+ """
97
+ Calculate a sha256 sum for a given file
98
+
99
+ :param file_path: the path to the local file to upload
100
+ :type file_path: pathlib.Path
101
+ :return: a haslib Hash object
102
+ :rtype: _hashlib.HASH
103
+ """
104
+ sha256_hash = hashlib.sha256()
105
+ with open(file_path.resolve(), "rb") as f:
106
+ for byte_block in iter(lambda: f.read(4096), b""):
107
+ sha256_hash.update(byte_block)
108
+ return sha256_hash
awspub/exceptions.py ADDED
@@ -0,0 +1,28 @@
1
+ class MultipleSnapshotsException(Exception):
2
+ pass
3
+
4
+
5
+ class MultipleImportSnapshotTasksException(Exception):
6
+ pass
7
+
8
+
9
+ class MultipleImagesException(Exception):
10
+ pass
11
+
12
+
13
+ class IncompleteImageSetException(Exception):
14
+ pass
15
+
16
+
17
+ class BucketDoesNotExistException(Exception):
18
+ def __init__(self, bucket_name: str, *args, **kwargs):
19
+ msg = f"The bucket named '{bucket_name}' does not exist. You will need to create the bucket before proceeding."
20
+ super().__init__(msg, *args, **kwargs)
21
+
22
+
23
+ class AWSNotificationException(Exception):
24
+ pass
25
+
26
+
27
+ class AWSAuthorizationException(Exception):
28
+ pass