stages/squashfs: Add exclude_paths support
Add the ability to exclude files and directories from the squashfs image. This uses the mksquashfs -regex -e FILES... feature, so simple matches or regexes can be used. This also adds a new test for squashfs, based on the existing test for erofs.
This commit is contained in:
parent
387806a8c3
commit
86c89a2421
3 changed files with 116 additions and 0 deletions
|
|
@ -10,6 +10,7 @@ def main(inputs, output_dir, options):
|
|||
source = inputs["tree"]["path"]
|
||||
filename = options["filename"].lstrip("/")
|
||||
compression = options.get("compression")
|
||||
exclude_paths = options.get("exclude_paths")
|
||||
|
||||
target = os.path.join(output_dir, filename)
|
||||
|
||||
|
|
@ -22,6 +23,10 @@ def main(inputs, output_dir, options):
|
|||
for opt, val in opts.items():
|
||||
cmd += [f"-X{opt}", val]
|
||||
|
||||
if exclude_paths:
|
||||
cmd += ["-regex", "-e"]
|
||||
cmd.extend(exclude_paths)
|
||||
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -14,6 +14,13 @@
|
|||
"description": "Filename for squashfs image",
|
||||
"type": "string"
|
||||
},
|
||||
"exclude_paths": {
|
||||
"type": "array",
|
||||
"description": "Regex of paths to exclude, can be files or directories",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"compression": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
|
|
|||
104
stages/test/test_squashfs.py
Normal file
104
stages/test/test_squashfs.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import os.path
|
||||
import subprocess
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from osbuild import testutil
|
||||
from osbuild.testutil import has_executable, make_fake_input_tree
|
||||
|
||||
TEST_INPUT = [
|
||||
({}, []),
|
||||
({"compression": {"method": "lz4"}}, ["-comp", "lz4"]),
|
||||
({"compression": {"method": "xz", "options": {"bcj": "x86"}}}, ["-comp", "xz", "-Xbcj", "x86"]),
|
||||
({"exclude_paths": ["boot/.*", "root/.*"]}, ["-regex", "-e", "boot/.*", "root/.*"])
|
||||
]
|
||||
|
||||
|
||||
STAGE_NAME = "org.osbuild.squashfs"
|
||||
|
||||
|
||||
@pytest.mark.skipif(not has_executable("mksquashfs"), reason="no mksquashfs")
|
||||
@pytest.mark.parametrize("test_options,expected", TEST_INPUT)
|
||||
def test_squashfs_integration(tmp_path, stage_module, test_options, expected): # pylint: disable=unused-argument
|
||||
fake_input_tree = make_fake_input_tree(tmp_path, {
|
||||
"/file-in-root.txt": "other content",
|
||||
"/subdir/file-in-subdir.txt": "subdir content",
|
||||
})
|
||||
inputs = {
|
||||
"tree": {
|
||||
"path": fake_input_tree,
|
||||
}
|
||||
}
|
||||
filename = "some-file.img"
|
||||
options = {
|
||||
"filename": filename,
|
||||
}
|
||||
options.update(test_options)
|
||||
|
||||
stage_module.main(inputs, tmp_path, options)
|
||||
|
||||
img_path = os.path.join(tmp_path, "some-file.img")
|
||||
assert os.path.exists(img_path)
|
||||
# validate the content
|
||||
output = subprocess.check_output([
|
||||
"unsquashfs", "-ls", img_path], encoding="utf-8")
|
||||
assert "subdir/file-in-subdir.txt\n" in output
|
||||
assert "file-in-root.txt\n" in output
|
||||
|
||||
|
||||
@mock.patch("subprocess.run")
|
||||
@pytest.mark.parametrize("test_options,expected", TEST_INPUT)
|
||||
def test_squashfs(mock_run, tmp_path, stage_module, test_options, expected):
|
||||
fake_input_tree = make_fake_input_tree(tmp_path, {
|
||||
"/some-dir/some-file.txt": "content",
|
||||
})
|
||||
inputs = {
|
||||
"tree": {
|
||||
"path": fake_input_tree,
|
||||
}
|
||||
}
|
||||
filename = "some-file.img"
|
||||
options = {
|
||||
"filename": filename,
|
||||
}
|
||||
options.update(test_options)
|
||||
|
||||
stage_module.main(inputs, tmp_path, options)
|
||||
|
||||
expected = [
|
||||
"mksquashfs",
|
||||
f"{fake_input_tree}",
|
||||
f"{os.path.join(tmp_path, filename)}",
|
||||
] + expected
|
||||
mock_run.assert_called_with(expected, check=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test_data,expected_err", [
|
||||
# bad
|
||||
({"extra": "option"}, "'extra' was unexpected"),
|
||||
({"compression": {"method": "invalid"}}, "'invalid' is not one of ["),
|
||||
({"compression": {}}, "'method' is a required property"),
|
||||
({"compression": {"method": "xz", "options": {"bcj": "invalid"}}}, "'invalid' is not one of ["),
|
||||
({"compression": {"method": "xz", "options": {"level": 9}}}, "Additional properties are not allowed"),
|
||||
# good
|
||||
({"compression": {"method": "lz4"}}, ""),
|
||||
({"exclude_paths": ["boot/", "root/"]}, "")
|
||||
])
|
||||
def test_schema_validation_squashfs(stage_schema, test_data, expected_err):
|
||||
test_input = {
|
||||
"type": STAGE_NAME,
|
||||
"options": {
|
||||
"filename": "some-filename.img",
|
||||
}
|
||||
}
|
||||
test_input["options"].update(test_data)
|
||||
res = stage_schema.validate(test_input)
|
||||
|
||||
if expected_err == "":
|
||||
assert res.valid is True, f"err: {[e.as_dict() for e in res.errors]}"
|
||||
else:
|
||||
assert res.valid is False
|
||||
testutil.assert_jsonschema_error_contains(res, expected_err, expected_num_errs=1)
|
||||
Loading…
Add table
Add a link
Reference in a new issue