stages(bootupd): add tests for existing behavior

Also refactor bind mounts into a helper.
This commit is contained in:
Michael Vogt 2024-01-09 11:54:37 +01:00 committed by Achilleas Koutsou
parent eb657b08b3
commit dacf5733ea
2 changed files with 64 additions and 28 deletions

View file

@ -9,6 +9,7 @@ and GRUB for BIOS firmware on x86_64.
The project is deployed in Fedora CoreOS and derivatives
"""
import contextlib
import os
import subprocess
import sys
@ -67,6 +68,19 @@ SCHEMA_2 = r"""
"""
@contextlib.contextmanager
def bind_mounts(sources, dest_root):
for src in sources:
dst = os.path.join(dest_root, src.lstrip("/"))
subprocess.run(["mount", "--rbind", src, dst], check=True)
try:
yield
finally:
for src in sources:
dst = os.path.join(dest_root, src.lstrip("/"))
subprocess.run(["umount", "--recursive", dst], check=False)
def main(args, options):
deployment = options.get("deployment", None)
static_configs = options.get("static-configs", False)
@ -101,22 +115,11 @@ def main(args, options):
# want to make sure the version used matches the target and not
# risk any inconsistencies with the build root). Let's set up
# and chroot to run the bootupctl command from the target.
submounts = ['dev', 'proc', 'sys', 'run', 'var', 'tmp']
for mnt in submounts:
subprocess.run(['mount', '--rbind',
os.path.join("/", mnt),
os.path.join(root, mnt)],
check=True)
try:
with bind_mounts(['/dev', '/proc', '/sys', '/run', '/var', '/tmp'], root):
cmd = ['chroot', root, '/usr/bin/bootupctl', 'backend', 'install']
cmd.extend(bootupd_args)
cmd.append(mounts)
subprocess.run(cmd, check=True)
finally:
for mnt in submounts:
subprocess.run(['umount', '--recursive',
os.path.join(root, mnt)],
check=False)
return 0

View file

@ -1,39 +1,42 @@
#!/usr/bin/python3
import os.path
import subprocess
from unittest import mock
from unittest.mock import call, patch
import pytest
import osbuild.meta
from osbuild.testutil import has_executable, make_fake_input_tree
from osbuild.testutil.imports import import_module_from_path
@pytest.mark.parametrize("test_data,expected_err", [
# bad
({"deployment": "totally"}, "'totally' is not of type 'object'"),
({"deployment": "must-be-object"}, "'must-be-object' is not of type 'object'"),
({"deployment": {"osname": "some-os"}}, "'ref' is a required property"),
({"deployment": {"ref": "some-ref"}}, "'osname' is a required property"),
({"deployment": {"osname": "some-os", "ref": "some-ref", "serial": "yo"}}, "'yo' is not of type 'number'"),
({"deployment": {"osname": "some-os", "ref": "some-ref", "serial": "must-be-number"}},
"'must-be-number' is not of type 'number'"),
({"random": "property"}, "Additional properties are not allowed"),
({"bios": {}}, "'device' is a required property"),
({"bios": "yes"}, "'yes' is not of type 'object'"),
({"bios": "must-be-object"}, "'must-be-object' is not of type 'object'"),
# good
({}, ""),
({"deployment": {
"osname": "some-os",
"ref": "some-ref",
"serial": 1,
},
"static-configs": True,
"bios": {
"device": "/dev/sda",
}}, "")
({
"deployment":
{
"osname": "some-os",
"ref": "some-ref",
"serial": 1,
},
"static-configs": True,
"bios":
{
"device": "/dev/sda",
},
}, "")
])
def test_schema_validation_bootupd(test_data, expected_err):
def test_bootupd_schema_validation(test_data, expected_err):
name = "org.osbuild.bootupd"
root = os.path.join(os.path.dirname(__file__), "../..")
mod_info = osbuild.meta.ModuleInfo.load(root, "Stage", name)
@ -54,3 +57,33 @@ def test_schema_validation_bootupd(test_data, expected_err):
assert len(res.errors) == 1, [e.as_dict() for e in res.errors]
err_msgs = [e.as_dict()["message"] for e in res.errors]
assert expected_err in err_msgs[0]
@patch("subprocess.run")
def test_bootupd_defaults(mocked_run):
stage_path = os.path.join(os.path.dirname(__file__), "../org.osbuild.bootupd")
stage = import_module_from_path("bootupd_stage", stage_path)
args = {
"paths": {
"mounts": "/run/osbuild/mounts",
},
}
options = {}
stage.main(args, options)
assert mocked_run.call_args_list == [
call(["mount", "--rbind", "/dev", "/run/osbuild/mounts/dev"], check=True),
call(["mount", "--rbind", "/proc", "/run/osbuild/mounts/proc"], check=True),
call(["mount", "--rbind", "/sys", "/run/osbuild/mounts/sys"], check=True),
call(["mount", "--rbind", "/run", "/run/osbuild/mounts/run"], check=True),
call(["mount", "--rbind", "/var", "/run/osbuild/mounts/var"], check=True),
call(["mount", "--rbind", "/tmp", "/run/osbuild/mounts/tmp"], check=True),
call(["chroot", "/run/osbuild/mounts", "/usr/bin/bootupctl", "backend", "install", "/run/osbuild/mounts"], check=True),
call(["umount", "--recursive", "/run/osbuild/mounts/dev"], check=False),
call(["umount", "--recursive", "/run/osbuild/mounts/proc"], check=False),
call(["umount", "--recursive", "/run/osbuild/mounts/sys"], check=False),
call(["umount", "--recursive", "/run/osbuild/mounts/run"], check=False),
call(["umount", "--recursive", "/run/osbuild/mounts/var"], check=False),
call(["umount", "--recursive", "/run/osbuild/mounts/tmp"], check=False),
]