Merge ~jslarraz/review-tools:rock-container into review-tools:master
- Git
- lp:~jslarraz/review-tools
- rock-container
- Merge into master
Proposed by
Jorge Sancho Larraz
Status: | Merged |
---|---|
Merged at revision: | 10f1ead2610427bf86c358437e6ee0ede4ca6b43 |
Proposed branch: | ~jslarraz/review-tools:rock-container |
Merge into: | review-tools:master |
Diff against target: |
771 lines (+339/-333) 7 files modified
reviewtools/available.py (+3/-2) reviewtools/common.py (+0/-139) reviewtools/containers/rock_container.py (+26/-0) reviewtools/containers/tar_container.py (+96/-0) reviewtools/tests/containers/test_rock_container.py (+144/-0) reviewtools/tests/containers/test_tar_container.py (+70/-0) reviewtools/tests/test_common.py (+0/-192) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alex Murray | Approve | ||
Evan Caville | Approve | ||
Review via email:
|
Commit message
rock function to container classes
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alex Murray (alexmurray) wrote : | # |
LGTM - thanks for the additional TarContainer tests as well!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/reviewtools/available.py b/reviewtools/available.py | |||
2 | index 94bfbe1..90f6917 100755 | |||
3 | --- a/reviewtools/available.py | |||
4 | +++ b/reviewtools/available.py | |||
5 | @@ -24,7 +24,6 @@ from reviewtools.common import ( | |||
6 | 24 | read_file_as_json_dict, | 24 | read_file_as_json_dict, |
7 | 25 | MKDTEMP_PREFIX, | 25 | MKDTEMP_PREFIX, |
8 | 26 | _add_error, # make a class | 26 | _add_error, # make a class |
9 | 27 | get_rock_manifest, | ||
10 | 28 | ) | 27 | ) |
11 | 29 | import reviewtools.email as email | 28 | import reviewtools.email as email |
12 | 30 | 29 | ||
13 | @@ -35,6 +34,7 @@ from reviewtools.store import ( | |||
14 | 35 | get_faked_build_and_stage_packages, | 34 | get_faked_build_and_stage_packages, |
15 | 36 | ) | 35 | ) |
16 | 37 | from reviewtools.usn import read_usn_db | 36 | from reviewtools.usn import read_usn_db |
17 | 37 | from reviewtools.containers.rock_container import RockContainer | ||
18 | 38 | from reviewtools.containers.snap_container import SnapContainer, ContainerException | 38 | from reviewtools.containers.snap_container import SnapContainer, ContainerException |
19 | 39 | 39 | ||
20 | 40 | email_update_required_text = """A scan of this %s shows that it was built with packages from the Ubuntu | 40 | email_update_required_text = """A scan of this %s shows that it was built with packages from the Ubuntu |
21 | @@ -536,7 +536,8 @@ def scan_snap(secnot_db_fn, snap_fn, with_cves=False, ignore_pockets=list()): | |||
22 | 536 | def scan_rock(secnot_db_fn, rock_fn, with_cves=False, ignore_pockets=list()): | 536 | def scan_rock(secnot_db_fn, rock_fn, with_cves=False, ignore_pockets=list()): |
23 | 537 | """Scan rock for packages with security notices""" | 537 | """Scan rock for packages with security notices""" |
24 | 538 | out = "" | 538 | out = "" |
26 | 539 | man = get_rock_manifest(rock_fn) | 539 | rock = RockContainer(rock_fn) |
27 | 540 | man = rock.get_rock_manifest() | ||
28 | 540 | # Since ROCKs can be based on non LTS Ubuntu releases, secnot_db should | 541 | # Since ROCKs can be based on non LTS Ubuntu releases, secnot_db should |
29 | 541 | # include them (otherwise the USN db is filtered by tracked LTS releases only | 542 | # include them (otherwise the USN db is filtered by tracked LTS releases only |
30 | 542 | # since that is the requirement for snaps) | 543 | # since that is the requirement for snaps) |
31 | diff --git a/reviewtools/common.py b/reviewtools/common.py | |||
32 | index 5de33ee..88c6e58 100644 | |||
33 | --- a/reviewtools/common.py | |||
34 | +++ b/reviewtools/common.py | |||
35 | @@ -25,11 +25,9 @@ import os | |||
36 | 25 | from pkg_resources import resource_filename | 25 | from pkg_resources import resource_filename |
37 | 26 | import re | 26 | import re |
38 | 27 | import shutil | 27 | import shutil |
39 | 28 | import stat | ||
40 | 29 | import subprocess | 28 | import subprocess |
41 | 30 | import sys | 29 | import sys |
42 | 31 | import tarfile | 30 | import tarfile |
43 | 32 | import tempfile | ||
44 | 33 | import time | 31 | import time |
45 | 34 | import types | 32 | import types |
46 | 35 | import yaml | 33 | import yaml |
47 | @@ -486,16 +484,6 @@ def unsquashfs_lln_parse(lln_out): | |||
48 | 486 | return hdr, entries | 484 | return hdr, entries |
49 | 487 | 485 | ||
50 | 488 | 486 | ||
51 | 489 | def _calculate_rock_untar_uncompressed_size(rock_pkg): | ||
52 | 490 | """Calculate size of the uncompressed tar""" | ||
53 | 491 | size = 0 | ||
54 | 492 | with tarfile.open(rock_pkg) as tar: | ||
55 | 493 | for tarinfo in tar: | ||
56 | 494 | size += tarinfo.size | ||
57 | 495 | |||
58 | 496 | return size | ||
59 | 497 | |||
60 | 498 | |||
61 | 499 | def unsquashfs_supports_ignore_errors(): | 487 | def unsquashfs_supports_ignore_errors(): |
62 | 500 | """Detect if unsquashfs supports the -ignore-errors option""" | 488 | """Detect if unsquashfs supports the -ignore-errors option""" |
63 | 501 | (rc, out) = cmd(["unsquashfs", "-help"]) | 489 | (rc, out) = cmd(["unsquashfs", "-help"]) |
64 | @@ -503,112 +491,6 @@ def unsquashfs_supports_ignore_errors(): | |||
65 | 503 | return "-ig[nore-errors]" in out | 491 | return "-ig[nore-errors]" in out |
66 | 504 | 492 | ||
67 | 505 | 493 | ||
68 | 506 | def is_pkg_uncompressed_size_valid(pkg_max_size, size, pkg): | ||
69 | 507 | st = os.statvfs(pkg) | ||
70 | 508 | avail = st.f_bsize * st.f_bavail * 0.9 # 90% of available space | ||
71 | 509 | if size > pkg_max_size: | ||
72 | 510 | return ( | ||
73 | 511 | False, | ||
74 | 512 | "uncompressed %s is too large (%dM > %dM)" | ||
75 | 513 | % (pkg, size / 1024 / 1024, pkg_max_size / 1024 / 1024), | ||
76 | 514 | ) | ||
77 | 515 | elif size > avail * 0.9: | ||
78 | 516 | return ( | ||
79 | 517 | False, | ||
80 | 518 | "uncompressed %s is too large for available space (%dM > %dM)" | ||
81 | 519 | % (pkg, size / 1024 / 1024, avail / 1024 / 1024), | ||
82 | 520 | ) | ||
83 | 521 | else: | ||
84 | 522 | return True, "" | ||
85 | 523 | |||
86 | 524 | |||
87 | 525 | def _unpack_rock_tar(rock_pkg, dest): | ||
88 | 526 | """Unpack a tar based rock package to dest""" | ||
89 | 527 | size = _calculate_rock_untar_uncompressed_size(rock_pkg) | ||
90 | 528 | |||
91 | 529 | # Assuming MAX_UNCOMPRESSED_SIZE for rocks is same as snaps | ||
92 | 530 | # MAX_UNCOMPRESSED_SIZE | ||
93 | 531 | rock_max_size = MAX_UNCOMPRESSED_SIZE * 1024 * 1024 * 1024 | ||
94 | 532 | |||
95 | 533 | valid_size, error_msg = is_pkg_uncompressed_size_valid( | ||
96 | 534 | rock_max_size, size, rock_pkg | ||
97 | 535 | ) | ||
98 | 536 | if valid_size: | ||
99 | 537 | global MKDTEMP_PREFIX | ||
100 | 538 | global MKDTEMP_DIR | ||
101 | 539 | d = tempfile.mkdtemp(prefix=MKDTEMP_PREFIX, dir=MKDTEMP_DIR) | ||
102 | 540 | |||
103 | 541 | try: | ||
104 | 542 | with tarfile.open(rock_pkg) as tar: | ||
105 | 543 | # Inspecting members before extracting, since it is possible that | ||
106 | 544 | # files are created outside of path, e.g. members that have | ||
107 | 545 | # absolute filenames starting with "/" or filenames with two dots | ||
108 | 546 | # ".." | ||
109 | 547 | # https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extractall | ||
110 | 548 | for name in tar.getnames(): | ||
111 | 549 | if name.startswith("..") or name.startswith("/"): | ||
112 | 550 | logger.error( | ||
113 | 551 | "Bad path %s while extracting archive at %s" | ||
114 | 552 | % (name, rock_pkg) | ||
115 | 553 | ) | ||
116 | 554 | |||
117 | 555 | tar.extractall(path=d) | ||
118 | 556 | except Exception as e: | ||
119 | 557 | logger.error("Unexpected exception while unpacking rock %s" % e) | ||
120 | 558 | if os.path.isdir(d): | ||
121 | 559 | recursive_rm(d) | ||
122 | 560 | |||
123 | 561 | if dest is None: | ||
124 | 562 | dest = d | ||
125 | 563 | else: | ||
126 | 564 | # Recursively move extracted content to original dir, | ||
127 | 565 | # keeping permissions | ||
128 | 566 | move_dir_content(d, dest) | ||
129 | 567 | |||
130 | 568 | return dest | ||
131 | 569 | else: | ||
132 | 570 | logger.error(error_msg) | ||
133 | 571 | |||
134 | 572 | |||
135 | 573 | def check_dir(dest): | ||
136 | 574 | if dest is not None and os.path.exists(dest): | ||
137 | 575 | logger.error("'%s' exists. Aborting." % dest) | ||
138 | 576 | |||
139 | 577 | |||
140 | 578 | def check_fn(fn): | ||
141 | 579 | if not os.path.isfile(fn): | ||
142 | 580 | logger.error("Could not find '%s'" % fn) | ||
143 | 581 | pkg = fn | ||
144 | 582 | if not pkg.startswith("/"): | ||
145 | 583 | pkg = os.path.abspath(pkg) | ||
146 | 584 | return pkg | ||
147 | 585 | |||
148 | 586 | |||
149 | 587 | def check_max_pkg_size(pkg): | ||
150 | 588 | size = os.stat(pkg)[stat.ST_SIZE] | ||
151 | 589 | max = MAX_COMPRESSED_SIZE * 1024 * 1024 * 1024 | ||
152 | 590 | if size > max: | ||
153 | 591 | logger.error( | ||
154 | 592 | "compressed file is too large (%dM > %dM)" | ||
155 | 593 | % (size / 1024 / 1024, max / 1024 / 1024) | ||
156 | 594 | ) | ||
157 | 595 | |||
158 | 596 | |||
159 | 597 | def unpack_rock(fn, dest=None): | ||
160 | 598 | """Unpack rock""" | ||
161 | 599 | pkg = check_fn(fn) | ||
162 | 600 | check_dir(dest) | ||
163 | 601 | |||
164 | 602 | # Limit the maximimum size of the package | ||
165 | 603 | check_max_pkg_size(pkg) | ||
166 | 604 | |||
167 | 605 | # check if its a tar based rock | ||
168 | 606 | if tarfile.is_tarfile(pkg): | ||
169 | 607 | return _unpack_rock_tar(fn, dest) | ||
170 | 608 | |||
171 | 609 | logger.error("Unsupported package format (not tar)") | ||
172 | 610 | |||
173 | 611 | |||
174 | 612 | def open_file_read(path): | 494 | def open_file_read(path): |
175 | 613 | """Open specified file read-only""" | 495 | """Open specified file read-only""" |
176 | 614 | try: | 496 | try: |
177 | @@ -858,27 +740,6 @@ def read_file_as_json_dict(fn): | |||
178 | 858 | return raw | 740 | return raw |
179 | 859 | 741 | ||
180 | 860 | 742 | ||
181 | 861 | def get_rock_manifest(fn): | ||
182 | 862 | if "SNAP_USER_COMMON" in os.environ and os.path.exists( | ||
183 | 863 | os.environ["SNAP_USER_COMMON"] | ||
184 | 864 | ): | ||
185 | 865 | MKDTEMP_DIR = os.environ["SNAP_USER_COMMON"] | ||
186 | 866 | else: | ||
187 | 867 | MKDTEMP_DIR = tempfile.gettempdir() | ||
188 | 868 | unpack_tmp_dir = tempfile.mktemp(prefix=MKDTEMP_PREFIX, dir=MKDTEMP_DIR) | ||
189 | 869 | |||
190 | 870 | man_fn = "/usr/share/rocks/dpkg.query" | ||
191 | 871 | unpack_rock(fn, unpack_tmp_dir) | ||
192 | 872 | |||
193 | 873 | # since ROCK manifest is not available yet, we build a manifest using the | ||
194 | 874 | # information available in /usr/share/rocks/dpkg.query present inside the | ||
195 | 875 | # rock | ||
196 | 876 | man_yaml = build_manifest_from_rock_tar(man_fn, unpack_tmp_dir) | ||
197 | 877 | recursive_rm(unpack_tmp_dir) | ||
198 | 878 | |||
199 | 879 | return man_yaml | ||
200 | 880 | |||
201 | 881 | |||
202 | 882 | def list_dir(path, dirs_only=False): | 743 | def list_dir(path, dirs_only=False): |
203 | 883 | """List directory items""" | 744 | """List directory items""" |
204 | 884 | results = list(map(lambda x: os.path.join(path, x), os.listdir(path))) | 745 | results = list(map(lambda x: os.path.join(path, x), os.listdir(path))) |
205 | diff --git a/reviewtools/containers/rock_container.py b/reviewtools/containers/rock_container.py | |||
206 | 885 | new file mode 100644 | 746 | new file mode 100644 |
207 | index 0000000..6a6e799 | |||
208 | --- /dev/null | |||
209 | +++ b/reviewtools/containers/rock_container.py | |||
210 | @@ -0,0 +1,26 @@ | |||
211 | 1 | import yaml | ||
212 | 2 | from reviewtools.containers.tar_container import ( | ||
213 | 3 | TarContainer, | ||
214 | 4 | ContainerException, | ||
215 | 5 | ) | ||
216 | 6 | from reviewtools.common import build_manifest_from_rock_tar | ||
217 | 7 | |||
218 | 8 | |||
219 | 9 | class RockContainer(TarContainer): | ||
220 | 10 | # TODO: review-tools was not checking for it. We still have some snaps in | ||
221 | 11 | # "tests/" that doesn't fit this limit and will need to be regenerated before | ||
222 | 12 | # this check can be enforced. | ||
223 | 13 | # _min_packed_size = 16 * 1024 | ||
224 | 14 | _max_packed_size = 5 * 1024 * 1024 * 1024 | ||
225 | 15 | _max_unpacked_size = 25 * 1024 * 1024 * 1024 | ||
226 | 16 | |||
227 | 17 | |||
228 | 18 | def get_rock_manifest(self): | ||
229 | 19 | |||
230 | 20 | man_fn = "/usr/share/rocks/dpkg.query" | ||
231 | 21 | # since ROCK manifest is not available yet, we build a manifest using the | ||
232 | 22 | # information available in /usr/share/rocks/dpkg.query present inside the | ||
233 | 23 | # rock | ||
234 | 24 | man_yaml = build_manifest_from_rock_tar(man_fn, self.unpack_dir) | ||
235 | 25 | |||
236 | 26 | return man_yaml | ||
237 | diff --git a/reviewtools/containers/tar_container.py b/reviewtools/containers/tar_container.py | |||
238 | 0 | new file mode 100644 | 27 | new file mode 100644 |
239 | index 0000000..674dd1b | |||
240 | --- /dev/null | |||
241 | +++ b/reviewtools/containers/tar_container.py | |||
242 | @@ -0,0 +1,96 @@ | |||
243 | 1 | import os | ||
244 | 2 | import shutil | ||
245 | 3 | import tarfile | ||
246 | 4 | from reviewtools.common import ( | ||
247 | 5 | recursive_rm, | ||
248 | 6 | ) | ||
249 | 7 | from reviewtools.containers.base_container import BaseContainer, ContainerException | ||
250 | 8 | |||
251 | 9 | |||
252 | 10 | class TarContainer(BaseContainer): | ||
253 | 11 | """ | ||
254 | 12 | A container is a file that encapsulates a file system. This class extends | ||
255 | 13 | BaseContainer to handle functionality that is specific to Tar containers. | ||
256 | 14 | """ | ||
257 | 15 | |||
258 | 16 | def check_container_format(self): | ||
259 | 17 | """ | ||
260 | 18 | Checks that the container file has the expected format. | ||
261 | 19 | |||
262 | 20 | Raises: | ||
263 | 21 | ContainerException: This method will raise an exception if the | ||
264 | 22 | container file is not a tar container. | ||
265 | 23 | """ | ||
266 | 24 | if not tarfile.is_tarfile(self.filename): | ||
267 | 25 | raise ContainerException("Unsupported package format (not tar)") | ||
268 | 26 | |||
269 | 27 | |||
270 | 28 | def calculate_unpacked_size(self) -> int: | ||
271 | 29 | """ | ||
272 | 30 | Estimates the space that the unpacked directory will use by adding the | ||
273 | 31 | individual files size without extracting them. | ||
274 | 32 | |||
275 | 33 | Returns: | ||
276 | 34 | int: Estimated size in bytes of the unpacked directory | ||
277 | 35 | """ | ||
278 | 36 | size = 0 | ||
279 | 37 | with tarfile.open(self.filename) as tar: | ||
280 | 38 | for tarinfo in tar: | ||
281 | 39 | size += tarinfo.size | ||
282 | 40 | return size | ||
283 | 41 | |||
284 | 42 | def unpack(self, items: list = [], force: bool = False) -> str: | ||
285 | 43 | """ | ||
286 | 44 | Extracts the content of the container file and returns the absolute path to | ||
287 | 45 | the newly unpacked directory. | ||
288 | 46 | |||
289 | 47 | Args: | ||
290 | 48 | force (bool, optional): If ``True``, the unpack_dir will be overwritten | ||
291 | 49 | if it already exists. Defaults to ``False`` | ||
292 | 50 | |||
293 | 51 | Returns: | ||
294 | 52 | str: absolute path to the newly created unpack dir | ||
295 | 53 | |||
296 | 54 | Raises: | ||
297 | 55 | ContainerException: This method will raise an ContainerException if the | ||
298 | 56 | unpack_dir already exists and this method was called without the | ||
299 | 57 | force argument set to True | ||
300 | 58 | RuntimeError: This method will raise a RuntimeError if the extraction | ||
301 | 59 | fails for an unknown reason. | ||
302 | 60 | """ | ||
303 | 61 | if self._unpack_dir is not None and not force: | ||
304 | 62 | raise ContainerException("'%s' exists. Aborting." % self._unpack_dir) | ||
305 | 63 | |||
306 | 64 | # Check disk space and space available in disk | ||
307 | 65 | self.check_unpacked_size() | ||
308 | 66 | self.check_disk_space() | ||
309 | 67 | |||
310 | 68 | # Unpack the container | ||
311 | 69 | stage_dir = os.path.join(self.tmp_dir, "stage") | ||
312 | 70 | |||
313 | 71 | with tarfile.open(self.filename) as tar: | ||
314 | 72 | # Inspecting members before extracting, since it is possible that | ||
315 | 73 | # files are created outside of path, e.g. members that have | ||
316 | 74 | # absolute filenames starting with "/" or filenames with two dots | ||
317 | 75 | # ".." | ||
318 | 76 | # https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extractall | ||
319 | 77 | for name in tar.getnames(): | ||
320 | 78 | if name.startswith("..") or name.startswith("/"): | ||
321 | 79 | raise ContainerException( | ||
322 | 80 | "Bad path %s while extracting archive at %s" | ||
323 | 81 | % (name, self.filename) | ||
324 | 82 | ) | ||
325 | 83 | |||
326 | 84 | try: | ||
327 | 85 | tar.extractall(path=stage_dir) | ||
328 | 86 | except Exception as e: | ||
329 | 87 | if os.path.isdir(stage_dir): | ||
330 | 88 | recursive_rm(stage_dir) | ||
331 | 89 | raise RuntimeError("Unexpected exception while unpacking rock %s" % e) | ||
332 | 90 | |||
333 | 91 | # Update on success | ||
334 | 92 | if self._unpack_dir is not None and os.path.exists(self._unpack_dir): | ||
335 | 93 | recursive_rm(self._unpack_dir) | ||
336 | 94 | self._unpack_dir = ".".join(self.filename.split(".")[:-1]) | ||
337 | 95 | shutil.move(stage_dir, self._unpack_dir) | ||
338 | 96 | return self._unpack_dir | ||
339 | diff --git a/reviewtools/tests/containers/test_rock_container.py b/reviewtools/tests/containers/test_rock_container.py | |||
340 | 0 | new file mode 100644 | 97 | new file mode 100644 |
341 | index 0000000..f59b2d9 | |||
342 | --- /dev/null | |||
343 | +++ b/reviewtools/tests/containers/test_rock_container.py | |||
344 | @@ -0,0 +1,144 @@ | |||
345 | 1 | import unittest | ||
346 | 2 | from tempfile import mkdtemp | ||
347 | 3 | from reviewtools.common import ReviewException | ||
348 | 4 | from reviewtools.containers.rock_container import ( | ||
349 | 5 | RockContainer, | ||
350 | 6 | ContainerException, | ||
351 | 7 | ) | ||
352 | 8 | |||
353 | 9 | |||
354 | 10 | class TestRockContainer(unittest.TestCase): | ||
355 | 11 | """Tests for reviewtools.containers.rock_container""" | ||
356 | 12 | |||
357 | 13 | def test_get_rock_manifest(self): | ||
358 | 14 | """Test get_rock_manifest()""" | ||
359 | 15 | valid_rock_fn = "./tests/test-rock-redis_5.0-20.04.tar" | ||
360 | 16 | expected_manifest_yaml = { | ||
361 | 17 | "manifest-version": "1", | ||
362 | 18 | "os-release-id": "ubuntu", | ||
363 | 19 | "os-release-version-id": "20.04", | ||
364 | 20 | "stage-packages": [ | ||
365 | 21 | "adduser=3.118ubuntu2,adduser=3.118ubuntu2", | ||
366 | 22 | "apt=2.0.2ubuntu0.2,apt=2.0.2ubuntu0.2", | ||
367 | 23 | "base-files=11ubuntu5.2,base-files=11ubuntu5.2", | ||
368 | 24 | "base-passwd=3.5.47,base-passwd=3.5.47", | ||
369 | 25 | "bash=5.0-6ubuntu1.1,bash=5.0-6ubuntu1.1", | ||
370 | 26 | "bsdutils=1:2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
371 | 27 | "bzip2=1.0.8-2,bzip2=1.0.8-2", | ||
372 | 28 | "coreutils=8.30-3ubuntu2," "coreutils=8.30-3ubuntu2", | ||
373 | 29 | "dash=0.5.10.2-6,dash=0.5.10.2-6", | ||
374 | 30 | "debconf=1.5.73,debconf=1.5.73", | ||
375 | 31 | "debianutils=4.9.1,debianutils=4.9.1", | ||
376 | 32 | "diffutils=1:3.7-3,diffutils=1:3.7-3", | ||
377 | 33 | "dpkg=1.19.7ubuntu3,dpkg=1.19.7ubuntu3", | ||
378 | 34 | "e2fsprogs=1.45.5-2ubuntu1," "e2fsprogs=1.45.5-2ubuntu1", | ||
379 | 35 | "fdisk=2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
380 | 36 | "findutils=4.7.0-1ubuntu1," "findutils=4.7.0-1ubuntu1", | ||
381 | 37 | "gcc-10-base:amd64=10.2.0-5ubuntu1~20.04," | ||
382 | 38 | "gcc-10=10.2.0-5ubuntu1~20.04", | ||
383 | 39 | "gpgv=2.2.19-3ubuntu2,gnupg2=2.2.19-3ubuntu2", | ||
384 | 40 | "grep=3.4-1,grep=3.4-1", | ||
385 | 41 | "gzip=1.10-0ubuntu4,gzip=1.10-0ubuntu4", | ||
386 | 42 | "hostname=3.23,hostname=3.23", | ||
387 | 43 | "init-system-helpers=1.57," "init-system-helpers=1.57", | ||
388 | 44 | "libacl1:amd64=2.2.53-6,acl=2.2.53-6", | ||
389 | 45 | "libapt-pkg6.0:amd64=2.0.2ubuntu0.2," "apt=2.0.2ubuntu0.2", | ||
390 | 46 | "libatomic1:amd64=10.2.0-5ubuntu1~20.04," | ||
391 | 47 | "gcc-10=10.2.0-5ubuntu1~20.04", | ||
392 | 48 | "libattr1:amd64=1:2.4.48-5,attr=1:2.4.48-5", | ||
393 | 49 | "libaudit-common=1:2.8.5-2ubuntu6," "audit=1:2.8.5-2ubuntu6", | ||
394 | 50 | "libaudit1:amd64=1:2.8.5-2ubuntu6," "audit=1:2.8.5-2ubuntu6", | ||
395 | 51 | "libblkid1:amd64=2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
396 | 52 | "libbz2-1.0:amd64=1.0.8-2,bzip2=1.0.8-2", | ||
397 | 53 | "libc-bin=2.31-0ubuntu9.1," "glibc=2.31-0ubuntu9.1", | ||
398 | 54 | "libc6:amd64=2.31-0ubuntu9.1," "glibc=2.31-0ubuntu9.1", | ||
399 | 55 | "libcap-ng0:amd64=0.7.9-2.1build1," "libcap-ng=0.7.9-2.1build1", | ||
400 | 56 | "libcom-err2:amd64=1.45.5-2ubuntu1," "e2fsprogs=1.45.5-2ubuntu1", | ||
401 | 57 | "libcrypt1:amd64=1:4.4.10-10ubuntu4," "libxcrypt=1:4.4.10-10ubuntu4", | ||
402 | 58 | "libdb5.3:amd64=5.3.28+dfsg1-0.6ubuntu2," | ||
403 | 59 | "db5.3=5.3.28+dfsg1-0.6ubuntu2", | ||
404 | 60 | "libdebconfclient0:amd64=0.251ubuntu1," "cdebconf=0.251ubuntu1", | ||
405 | 61 | "libext2fs2:amd64=1.45.5-2ubuntu1," "e2fsprogs=1.45.5-2ubuntu1", | ||
406 | 62 | "libfdisk1:amd64=2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
407 | 63 | "libffi7:amd64=3.3-4,libffi=3.3-4", | ||
408 | 64 | "libgcc-s1:amd64=10.2.0-5ubuntu1~20.04," "gcc-10=10.2.0-5ubuntu1~20.04", | ||
409 | 65 | "libgcrypt20:amd64=1.8.5-5ubuntu1," "libgcrypt20=1.8.5-5ubuntu1", | ||
410 | 66 | "libgmp10:amd64=2:6.2.0+dfsg-4," "gmp=2:6.2.0+dfsg-4", | ||
411 | 67 | "libgnutls30:amd64=3.6.13-2ubuntu1.3," "gnutls28=3.6.13-2ubuntu1.3", | ||
412 | 68 | "libgpg-error0:amd64=1.37-1," "libgpg-error=1.37-1", | ||
413 | 69 | "libhiredis0.14:amd64=0.14.0-6," "hiredis=0.14.0-6", | ||
414 | 70 | "libhogweed5:amd64=3.5.1+really3.5.1-2," "nettle=3.5.1+really3.5.1-2", | ||
415 | 71 | "libidn2-0:amd64=2.2.0-2,libidn2=2.2.0-2", | ||
416 | 72 | "libjemalloc2:amd64=5.2.1-1ubuntu1," "jemalloc=5.2.1-1ubuntu1", | ||
417 | 73 | "liblua5.1-0:amd64=5.1.5-8.1build4," "lua5.1=5.1.5-8.1build4", | ||
418 | 74 | "liblz4-1:amd64=1.9.2-2,lz4=1.9.2-2", | ||
419 | 75 | "liblzma5:amd64=5.2.4-1ubuntu1," "xz-utils=5.2.4-1ubuntu1", | ||
420 | 76 | "libmount1:amd64=2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
421 | 77 | "libncurses6:amd64=6.2-0ubuntu2," "ncurses=6.2-0ubuntu2", | ||
422 | 78 | "libncursesw6:amd64=6.2-0ubuntu2," "ncurses=6.2-0ubuntu2", | ||
423 | 79 | "libnettle7:amd64=3.5.1+really3.5.1-2," "nettle=3.5.1+really3.5.1-2", | ||
424 | 80 | "libp11-kit0:amd64=0.23.20-1build1," "p11-kit=0.23.20-1build1", | ||
425 | 81 | "libpam-modules:amd64=1.3.1-5ubuntu4.1," "pam=1.3.1-5ubuntu4.1", | ||
426 | 82 | "libpam-modules-bin=1.3.1-5ubuntu4.1," "pam=1.3.1-5ubuntu4.1", | ||
427 | 83 | "libpam-runtime=1.3.1-5ubuntu4.1," "pam=1.3.1-5ubuntu4.1", | ||
428 | 84 | "libpam0g:amd64=1.3.1-5ubuntu4.1," "pam=1.3.1-5ubuntu4.1", | ||
429 | 85 | "libpcre2-8-0:amd64=10.34-7,pcre2=10.34-7", | ||
430 | 86 | "libpcre3:amd64=2:8.39-12build1," "pcre3=2:8.39-12build1", | ||
431 | 87 | "libprocps8:amd64=2:3.3.16-1ubuntu2," "procps=2:3.3.16-1ubuntu2", | ||
432 | 88 | "libseccomp2:amd64=2.4.3-1ubuntu3.20.04.3," | ||
433 | 89 | "libseccomp=2.4.3-1ubuntu3.20.04.3", | ||
434 | 90 | "libselinux1:amd64=3.0-1build2,libselinux=3.0-1build2", | ||
435 | 91 | "libsemanage-common=3.0-1build2,libsemanage=3.0-1build2", | ||
436 | 92 | "libsemanage1:amd64=3.0-1build2,libsemanage=3.0-1build2", | ||
437 | 93 | "libsepol1:amd64=3.0-1,libsepol=3.0-1", | ||
438 | 94 | "libsmartcols1:amd64=2.34-0.1ubuntu9.1,util-linux=2.34-0.1ubuntu9.1", | ||
439 | 95 | "libss2:amd64=1.45.5-2ubuntu1,e2fsprogs=1.45.5-2ubuntu1", | ||
440 | 96 | "libstdc++6:amd64=10.2.0-5ubuntu1~20.04,gcc-10=10.2.0-5ubuntu1~20.04", | ||
441 | 97 | "libsystemd0:amd64=245.4-4ubuntu3.3,systemd=245.4-4ubuntu3.3", | ||
442 | 98 | "libtasn1-6:amd64=4.16.0-2,libtasn1-6=4.16.0-2", | ||
443 | 99 | "libtinfo6:amd64=6.2-0ubuntu2,ncurses=6.2-0ubuntu2", | ||
444 | 100 | "libudev1:amd64=245.4-4ubuntu3.3,systemd=245.4-4ubuntu3.3", | ||
445 | 101 | "libunistring2:amd64=0.9.10-2,libunistring=0.9.10-2", | ||
446 | 102 | "libuuid1:amd64=2.34-0.1ubuntu9.1,util-linux=2.34-0.1ubuntu9.1", | ||
447 | 103 | "libxcursor1=4.0.0-2,tiff=4.0.0-2", | ||
448 | 104 | "libzstd1:amd64=1.4.4+dfsg-3,libzstd=1.4.4+dfsg-3", | ||
449 | 105 | "login=1:4.8.1-1ubuntu5.20.04,shadow=1:4.8.1-1ubuntu5.20.04", | ||
450 | 106 | "logsave=1.45.5-2ubuntu1,e2fsprogs=1.45.5-2ubuntu1", | ||
451 | 107 | "lsb-base=11.1.0ubuntu2,lsb=11.1.0ubuntu2", | ||
452 | 108 | "lua-bitop:amd64=1.0.2-5,lua-bitop=1.0.2-5", | ||
453 | 109 | "lua-cjson:amd64=2.1.0+dfsg-2.1,lua-cjson=2.1.0+dfsg-2.1", | ||
454 | 110 | "mawk=1.3.4.20200120-2,mawk=1.3.4.20200120-2", | ||
455 | 111 | "mount=2.34-0.1ubuntu9.1,util-linux=2.34-0.1ubuntu9.1", | ||
456 | 112 | "ncurses-base=6.2-0ubuntu2,ncurses=6.2-0ubuntu2", | ||
457 | 113 | "ncurses-bin=6.2-0ubuntu2,ncurses=6.2-0ubuntu2", | ||
458 | 114 | "passwd=1:4.8.1-1ubuntu5.20.04,shadow=1:4.8.1-1ubuntu5.20.04", | ||
459 | 115 | "perl-base=5.30.0-9ubuntu0.2,perl=5.30.0-9ubuntu0.2", | ||
460 | 116 | "procps=2:3.3.16-1ubuntu2,procps=2:3.3.16-1ubuntu2", | ||
461 | 117 | "pwgen=2.08-2,pwgen=2.08-2", | ||
462 | 118 | "redis-server=5:5.0.7-2,redis=5:5.0.7-2", | ||
463 | 119 | "redis-tools=5:5.0.7-2,redis=5:5.0.7-2", | ||
464 | 120 | "sed=4.7-1,sed=4.7-1", | ||
465 | 121 | "sensible-utils=0.0.12+nmu1,sensible-utils=0.0.12+nmu1", | ||
466 | 122 | "sysvinit-utils=2.96-2.1ubuntu1,sysvinit=2.96-2.1ubuntu1", | ||
467 | 123 | "tar=1.30+dfsg-7,tar=1.30+dfsg-7", | ||
468 | 124 | "tzdata=2020d-0ubuntu0.20.04,tzdata=2020d-0ubuntu0.20.04", | ||
469 | 125 | "ubuntu-keyring=2020.02.11.2,ubuntu-keyring=2020.02.11.2", | ||
470 | 126 | "util-linux=2.34-0.1ubuntu9.1,util-linux=2.34-0.1ubuntu9.1", | ||
471 | 127 | "zlib1g:amd64=1:1.2.11.dfsg-2ubuntu1.2,zlib=1:1.2.11.dfsg-2ubuntu1.2", | ||
472 | 128 | ], | ||
473 | 129 | } | ||
474 | 130 | valid_rock = RockContainer(valid_rock_fn) | ||
475 | 131 | self.assertDictEqual( | ||
476 | 132 | expected_manifest_yaml, valid_rock.get_rock_manifest() | ||
477 | 133 | ) | ||
478 | 134 | |||
479 | 135 | def test_get_rock_manifest_invalid_rock(self): | ||
480 | 136 | """Test get_rock_manifest() - invalid rock tar""" | ||
481 | 137 | invalid_rock_fn = "./tests/invalid_rock_multiple_layer_tar_archives.tar" | ||
482 | 138 | invalid_rock = RockContainer(invalid_rock_fn) | ||
483 | 139 | with self.assertRaises(ReviewException) as e: | ||
484 | 140 | invalid_rock.get_rock_manifest() | ||
485 | 141 | self.assertEqual( | ||
486 | 142 | e.exception.value, | ||
487 | 143 | "Unexpected number of layer tar archives inside layer directory: 2", | ||
488 | 144 | ) | ||
489 | diff --git a/reviewtools/tests/containers/test_tar_container.py b/reviewtools/tests/containers/test_tar_container.py | |||
490 | 0 | new file mode 100644 | 145 | new file mode 100644 |
491 | index 0000000..153ef3f | |||
492 | --- /dev/null | |||
493 | +++ b/reviewtools/tests/containers/test_tar_container.py | |||
494 | @@ -0,0 +1,70 @@ | |||
495 | 1 | import os | ||
496 | 2 | import unittest | ||
497 | 3 | from tempfile import mkstemp, mkdtemp | ||
498 | 4 | from reviewtools.containers.tar_container import ( | ||
499 | 5 | TarContainer, | ||
500 | 6 | ContainerException, | ||
501 | 7 | ) | ||
502 | 8 | |||
503 | 9 | |||
504 | 10 | class TestTarContainer(unittest.TestCase): | ||
505 | 11 | """Tests for reviewtools.containers.tar_container""" | ||
506 | 12 | |||
507 | 13 | @classmethod | ||
508 | 14 | def setUpClass(cls): | ||
509 | 15 | cls.tmp_dir = mkdtemp() | ||
510 | 16 | cls.fn = "./tests/test-rock-redis_5.0-20.04.tar" | ||
511 | 17 | |||
512 | 18 | # Test initialization | ||
513 | 19 | def test_check_initialization__happy(self): | ||
514 | 20 | TarContainer(self.fn) | ||
515 | 21 | |||
516 | 22 | def test_check_initialization__invalid_format(self): | ||
517 | 23 | fd, plain_file = mkstemp(suffix=".tar") | ||
518 | 24 | with self.assertRaises(ContainerException) as context: | ||
519 | 25 | TarContainer(plain_file) | ||
520 | 26 | self.assertEqual( | ||
521 | 27 | "Unsupported package format (not tar)", context.exception.value | ||
522 | 28 | ) | ||
523 | 29 | os.unlink(plain_file) | ||
524 | 30 | |||
525 | 31 | # Test calculate unpacked size | ||
526 | 32 | def test_calculate_unpacked_size__happy(self): | ||
527 | 33 | # unpacked size calculated is a bit smaller than actual size as it does not consider that | ||
528 | 34 | # folders require at least one complete block | ||
529 | 35 | container = TarContainer(self.fn) | ||
530 | 36 | size = container.calculate_unpacked_size() | ||
531 | 37 | self.assertTrue(isinstance(size, int)) | ||
532 | 38 | |||
533 | 39 | # Test unpack | ||
534 | 40 | def test_unpack__happy(self): | ||
535 | 41 | container = TarContainer(self.fn) | ||
536 | 42 | container.unpack() | ||
537 | 43 | |||
538 | 44 | def test_unpack__force(self): | ||
539 | 45 | container = TarContainer(self.fn) | ||
540 | 46 | container.unpack() | ||
541 | 47 | container.unpack(force=True) | ||
542 | 48 | |||
543 | 49 | def test_unpack__no_force(self): | ||
544 | 50 | container = TarContainer(self.fn) | ||
545 | 51 | container.unpack() | ||
546 | 52 | with self.assertRaises(ContainerException) as context: | ||
547 | 53 | container.unpack() | ||
548 | 54 | self.assertTrue(" exists. Aborting." in context.exception.value) | ||
549 | 55 | |||
550 | 56 | def test_check_unpack__slash_file(self): | ||
551 | 57 | container = TarContainer("./tests/test-rock-invalid-1.tar") | ||
552 | 58 | with self.assertRaises(ContainerException) as context: | ||
553 | 59 | container.unpack() | ||
554 | 60 | self.assertTrue( | ||
555 | 61 | " while extracting archive at " in context.exception.value | ||
556 | 62 | ) | ||
557 | 63 | |||
558 | 64 | def test_check_unpack__two_dots_file(self): | ||
559 | 65 | container = TarContainer("./tests/test-rock-invalid-2.tar") | ||
560 | 66 | with self.assertRaises(ContainerException) as context: | ||
561 | 67 | container.unpack() | ||
562 | 68 | self.assertTrue( | ||
563 | 69 | " while extracting archive at " in context.exception.value | ||
564 | 70 | ) | ||
565 | diff --git a/reviewtools/tests/test_common.py b/reviewtools/tests/test_common.py | |||
566 | index 85504ca..953d2c0 100644 | |||
567 | --- a/reviewtools/tests/test_common.py | |||
568 | +++ b/reviewtools/tests/test_common.py | |||
569 | @@ -19,7 +19,6 @@ import os | |||
570 | 19 | import shutil | 19 | import shutil |
571 | 20 | import tempfile | 20 | import tempfile |
572 | 21 | 21 | ||
573 | 22 | from reviewtools.sr_common import ReviewException | ||
574 | 23 | import reviewtools.sr_tests as sr_tests | 22 | import reviewtools.sr_tests as sr_tests |
575 | 24 | import reviewtools.common | 23 | import reviewtools.common |
576 | 25 | from reviewtools.common import StatLLN | 24 | from reviewtools.common import StatLLN |
577 | @@ -502,194 +501,3 @@ drwxr-xr-x 0/0 48 2020-03-24 09:11 squashfs-root/meta | |||
578 | 502 | continue | 501 | continue |
579 | 503 | 502 | ||
580 | 504 | raise Exception("parsed input should be invalid") | 503 | raise Exception("parsed input should be invalid") |
581 | 505 | |||
582 | 506 | def test_check_pkg_uncompressed_size_ok(self): | ||
583 | 507 | """Test check_pkg_uncompressed_size() - rocks and snaps""" | ||
584 | 508 | pkgs = [ | ||
585 | 509 | "./tests/test-rock-redis_5.0-20.04.tar", | ||
586 | 510 | "./tests/test-snapcraft-manifest-unittest_0_amd64.snap", | ||
587 | 511 | ] | ||
588 | 512 | max_size = 3 * 1024 * 1024 | ||
589 | 513 | size = 1 * 1024 * 1024 | ||
590 | 514 | for pkg in pkgs: | ||
591 | 515 | with self.subTest(pkg=pkg): | ||
592 | 516 | valid_size, _ = reviewtools.common.is_pkg_uncompressed_size_valid( | ||
593 | 517 | max_size, size, pkg | ||
594 | 518 | ) | ||
595 | 519 | self.assertTrue(valid_size) | ||
596 | 520 | |||
597 | 521 | def test_check_pkg_uncompressed_size_max_size_error(self): | ||
598 | 522 | """Test check_pkg_uncompressed_size() - rocks and snaps""" | ||
599 | 523 | pkgs = [ | ||
600 | 524 | "./tests/test-rock-redis_5.0-20.04.tar", | ||
601 | 525 | "./tests/test-snapcraft-manifest-unittest_0_amd64.snap", | ||
602 | 526 | ] | ||
603 | 527 | max_size = 1024 | ||
604 | 528 | size = 1 * 1024 * 1024 | ||
605 | 529 | for pkg in pkgs: | ||
606 | 530 | with self.subTest(pkg=pkg): | ||
607 | 531 | valid_size, _ = reviewtools.common.is_pkg_uncompressed_size_valid( | ||
608 | 532 | max_size, size, pkg | ||
609 | 533 | ) | ||
610 | 534 | self.assertFalse(valid_size) | ||
611 | 535 | |||
612 | 536 | def test_unpack_rock_invalid_format(self): | ||
613 | 537 | """Test unpack_rock() - invalid rock format""" | ||
614 | 538 | invalid_rock = "./tests/test-snapcraft-manifest-unittest_0_amd64.snap" | ||
615 | 539 | with self.assertRaises(SystemExit) as e: | ||
616 | 540 | reviewtools.common.unpack_rock(invalid_rock) | ||
617 | 541 | self.assertEqual(e.exception.code, 1) | ||
618 | 542 | |||
619 | 543 | def test_unpack_rock_valid_format(self): | ||
620 | 544 | """Test unpack_rock() - valid rock format""" | ||
621 | 545 | # TODO: add further unit testing for tar unpacking functionality | ||
622 | 546 | valid_rock = "./tests/test-rock-redis_5.0-20.04.tar" | ||
623 | 547 | unpack_dir = reviewtools.common.unpack_rock(valid_rock) | ||
624 | 548 | self.assertIn("review-tools-", unpack_dir) | ||
625 | 549 | |||
626 | 550 | def test_unpack_rock_invalid_format_filename_starting_with_slash(self): | ||
627 | 551 | """Test unpack_rock() - invalid - filename starting with slash""" | ||
628 | 552 | # TODO: add further unit testing for tar unpacking functionality | ||
629 | 553 | invalid_rock = "./tests/test-rock-invalid-1.tar" | ||
630 | 554 | with self.assertRaises(SystemExit) as e: | ||
631 | 555 | reviewtools.common.unpack_rock(invalid_rock) | ||
632 | 556 | self.assertEqual(e.exception.code, 1) | ||
633 | 557 | |||
634 | 558 | def test_unpack_rock_invalid_format_filename_with_two_dots(self): | ||
635 | 559 | """Test unpack_rock() - invalid - filename with two dots""" | ||
636 | 560 | # TODO: add further unit testing for tar unpacking functionality | ||
637 | 561 | invalid_rock = "./tests/test-rock-invalid-2.tar" | ||
638 | 562 | with self.assertRaises(SystemExit) as e: | ||
639 | 563 | reviewtools.common.unpack_rock(invalid_rock) | ||
640 | 564 | self.assertEqual(e.exception.code, 1) | ||
641 | 565 | |||
642 | 566 | def test_get_rock_manifest(self): | ||
643 | 567 | """Test get_rock_manifest()""" | ||
644 | 568 | valid_rock_fn = "./tests/test-rock-redis_5.0-20.04.tar" | ||
645 | 569 | expected_manifest_yaml = { | ||
646 | 570 | "manifest-version": "1", | ||
647 | 571 | "os-release-id": "ubuntu", | ||
648 | 572 | "os-release-version-id": "20.04", | ||
649 | 573 | "stage-packages": [ | ||
650 | 574 | "adduser=3.118ubuntu2,adduser=3.118ubuntu2", | ||
651 | 575 | "apt=2.0.2ubuntu0.2,apt=2.0.2ubuntu0.2", | ||
652 | 576 | "base-files=11ubuntu5.2,base-files=11ubuntu5.2", | ||
653 | 577 | "base-passwd=3.5.47,base-passwd=3.5.47", | ||
654 | 578 | "bash=5.0-6ubuntu1.1,bash=5.0-6ubuntu1.1", | ||
655 | 579 | "bsdutils=1:2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
656 | 580 | "bzip2=1.0.8-2,bzip2=1.0.8-2", | ||
657 | 581 | "coreutils=8.30-3ubuntu2," "coreutils=8.30-3ubuntu2", | ||
658 | 582 | "dash=0.5.10.2-6,dash=0.5.10.2-6", | ||
659 | 583 | "debconf=1.5.73,debconf=1.5.73", | ||
660 | 584 | "debianutils=4.9.1,debianutils=4.9.1", | ||
661 | 585 | "diffutils=1:3.7-3,diffutils=1:3.7-3", | ||
662 | 586 | "dpkg=1.19.7ubuntu3,dpkg=1.19.7ubuntu3", | ||
663 | 587 | "e2fsprogs=1.45.5-2ubuntu1," "e2fsprogs=1.45.5-2ubuntu1", | ||
664 | 588 | "fdisk=2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
665 | 589 | "findutils=4.7.0-1ubuntu1," "findutils=4.7.0-1ubuntu1", | ||
666 | 590 | "gcc-10-base:amd64=10.2.0-5ubuntu1~20.04," | ||
667 | 591 | "gcc-10=10.2.0-5ubuntu1~20.04", | ||
668 | 592 | "gpgv=2.2.19-3ubuntu2,gnupg2=2.2.19-3ubuntu2", | ||
669 | 593 | "grep=3.4-1,grep=3.4-1", | ||
670 | 594 | "gzip=1.10-0ubuntu4,gzip=1.10-0ubuntu4", | ||
671 | 595 | "hostname=3.23,hostname=3.23", | ||
672 | 596 | "init-system-helpers=1.57," "init-system-helpers=1.57", | ||
673 | 597 | "libacl1:amd64=2.2.53-6,acl=2.2.53-6", | ||
674 | 598 | "libapt-pkg6.0:amd64=2.0.2ubuntu0.2," "apt=2.0.2ubuntu0.2", | ||
675 | 599 | "libatomic1:amd64=10.2.0-5ubuntu1~20.04," | ||
676 | 600 | "gcc-10=10.2.0-5ubuntu1~20.04", | ||
677 | 601 | "libattr1:amd64=1:2.4.48-5,attr=1:2.4.48-5", | ||
678 | 602 | "libaudit-common=1:2.8.5-2ubuntu6," "audit=1:2.8.5-2ubuntu6", | ||
679 | 603 | "libaudit1:amd64=1:2.8.5-2ubuntu6," "audit=1:2.8.5-2ubuntu6", | ||
680 | 604 | "libblkid1:amd64=2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
681 | 605 | "libbz2-1.0:amd64=1.0.8-2,bzip2=1.0.8-2", | ||
682 | 606 | "libc-bin=2.31-0ubuntu9.1," "glibc=2.31-0ubuntu9.1", | ||
683 | 607 | "libc6:amd64=2.31-0ubuntu9.1," "glibc=2.31-0ubuntu9.1", | ||
684 | 608 | "libcap-ng0:amd64=0.7.9-2.1build1," "libcap-ng=0.7.9-2.1build1", | ||
685 | 609 | "libcom-err2:amd64=1.45.5-2ubuntu1," "e2fsprogs=1.45.5-2ubuntu1", | ||
686 | 610 | "libcrypt1:amd64=1:4.4.10-10ubuntu4," "libxcrypt=1:4.4.10-10ubuntu4", | ||
687 | 611 | "libdb5.3:amd64=5.3.28+dfsg1-0.6ubuntu2," | ||
688 | 612 | "db5.3=5.3.28+dfsg1-0.6ubuntu2", | ||
689 | 613 | "libdebconfclient0:amd64=0.251ubuntu1," "cdebconf=0.251ubuntu1", | ||
690 | 614 | "libext2fs2:amd64=1.45.5-2ubuntu1," "e2fsprogs=1.45.5-2ubuntu1", | ||
691 | 615 | "libfdisk1:amd64=2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
692 | 616 | "libffi7:amd64=3.3-4,libffi=3.3-4", | ||
693 | 617 | "libgcc-s1:amd64=10.2.0-5ubuntu1~20.04," "gcc-10=10.2.0-5ubuntu1~20.04", | ||
694 | 618 | "libgcrypt20:amd64=1.8.5-5ubuntu1," "libgcrypt20=1.8.5-5ubuntu1", | ||
695 | 619 | "libgmp10:amd64=2:6.2.0+dfsg-4," "gmp=2:6.2.0+dfsg-4", | ||
696 | 620 | "libgnutls30:amd64=3.6.13-2ubuntu1.3," "gnutls28=3.6.13-2ubuntu1.3", | ||
697 | 621 | "libgpg-error0:amd64=1.37-1," "libgpg-error=1.37-1", | ||
698 | 622 | "libhiredis0.14:amd64=0.14.0-6," "hiredis=0.14.0-6", | ||
699 | 623 | "libhogweed5:amd64=3.5.1+really3.5.1-2," "nettle=3.5.1+really3.5.1-2", | ||
700 | 624 | "libidn2-0:amd64=2.2.0-2,libidn2=2.2.0-2", | ||
701 | 625 | "libjemalloc2:amd64=5.2.1-1ubuntu1," "jemalloc=5.2.1-1ubuntu1", | ||
702 | 626 | "liblua5.1-0:amd64=5.1.5-8.1build4," "lua5.1=5.1.5-8.1build4", | ||
703 | 627 | "liblz4-1:amd64=1.9.2-2,lz4=1.9.2-2", | ||
704 | 628 | "liblzma5:amd64=5.2.4-1ubuntu1," "xz-utils=5.2.4-1ubuntu1", | ||
705 | 629 | "libmount1:amd64=2.34-0.1ubuntu9.1," "util-linux=2.34-0.1ubuntu9.1", | ||
706 | 630 | "libncurses6:amd64=6.2-0ubuntu2," "ncurses=6.2-0ubuntu2", | ||
707 | 631 | "libncursesw6:amd64=6.2-0ubuntu2," "ncurses=6.2-0ubuntu2", | ||
708 | 632 | "libnettle7:amd64=3.5.1+really3.5.1-2," "nettle=3.5.1+really3.5.1-2", | ||
709 | 633 | "libp11-kit0:amd64=0.23.20-1build1," "p11-kit=0.23.20-1build1", | ||
710 | 634 | "libpam-modules:amd64=1.3.1-5ubuntu4.1," "pam=1.3.1-5ubuntu4.1", | ||
711 | 635 | "libpam-modules-bin=1.3.1-5ubuntu4.1," "pam=1.3.1-5ubuntu4.1", | ||
712 | 636 | "libpam-runtime=1.3.1-5ubuntu4.1," "pam=1.3.1-5ubuntu4.1", | ||
713 | 637 | "libpam0g:amd64=1.3.1-5ubuntu4.1," "pam=1.3.1-5ubuntu4.1", | ||
714 | 638 | "libpcre2-8-0:amd64=10.34-7,pcre2=10.34-7", | ||
715 | 639 | "libpcre3:amd64=2:8.39-12build1," "pcre3=2:8.39-12build1", | ||
716 | 640 | "libprocps8:amd64=2:3.3.16-1ubuntu2," "procps=2:3.3.16-1ubuntu2", | ||
717 | 641 | "libseccomp2:amd64=2.4.3-1ubuntu3.20.04.3," | ||
718 | 642 | "libseccomp=2.4.3-1ubuntu3.20.04.3", | ||
719 | 643 | "libselinux1:amd64=3.0-1build2,libselinux=3.0-1build2", | ||
720 | 644 | "libsemanage-common=3.0-1build2,libsemanage=3.0-1build2", | ||
721 | 645 | "libsemanage1:amd64=3.0-1build2,libsemanage=3.0-1build2", | ||
722 | 646 | "libsepol1:amd64=3.0-1,libsepol=3.0-1", | ||
723 | 647 | "libsmartcols1:amd64=2.34-0.1ubuntu9.1,util-linux=2.34-0.1ubuntu9.1", | ||
724 | 648 | "libss2:amd64=1.45.5-2ubuntu1,e2fsprogs=1.45.5-2ubuntu1", | ||
725 | 649 | "libstdc++6:amd64=10.2.0-5ubuntu1~20.04,gcc-10=10.2.0-5ubuntu1~20.04", | ||
726 | 650 | "libsystemd0:amd64=245.4-4ubuntu3.3,systemd=245.4-4ubuntu3.3", | ||
727 | 651 | "libtasn1-6:amd64=4.16.0-2,libtasn1-6=4.16.0-2", | ||
728 | 652 | "libtinfo6:amd64=6.2-0ubuntu2,ncurses=6.2-0ubuntu2", | ||
729 | 653 | "libudev1:amd64=245.4-4ubuntu3.3,systemd=245.4-4ubuntu3.3", | ||
730 | 654 | "libunistring2:amd64=0.9.10-2,libunistring=0.9.10-2", | ||
731 | 655 | "libuuid1:amd64=2.34-0.1ubuntu9.1,util-linux=2.34-0.1ubuntu9.1", | ||
732 | 656 | "libxcursor1=4.0.0-2,tiff=4.0.0-2", | ||
733 | 657 | "libzstd1:amd64=1.4.4+dfsg-3,libzstd=1.4.4+dfsg-3", | ||
734 | 658 | "login=1:4.8.1-1ubuntu5.20.04,shadow=1:4.8.1-1ubuntu5.20.04", | ||
735 | 659 | "logsave=1.45.5-2ubuntu1,e2fsprogs=1.45.5-2ubuntu1", | ||
736 | 660 | "lsb-base=11.1.0ubuntu2,lsb=11.1.0ubuntu2", | ||
737 | 661 | "lua-bitop:amd64=1.0.2-5,lua-bitop=1.0.2-5", | ||
738 | 662 | "lua-cjson:amd64=2.1.0+dfsg-2.1,lua-cjson=2.1.0+dfsg-2.1", | ||
739 | 663 | "mawk=1.3.4.20200120-2,mawk=1.3.4.20200120-2", | ||
740 | 664 | "mount=2.34-0.1ubuntu9.1,util-linux=2.34-0.1ubuntu9.1", | ||
741 | 665 | "ncurses-base=6.2-0ubuntu2,ncurses=6.2-0ubuntu2", | ||
742 | 666 | "ncurses-bin=6.2-0ubuntu2,ncurses=6.2-0ubuntu2", | ||
743 | 667 | "passwd=1:4.8.1-1ubuntu5.20.04,shadow=1:4.8.1-1ubuntu5.20.04", | ||
744 | 668 | "perl-base=5.30.0-9ubuntu0.2,perl=5.30.0-9ubuntu0.2", | ||
745 | 669 | "procps=2:3.3.16-1ubuntu2,procps=2:3.3.16-1ubuntu2", | ||
746 | 670 | "pwgen=2.08-2,pwgen=2.08-2", | ||
747 | 671 | "redis-server=5:5.0.7-2,redis=5:5.0.7-2", | ||
748 | 672 | "redis-tools=5:5.0.7-2,redis=5:5.0.7-2", | ||
749 | 673 | "sed=4.7-1,sed=4.7-1", | ||
750 | 674 | "sensible-utils=0.0.12+nmu1,sensible-utils=0.0.12+nmu1", | ||
751 | 675 | "sysvinit-utils=2.96-2.1ubuntu1,sysvinit=2.96-2.1ubuntu1", | ||
752 | 676 | "tar=1.30+dfsg-7,tar=1.30+dfsg-7", | ||
753 | 677 | "tzdata=2020d-0ubuntu0.20.04,tzdata=2020d-0ubuntu0.20.04", | ||
754 | 678 | "ubuntu-keyring=2020.02.11.2,ubuntu-keyring=2020.02.11.2", | ||
755 | 679 | "util-linux=2.34-0.1ubuntu9.1,util-linux=2.34-0.1ubuntu9.1", | ||
756 | 680 | "zlib1g:amd64=1:1.2.11.dfsg-2ubuntu1.2,zlib=1:1.2.11.dfsg-2ubuntu1.2", | ||
757 | 681 | ], | ||
758 | 682 | } | ||
759 | 683 | self.assertDictEqual( | ||
760 | 684 | expected_manifest_yaml, reviewtools.common.get_rock_manifest(valid_rock_fn) | ||
761 | 685 | ) | ||
762 | 686 | |||
763 | 687 | def test_get_rock_manifest_invalid_rock(self): | ||
764 | 688 | """Test get_rock_manifest() - invalid rock tar""" | ||
765 | 689 | invalid_rock_fn = "./tests/invalid_rock_multiple_layer_tar_archives.tar" | ||
766 | 690 | with self.assertRaises(ReviewException) as e: | ||
767 | 691 | reviewtools.common.get_rock_manifest(invalid_rock_fn) | ||
768 | 692 | self.assertEqual( | ||
769 | 693 | e.exception.value, | ||
770 | 694 | "Unexpected number of layer tar archives inside layer directory: 2", | ||
771 | 695 | ) |
refactor looks good to me! Use of inheritance looks clean and follows similar pattern for both snaps and rocks. Thanks!