diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1eb20719..b9107fa3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,6 @@ jobs: - "test.run.test_assemblers" - "test.run.test_boot" - "test.run.test_noop" - - "test.run.test_ostree" - "test.run.test_sources" - "test.run.test_stages" - "test.src" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8920d28b..c6a35d63 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -40,7 +40,7 @@ RPM: - aws/rhel-9.0-nightly-aarch64 INTERNAL_NETWORK: "true" -Testing: +Composer Tests: stage: test extends: .terraform script: @@ -60,6 +60,21 @@ Testing: # - aws/rhel-9.0-nightly-aarch64 INTERNAL_NETWORK: "true" +OSTree Images: + stage: test + extends: .terraform + script: + - schutzbot/deploy.sh + - sudo test/cases/ostree-images + parallel: + matrix: + - RUNNER: + - aws/fedora-34-x86_64 + - aws/rhel-8.4-ga-x86_64 + - aws/rhel-8.6-nightly-x86_64 + - aws/rhel-9.0-nightly-x86_64 + INTERNAL_NETWORK: "true" + finish: stage: finish tags: diff --git a/schutzbot/deploy.sh b/schutzbot/deploy.sh index a10539c0..11498688 100755 --- a/schutzbot/deploy.sh +++ b/schutzbot/deploy.sh @@ -60,3 +60,6 @@ sudo dnf -y install osbuild-composer-tests # Set up a directory to hold repository overrides. sudo mkdir -p /etc/osbuild-composer/repositories + +# Temp fix until composer gains these dependencies +sudo dnf -y install osbuild-luks2 osbuild-lvm2 diff --git a/test/cases/ostree-images b/test/cases/ostree-images new file mode 100755 index 00000000..e2efa653 --- /dev/null +++ b/test/cases/ostree-images @@ -0,0 +1,171 @@ +#!/usr/bin/python3 + +"""OSTree Image Tests""" + +import argparse +import os +import tempfile +import time +import subprocess +import sys + + +RESET = "\033[0m" +GREEN = "\033[32m" +BOLD = "\033[1m" +RED = "\033[31m" + + +class OSBuild: + def __init__(self, store, outdir): + self.store = store + self.outdir = outdir + self.checkpoints = [] + + def run(self, manifest, exports, checkpoints=None): + cmd = [ + "osbuild", + "--store", os.fspath(self.store), + "--output-dir", os.fspath(self.outdir), + os.fspath(manifest) + ] + + for checkpoint in self.checkpoints + (checkpoints or []): + cmd += [ + "--checkpoint", checkpoint + ] + + for export in exports: + cmd += [ + "--export", export + ] + + subprocess.run(cmd, check=True) + + +def run_tests(args, tmpdir): + tests = { + "fedora-ostree-tarball": { + "manifest": "fedora-ostree-tarball.json", + "exports": { + "tarball": { + "artifact": "fedora-commit.tar" + } + } + }, + "fedora-ostree-container": { + "manifest": "fedora-ostree-container.json", + "exports": { + "container": { + "artifact": "fedora-container.tar" + } + }, + }, + "fedora-ostree-bootiso": { + "manifest": "fedora-ostree-bootiso.json", + "exports": { + "bootiso": { + "artifact": "fedora-ostree-boot.iso" + } + }, + }, + "fedora-ostree-image": { + "manifest": "fedora-ostree-image.json", + "exports": { + "qcow2": { + "artifact": "disk.qcow2" + } + }, + } + } + + outdir, store = args.output_directory, args.store + + if not outdir: + outdir = os.path.join(tmpdir, "outdir") + os.makedirs(outdir) + + if not store: + store = os.path.join(tmpdir, "store") + os.makedirs(store) + + print(f"Store at: {os.path.realpath(store)}") + print(f"Output at: {os.path.realpath(outdir)}") + + osbuild = OSBuild(store, outdir) + + osbuild.checkpoints = [ + "build", + "ostree-tree", + "ostree-commit" + ] + + results = [] + + for testname, test in tests.items(): + print(f"Testing {BOLD}{testname}{RESET}", flush=True) + manifest = test["manifest"] + + start = time.monotonic() + result = { + "test": manifest + } + path = os.path.join("test", "data", "manifests", manifest) + exports = test["exports"] + + try: + osbuild.run(path, exports.keys()) + for name, data in exports.items(): + artifact = data["artifact"] + path = os.path.join(outdir, name, artifact) + assert os.path.exists(path) + print(f"{GREEN}success{RESET}", flush=True) + except Exception as e: # pylint: disable=broad-except + print(f"{RED}Error{RESET}: {e}") + result["error"] = str(e) + + duration = time.monotonic() - start + result["duration"] = duration + print(f"Test duration: {duration}", flush=True) + + results.append(result) + + return results + + +def main(): + parser = argparse.ArgumentParser(description="ostree image tests") + parser.add_argument( + "--store", + metavar="DIRECTORY", + type=os.path.abspath, + default=None, + help="directory where intermediary os trees are stored") + parser.add_argument( + "--output-directory", + metavar="DIRECTORY", + type=os.path.abspath, + default=None, + help="directory where result objects are stored") + args = parser.parse_args() + + print(f"Running in {os.path.realpath(os.curdir)}") + + tmpdir = "/var/osbuild/tmp" + os.makedirs(tmpdir, exist_ok=True) + with tempfile.TemporaryDirectory(dir=tmpdir) as tmp: + results = run_tests(args, tmp) + + n = len(results) + failed = len(list(filter(lambda x: x.get("error"), results))) + ok = n - failed + + print("tests/ok/failed", end=": ") + print(f"{n}/{GREEN}{ok}{RESET}/{RED}{failed}{RESET}") + + if failed: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/test/run/test_ostree.py b/test/run/test_ostree.py deleted file mode 100644 index 725441e3..00000000 --- a/test/run/test_ostree.py +++ /dev/null @@ -1,88 +0,0 @@ -# -# Runtime / Integration Tests for ostree pipelines -# - -import os -import tempfile -import pytest - -from .. import test - - -@pytest.fixture(name="tmpdir", scope="module") -def tmpdir_fixture(): - with tempfile.TemporaryDirectory() as tmp: - yield tmp - - -@pytest.fixture(name="osb", scope="module") -def osbuild_fixture(): - with test.OSBuild() as osb: - yield osb - - -@pytest.fixture(name="testdata", scope="module") -def testdata_fixture(): - return test.TestBase.locate_test_data() - - -@pytest.mark.skipif(not test.TestBase.have_test_data(), reason="no test-data access") -@pytest.mark.skipif(not test.TestBase.can_bind_mount(), reason="root-only") -def test_ostree_tarball(osb, tmpdir, testdata): - - # Build a container - manifest = os.path.join(testdata, - "manifests/fedora-ostree-tarball.json") - osb.compile_file(manifest, - output_dir=tmpdir, - checkpoints=["build", "ostree-tree", "ostree-commit"], - exports=["tarball"]) - - tarball = os.path.join(tmpdir, "tarball", "fedora-commit.tar") - assert os.path.exists(tarball) - - -@pytest.mark.skipif(not test.TestBase.have_test_data(), reason="no test-data access") -@pytest.mark.skipif(not test.TestBase.can_bind_mount(), reason="root-only") -def test_ostree_container(osb, tmpdir, testdata): - - # Build a container - manifest = os.path.join(testdata, - "manifests/fedora-ostree-container.json") - osb.compile_file(manifest, - output_dir=tmpdir, - checkpoints=["build", "ostree-tree", "ostree-commit"], - exports=["container"]) - - oci_archive = os.path.join(tmpdir, "container", "fedora-container.tar") - assert os.path.exists(oci_archive) - - -@pytest.mark.skipif(not test.TestBase.have_test_data(), reason="no test-data access") -@pytest.mark.skipif(not test.TestBase.can_bind_mount(), reason="root-only") -def test_ostree_bootiso(osb, tmpdir, testdata): - # build a bootable ISO - manifest = os.path.join(testdata, - "manifests/fedora-ostree-bootiso.json") - osb.compile_file(manifest, - output_dir=tmpdir, - checkpoints=["build", "ostree-tree", "ostree-commit"], - exports=["bootiso"]) - - bootiso = os.path.join(tmpdir, "bootiso", "fedora-ostree-boot.iso") - assert os.path.exists(bootiso) - - -@pytest.mark.skipif(not test.TestBase.have_test_data(), reason="no test-data access") -@pytest.mark.skipif(not test.TestBase.can_bind_mount(), reason="root-only") -def test_ostree_image(osb, tmpdir, testdata): - # build a qemu image - manifest = os.path.join(testdata, - "manifests/fedora-ostree-image.json") - osb.compile_file(manifest, - output_dir=tmpdir, - checkpoints=["build", "ostree-tree", "ostree-commit"], - exports=["qcow2"]) - - bootiso = os.path.join(tmpdir, "qcow2", "disk.qcow2") - assert os.path.exists(bootiso)