test: add test for export option
This commit is contained in:
parent
8cce659ec5
commit
962b7f4d4b
4 changed files with 123 additions and 2 deletions
89
test/run/test_exports.py
Normal file
89
test/run/test_exports.py
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
import contextlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from .. import test
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="jsondata", scope="module")
|
||||||
|
def jsondata_fixture():
|
||||||
|
return json.dumps({
|
||||||
|
"version": "2",
|
||||||
|
"pipelines": [
|
||||||
|
{
|
||||||
|
"name": "image",
|
||||||
|
"stages": [
|
||||||
|
{
|
||||||
|
"type": "org.osbuild.truncate",
|
||||||
|
"options": {
|
||||||
|
"filename": "foo.img",
|
||||||
|
"size": "10",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
# cannot use org.osbuild.chown as it needs the chown
|
||||||
|
# binary in the stage
|
||||||
|
"type": "org.osbuild.testing.injectpy",
|
||||||
|
"options": {
|
||||||
|
"code": [
|
||||||
|
'import os',
|
||||||
|
'os.chown(f"{tree}/foo.img", 1000, 1000)',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="osb", scope="module")
|
||||||
|
def osbuild_fixture():
|
||||||
|
with test.OSBuild() as osb:
|
||||||
|
yield osb
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="testing_libdir", scope="module")
|
||||||
|
def testing_libdir_fixture(tmpdir_factory):
|
||||||
|
tests_path = pathlib.Path(__file__).parent.parent
|
||||||
|
project_path = tests_path.parent
|
||||||
|
testing_libdir_path = tests_path / "stages"
|
||||||
|
fake_libdir_path = tmpdir_factory.mktemp("fake-libdir")
|
||||||
|
# there must be an empty "osbild" dir for a "os.listdir(self._libdir)"
|
||||||
|
# in buildroot.py
|
||||||
|
(fake_libdir_path / "osbuild").mkdir()
|
||||||
|
# construct minimal viable libdir from current checkout
|
||||||
|
for d in ["stages", "runners", ]:
|
||||||
|
subprocess.run(
|
||||||
|
["cp", "-a", os.fspath(project_path / d), f"{fake_libdir_path}"],
|
||||||
|
check=True)
|
||||||
|
# now inject testing stages
|
||||||
|
for p in testing_libdir_path.glob("org.osbuild.testing.*"):
|
||||||
|
shutil.copy2(p, fake_libdir_path / "stages")
|
||||||
|
yield fake_libdir_path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(os.getuid() != 0, reason="root-only")
|
||||||
|
def test_exports_normal(osb, tmp_path, jsondata, testing_libdir): # pylint: disable=unused-argument
|
||||||
|
osb.compile(jsondata, output_dir=tmp_path, exports=["image"], libdir=testing_libdir)
|
||||||
|
expected_export = tmp_path / "image/foo.img"
|
||||||
|
assert expected_export.exists()
|
||||||
|
assert expected_export.stat().st_uid == 1000
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(os.getuid() != 0, reason="root-only")
|
||||||
|
def test_exports_with_force_no_preserve_owner(osb, tmp_path, jsondata, testing_libdir):
|
||||||
|
with contextlib.ExitStack() as cm:
|
||||||
|
k = "OSBUILD_EXPORT_FORCE_NO_PRESERVE_OWNER"
|
||||||
|
os.environ[k] = "1"
|
||||||
|
cm.callback(os.unsetenv, k)
|
||||||
|
|
||||||
|
osb.compile(jsondata, output_dir=tmp_path, exports=["image"], libdir=testing_libdir)
|
||||||
|
expected_export = tmp_path / "image/foo.img"
|
||||||
|
assert expected_export.exists()
|
||||||
|
assert expected_export.stat().st_uid == 0
|
||||||
5
test/stages/README.md
Normal file
5
test/stages/README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
This directory contains stages that can only be used during testing and
|
||||||
|
will be dynamically added to the library directory.
|
||||||
|
|
||||||
|
See `test/run/test_exports.py` for an example usage of the `pyinject`
|
||||||
|
stage.
|
||||||
27
test/stages/org.osbuild.testing.injectpy
Executable file
27
test/stages/org.osbuild.testing.injectpy
Executable file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
"""
|
||||||
|
Inject arbitrary python code.
|
||||||
|
|
||||||
|
ONLY USE FOR TESTING
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import osbuild.api
|
||||||
|
|
||||||
|
SCHEMA_2 = """
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def main(tree, options): # pylint: disable=unused-argument
|
||||||
|
script = "\n".join(options.get("code", []))
|
||||||
|
exec(script) # pylint: disable=exec-used
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
args = osbuild.api.arguments()
|
||||||
|
r = main(args["tree"], args.get("options", {}))
|
||||||
|
sys.exit(r)
|
||||||
|
|
@ -347,7 +347,7 @@ class OSBuild(contextlib.AbstractContextManager):
|
||||||
print(log)
|
print(log)
|
||||||
print("-- END ---------------------------------")
|
print("-- END ---------------------------------")
|
||||||
|
|
||||||
def compile(self, data_stdin, output_dir=None, checkpoints=None, check=False, exports=None):
|
def compile(self, data_stdin, output_dir=None, checkpoints=None, check=False, exports=None, libdir="."):
|
||||||
"""Compile an Artifact
|
"""Compile an Artifact
|
||||||
|
|
||||||
This takes a manifest as `data_stdin`, executes the pipeline, and
|
This takes a manifest as `data_stdin`, executes the pipeline, and
|
||||||
|
|
@ -377,7 +377,7 @@ class OSBuild(contextlib.AbstractContextManager):
|
||||||
cmd_args = [sys.executable, "-m", "osbuild"]
|
cmd_args = [sys.executable, "-m", "osbuild"]
|
||||||
|
|
||||||
cmd_args += ["--json"]
|
cmd_args += ["--json"]
|
||||||
cmd_args += ["--libdir", "."]
|
cmd_args += ["--libdir", libdir]
|
||||||
cmd_args += ["--output-directory", output_dir]
|
cmd_args += ["--output-directory", output_dir]
|
||||||
cmd_args += ["--store", self._cachedir]
|
cmd_args += ["--store", self._cachedir]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue