diff --git a/.travis.yml b/.travis.yml index 4e438dfe7..ba670d6a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,4 +19,13 @@ matrix: script: # ubuntu's rpm package sets dbpath to ~/.rpmdb, which makes rpm fail... - sudo sh -c 'mkdir /etc/rpm; echo "%_dbpath /var/lib/rpm" > /etc/rpm/macros' - - sudo env "PATH=$PATH" "OSBUILD_TEST_BUILD_PIPELINE=test/build-from-yum.json" test/run + - sudo env "PATH=$PATH" "OSBUILD_TEST_BUILD_PIPELINE=test/build-from-yum.json" test/run --image-info + # I know this looks stupid, but it actually enables the tests to run in parallel, so it takes less time + - language: python + python: 3.7 + env: PYTHONUNBUFFERED=1 + before_install: sudo apt-get install -y qemu-kvm + script: + # ubuntu's rpm package sets dbpath to ~/.rpmdb, which makes rpm fail... + - sudo sh -c 'mkdir /etc/rpm; echo "%_dbpath /var/lib/rpm" > /etc/rpm/macros' + - sudo env "PATH=$PATH" "OSBUILD_TEST_BUILD_PIPELINE=test/build-from-yum.json" test/run --boot-test diff --git a/internal/distro/distro_test.go b/internal/distro/distro_test.go index 851bed893..3869bc801 100644 --- a/internal/distro/distro_test.go +++ b/internal/distro/distro_test.go @@ -21,7 +21,7 @@ func TestDistro_Pipeline(t *testing.T) { } for _, fileInfo := range fileInfos { type compose struct { - Distro string `json:"distro"` + Distro string `json:"distro"` OutputFormat string `json:"output-format"` Blueprint *blueprint.Blueprint `json:"blueprint"` } @@ -63,4 +63,3 @@ func TestDistro_Pipeline(t *testing.T) { }) } } - diff --git a/test/cases/qcow2_local_boot.json b/test/cases/qcow2_local_boot.json new file mode 100644 index 000000000..bff7008ed --- /dev/null +++ b/test/cases/qcow2_local_boot.json @@ -0,0 +1,168 @@ +{ + "metadata": { + "output-format": "qcow2", + "filename": "image.qcow2", + "blueprint": { + "name": "qcow2-boot-test", + "description": "Image for boot test", + "packages": [], + "modules": [], + "groups": [], + "customizations": { + "user": [ + { + "name": "redhat", + "password": "$y$j9T$hMKTMCO/s27TcOMRH9eUN1$6G0Jrc20QiptW6P3fwm3LKDd/4IIVSr1N2u611UwNgB", + "groups": [ + "wheel" + ] + } + ], + "sshkey": [ + { + "user": "redhat", + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC61wMCjOSHwbVb4VfVyl5sn497qW4PsdQ7Ty7aD6wDNZ/QjjULkDV/yW5WjDlDQ7UqFH0Sr7vywjqDizUAqK7zM5FsUKsUXWHWwg/ehKg8j9xKcMv11AkFoUoujtfAujnKODkk58XSA9whPr7qcw3vPrmog680pnMSzf9LC7J6kXfs6lkoKfBh9VnlxusCrw2yg0qI1fHAZBLPx7mW6+me71QZsS6sVz8v8KXyrXsKTdnF50FjzHcK9HXDBtSJS5wA3fkcRYymJe0o6WMWNdgSRVpoSiWaHHmFgdMUJaYoCfhXzyl7LtNb3Q+Sveg+tJK7JaRXBLMUllOlJ6ll5Hod root@localhost" + } + ] + }, + "services": { + "enabled": [ + "sshd" + ] + } + } + }, + "pipeline": { + "build": { + "stages": [ + { + "name": "org.osbuild.dnf", + "options": { + "repos": [ + { + "metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBFturGcBEACv0xBo91V2n0uEC2vh69ywCiSyvUgN/AQH8EZpCVtM7NyjKgKm\nbbY4G3R0M3ir1xXmvUDvK0493/qOiFrjkplvzXFTGpPTi0ypqGgxc5d0ohRA1M75\nL+0AIlXoOgHQ358/c4uO8X0JAA1NYxCkAW1KSJgFJ3RjukrfqSHWthS1d4o8fhHy\nKJKEnirE5hHqB50dafXrBfgZdaOs3C6ppRIePFe2o4vUEapMTCHFw0woQR8Ah4/R\nn7Z9G9Ln+0Cinmy0nbIDiZJ+pgLAXCOWBfDUzcOjDGKvcpoZharA07c0q1/5ojzO\n4F0Fh4g/BUmtrASwHfcIbjHyCSr1j/3Iz883iy07gJY5Yhiuaqmp0o0f9fgHkG53\n2xCU1owmACqaIBNQMukvXRDtB2GJMuKa/asTZDP6R5re+iXs7+s9ohcRRAKGyAyc\nYKIQKcaA+6M8T7/G+TPHZX6HJWqJJiYB+EC2ERblpvq9TPlLguEWcmvjbVc31nyq\nSDoO3ncFWKFmVsbQPTbP+pKUmlLfJwtb5XqxNR5GEXSwVv4I7IqBmJz1MmRafnBZ\ng0FJUtH668GnldO20XbnSVBr820F5SISMXVwCXDXEvGwwiB8Lt8PvqzXnGIFDAu3\nDlQI5sxSqpPVWSyw08ppKT2Tpmy8adiBotLfaCFl2VTHwOae48X2dMPBvQARAQAB\ntDFGZWRvcmEgKDMwKSA8ZmVkb3JhLTMwLXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQI4BBMBAgAiBQJbbqxnAhsPBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAK\nCRDvPBEfz8ZZudTnD/9170LL3nyTVUCFmBjT9wZ4gYnpwtKVPa/pKnxbbS+Bmmac\ng9TrT9pZbqOHrNJLiZ3Zx1Hp+8uxr3Lo6kbYwImLhkOEDrf4aP17HfQ6VYFbQZI8\nf79OFxWJ7si9+3gfzeh9UYFEqOQfzIjLWFyfnas0OnV/P+RMQ1Zr+vPRqO7AR2va\nN9wg+Xl7157dhXPCGYnGMNSoxCbpRs0JNlzvJMuAea5nTTznRaJZtK/xKsqLn51D\nK07k9MHVFXakOH8QtMCUglbwfTfIpO5YRq5imxlWbqsYWVQy1WGJFyW6hWC0+RcJ\nOx5zGtOfi4/dN+xJ+ibnbyvy/il7Qm+vyFhCYqIPyS5m2UVJUuao3eApE38k78/o\n8aQOTnFQZ+U1Sw+6woFTxjqRQBXlQm2+7Bt3bqGATg4sXXWPbmwdL87Ic+mxn/ml\nSMfQux/5k6iAu1kQhwkO2YJn9eII6HIPkW+2m5N1JsUyJQe4cbtZE5Yh3TRA0dm7\n+zoBRfCXkOW4krchbgww/ptVmzMMP7GINJdROrJnsGl5FVeid9qHzV7aZycWSma7\nCxBYB1J8HCbty5NjtD6XMYRrMLxXugvX6Q4NPPH+2NKjzX4SIDejS6JjgrP3KA3O\npMuo7ZHMfveBngv8yP+ZD/1sS6l+dfExvdaJdOdgFCnp4p3gPbw5+Lv70HrMjA==\n=BfZ/\n-----END PGP PUBLIC KEY BLOCK-----\n", + "checksum": "sha256:9f596e18f585bee30ac41c11fb11a83ed6b11d5b341c1cb56ca4015d7717cb97" + } + ], + "packages": [ + "dnf", + "e2fsprogs", + "policycoreutils", + "qemu-img", + "systemd", + "grub2-pc", + "tar" + ], + "releasever": "30", + "basearch": "x86_64" + } + } + ] + }, + "stages": [ + { + "name": "org.osbuild.dnf", + "options": { + "repos": [ + { + "metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBFturGcBEACv0xBo91V2n0uEC2vh69ywCiSyvUgN/AQH8EZpCVtM7NyjKgKm\nbbY4G3R0M3ir1xXmvUDvK0493/qOiFrjkplvzXFTGpPTi0ypqGgxc5d0ohRA1M75\nL+0AIlXoOgHQ358/c4uO8X0JAA1NYxCkAW1KSJgFJ3RjukrfqSHWthS1d4o8fhHy\nKJKEnirE5hHqB50dafXrBfgZdaOs3C6ppRIePFe2o4vUEapMTCHFw0woQR8Ah4/R\nn7Z9G9Ln+0Cinmy0nbIDiZJ+pgLAXCOWBfDUzcOjDGKvcpoZharA07c0q1/5ojzO\n4F0Fh4g/BUmtrASwHfcIbjHyCSr1j/3Iz883iy07gJY5Yhiuaqmp0o0f9fgHkG53\n2xCU1owmACqaIBNQMukvXRDtB2GJMuKa/asTZDP6R5re+iXs7+s9ohcRRAKGyAyc\nYKIQKcaA+6M8T7/G+TPHZX6HJWqJJiYB+EC2ERblpvq9TPlLguEWcmvjbVc31nyq\nSDoO3ncFWKFmVsbQPTbP+pKUmlLfJwtb5XqxNR5GEXSwVv4I7IqBmJz1MmRafnBZ\ng0FJUtH668GnldO20XbnSVBr820F5SISMXVwCXDXEvGwwiB8Lt8PvqzXnGIFDAu3\nDlQI5sxSqpPVWSyw08ppKT2Tpmy8adiBotLfaCFl2VTHwOae48X2dMPBvQARAQAB\ntDFGZWRvcmEgKDMwKSA8ZmVkb3JhLTMwLXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQI4BBMBAgAiBQJbbqxnAhsPBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAK\nCRDvPBEfz8ZZudTnD/9170LL3nyTVUCFmBjT9wZ4gYnpwtKVPa/pKnxbbS+Bmmac\ng9TrT9pZbqOHrNJLiZ3Zx1Hp+8uxr3Lo6kbYwImLhkOEDrf4aP17HfQ6VYFbQZI8\nf79OFxWJ7si9+3gfzeh9UYFEqOQfzIjLWFyfnas0OnV/P+RMQ1Zr+vPRqO7AR2va\nN9wg+Xl7157dhXPCGYnGMNSoxCbpRs0JNlzvJMuAea5nTTznRaJZtK/xKsqLn51D\nK07k9MHVFXakOH8QtMCUglbwfTfIpO5YRq5imxlWbqsYWVQy1WGJFyW6hWC0+RcJ\nOx5zGtOfi4/dN+xJ+ibnbyvy/il7Qm+vyFhCYqIPyS5m2UVJUuao3eApE38k78/o\n8aQOTnFQZ+U1Sw+6woFTxjqRQBXlQm2+7Bt3bqGATg4sXXWPbmwdL87Ic+mxn/ml\nSMfQux/5k6iAu1kQhwkO2YJn9eII6HIPkW+2m5N1JsUyJQe4cbtZE5Yh3TRA0dm7\n+zoBRfCXkOW4krchbgww/ptVmzMMP7GINJdROrJnsGl5FVeid9qHzV7aZycWSma7\nCxBYB1J8HCbty5NjtD6XMYRrMLxXugvX6Q4NPPH+2NKjzX4SIDejS6JjgrP3KA3O\npMuo7ZHMfveBngv8yP+ZD/1sS6l+dfExvdaJdOdgFCnp4p3gPbw5+Lv70HrMjA==\n=BfZ/\n-----END PGP PUBLIC KEY BLOCK-----\n", + "checksum": "sha256:9f596e18f585bee30ac41c11fb11a83ed6b11d5b341c1cb56ca4015d7717cb97" + } + ], + "packages": [ + "kernel-core", + "@Fedora Cloud Server", + "chrony", + "polkit", + "systemd-udev", + "selinux-policy-targeted", + "grub2-pc", + "langpacks-en" + ], + "exclude_packages": [ + "dracut-config-rescue", + "etables", + "firewalld", + "gobject-introspection", + "plymouth" + ], + "releasever": "30", + "basearch": "x86_64" + } + }, + { + "name": "org.osbuild.locale", + "options": { + "language": "en_US" + } + }, + { + "name": "org.osbuild.fstab", + "options": { + "filesystems": [ + { + "uuid": "76a22bf4-f153-4541-b6c7-0332c0dfaeac", + "vfs_type": "ext4", + "path": "/", + "options": "defaults", + "freq": 1, + "passno": 1 + } + ] + } + }, + { + "name": "org.osbuild.grub2", + "options": { + "root_fs_uuid": "76a22bf4-f153-4541-b6c7-0332c0dfaeac", + "boot_fs_uuid": "00000000-0000-0000-0000-000000000000", + "kernel_opts": "ro biosdevname=0 net.ifnames=0" + } + }, + { + "name": "org.osbuild.systemd", + "options": { + "enabled_services": [ + "sshd" + ] + } + }, + { + "name": "org.osbuild.users", + "options": { + "users": { + "redhat": { + "groups": [ + "wheel" + ], + "password": "$6$IR7O7z56ouB/OInP$.hscD6dQqPQGwMuQ.idumixSHI/JEyaUfiCAHVSpGO/iNLEvvVZVOQL23zBzQbc2.yJ25xAZD75H0tXqKJpEE/", + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC61wMCjOSHwbVb4VfVyl5sn497qW4PsdQ7Ty7aD6wDNZ/QjjULkDV/yW5WjDlDQ7UqFH0Sr7vywjqDizUAqK7zM5FsUKsUXWHWwg/ehKg8j9xKcMv11AkFoUoujtfAujnKODkk58XSA9whPr7qcw3vPrmog680pnMSzf9LC7J6kXfs6lkoKfBh9VnlxusCrw2yg0qI1fHAZBLPx7mW6+me71QZsS6sVz8v8KXyrXsKTdnF50FjzHcK9HXDBtSJS5wA3fkcRYymJe0o6WMWNdgSRVpoSiWaHHmFgdMUJaYoCfhXzyl7LtNb3Q+Sveg+tJK7JaRXBLMUllOlJ6ll5Hod root@localhost" + } + } + } + }, + { + "name": "org.osbuild.selinux", + "options": { + "file_contexts": "etc/selinux/targeted/contexts/files/file_contexts" + } + }, + { + "name": "org.osbuild.fix-bls", + "options": {} + } + ], + "assembler": { + "name": "org.osbuild.qemu", + "options": { + "format": "qcow2", + "filename": "image.qcow2", + "ptuuid": "0x14fc63d2", + "root_fs_uuid": "76a22bf4-f153-4541-b6c7-0332c0dfaeac", + "size": 3221225472 + } + } + } +} diff --git a/test/keyring/id_rsa b/test/keyring/id_rsa new file mode 100644 index 000000000..baf10a797 --- /dev/null +++ b/test/keyring/id_rsa @@ -0,0 +1,27 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAQEAutcDAozkh8G1W+FX1cpebJ+Pe6luD7HUO08u2g+sAzWf0I41C5A1 +f8luVow5Q0O1KhR9Eq+78sI6g4s1AKiu8zORbFCrFF1h1sIP3oSoPI/cSnDL9dQJBaFKLo +7XwLo5yjg5JOfF0gPcIT6+6nMN7z65qIOvNKZzEs3/SwuyepF37OpZKCnwYfVZ5cbrAq8N +soNKiNXxwGQSz8e5luvpnu9UGbEurFc/L/Cl8q17Ck3ZxedBY8x3CvR1wwbUiUucAN35HE +WMpiXtKOljFjXYEkVaaEolmhx5hYHTFCWmKAn4V88pey7TW90Pkr3oPrSSuyWkVwSzFJZT +pSepZeR6HQAAA8gkYhqfJGIanwAAAAdzc2gtcnNhAAABAQC61wMCjOSHwbVb4VfVyl5sn4 +97qW4PsdQ7Ty7aD6wDNZ/QjjULkDV/yW5WjDlDQ7UqFH0Sr7vywjqDizUAqK7zM5FsUKsU +XWHWwg/ehKg8j9xKcMv11AkFoUoujtfAujnKODkk58XSA9whPr7qcw3vPrmog680pnMSzf +9LC7J6kXfs6lkoKfBh9VnlxusCrw2yg0qI1fHAZBLPx7mW6+me71QZsS6sVz8v8KXyrXsK +TdnF50FjzHcK9HXDBtSJS5wA3fkcRYymJe0o6WMWNdgSRVpoSiWaHHmFgdMUJaYoCfhXzy +l7LtNb3Q+Sveg+tJK7JaRXBLMUllOlJ6ll5HodAAAAAwEAAQAAAQBbJjHNuLZ0lEfJvzF+ +lu9hxqXVCl8rQPHszUBqGWMtXafNstKmBYBUCwzNJDN7YTisgrpRt3HViHPLYMpGvAQ9mV +bEpMYRdU0Z3Cqpv8XjZbtuhYC7OOn92SW7eOxAlZlD0hHuszOKtV9ayKWS8vZFVTB1yWhc +IyfYcK6vCdHUgPWrdiUJ7ULd0/t6thSCUYZxQAIBImDAh2GIKUV3b99WzUY8uAh4X70JoG +aVF2oFI/6gbIzvwUDqaEjzrll+ZRpxBdpQ+gdpGfvcKwipJrBEffd3Ji3TTqzqy91Iv/K9 +Wm3ExbSe5JqMoimQkTf7BkTnNMViNzzFlW+yg9A2otUBAAAAgH+N7lqHL55QrDggHX3SmX +WzckNWvNP5q1rxLuy+WshivaFzXfihg7NWXpk3Jx8+Bi3AWP+6eKDjE2T6pEj+80dbeXOl +uoZOaRtFbfqMiPxa+UP+EeW8d5rb62U+gMbAVMM/0yQKCG5F6fU9tis34+ev0trR4DeWKS +n9yL/dkUQBAAAAgQDg4sL9BYI6GEz7JzBbww8Xc0zgIexf3LCFOiBPrw7Cb3uGOcjxMRnX +qf4LUeatYe/PCruhnLoCoHdaJc1JeXWjptfCefF0X0R2TeXdcLk0S9VY4vwk9FbbX9Wo6/ +QS+SYr6b1MglUbvnFQpoGEZa8FaC7aKj+Y+k/+J32NwqEObQAAAIEA1LCzckxWUo9LvA11 +7eNeK5VZLAjHabP6grsSgJugX6lQZ6hBnvB+J1w0IbXVxH5EMnl8zeVByWvK0B/XNTBSzw +S7NYXBuUG2if21fsJJB/9VW+UWXK8m8vpErnW5P+6RdichxRs9HuU41e3Y17DvxgiteQ5W +nQbQ6LErYhygDHEAAAAOcm9vdEBsb2NhbGhvc3QBAgMEBQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/test/keyring/id_rsa.pub b/test/keyring/id_rsa.pub new file mode 100644 index 000000000..45330f39a --- /dev/null +++ b/test/keyring/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC61wMCjOSHwbVb4VfVyl5sn497qW4PsdQ7Ty7aD6wDNZ/QjjULkDV/yW5WjDlDQ7UqFH0Sr7vywjqDizUAqK7zM5FsUKsUXWHWwg/ehKg8j9xKcMv11AkFoUoujtfAujnKODkk58XSA9whPr7qcw3vPrmog680pnMSzf9LC7J6kXfs6lkoKfBh9VnlxusCrw2yg0qI1fHAZBLPx7mW6+me71QZsS6sVz8v8KXyrXsKTdnF50FjzHcK9HXDBtSJS5wA3fkcRYymJe0o6WMWNdgSRVpoSiWaHHmFgdMUJaYoCfhXzyl7LtNb3Q+Sveg+tJK7JaRXBLMUllOlJ6ll5Hod root@localhost diff --git a/test/run b/test/run index db5567e27..b4cdce7e4 100755 --- a/test/run +++ b/test/run @@ -1,17 +1,20 @@ #!/usr/bin/python3 +import argparse import contextlib import glob import json import os -import shutil import subprocess import sys import tempfile -import unittest +import time +import shutil import urllib.request +from typing import Dict, Any + TEST_DIR = os.path.dirname(__file__) @@ -36,6 +39,40 @@ def temporary_json_file(obj): os.unlink(f.name) +@contextlib.contextmanager +def create_ssh_keys(): + with tempfile.TemporaryDirectory() as dir: + # Copy the keys and set correct permissions/ownership on the directory and keys + # Proper directory ownership is implied by the fact that this process creates the directory + # The mode is adjusted by `chmod` + shutil.copyfile(f"{TEST_DIR}/keyring/id_rsa", f"{dir}/id_rsa") + shutil.copyfile(f"{TEST_DIR}/keyring/id_rsa.pub", f"{dir}/id_rsa.pub") + os.chmod(f"{dir}/id_rsa", 0o600) + try: + yield dir + finally: + pass + + +@contextlib.contextmanager +def qemu_boot_image(image_file): + # run in background + cmd = ["qemu-system-x86_64", + "-m", "2048", + "-snapshot", + "-accel", "accel=kvm:hvf:tcg", + "-net", "nic,model=rtl8139", "-net", "user,hostfwd=tcp::1022-:22", + "-nographic", + image_file + ] + print(f"running qemu command: {' '.join(cmd)}") + vm = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + try: + yield None + finally: + vm.kill() + + def run_osbuild(pipeline, store): osbuild_cmd = ["python3", "-m", "osbuild", "--json", "--libdir", ".", "--store", store, "-"] @@ -44,6 +81,7 @@ def run_osbuild(pipeline, store): osbuild_cmd.append("--build-pipeline") osbuild_cmd.append(os.path.abspath(build_pipeline)) + result = dict() try: result = json.loads(subprocess.check_output(osbuild_cmd, cwd="./osbuild", encoding="utf-8", input=json.dumps(pipeline))) except subprocess.CalledProcessError as err: @@ -53,25 +91,81 @@ def run_osbuild(pipeline, store): def run_test(case, store): - if "pipeline" in case: - _, output_id = run_osbuild(case["pipeline"], store) - filename = os.path.join(store, "refs", output_id, case["compose"]["filename"]) - else: - filename, _ = urllib.request.urlretrieve(case["url"]) + try: + if "pipeline" in case: + _, output_id = run_osbuild(case["pipeline"], store) + filename = os.path.join(store, "refs", output_id, case["compose"]["filename"]) + else: + filename, _ = urllib.request.urlretrieve(case["url"]) - info = json.loads(subprocess.check_output(["tools/image-info", filename])) - if info != case["expected"]: - with temporary_json_file(case["expected"]) as a, temporary_json_file(info) as b: - subprocess.run(["diff", "--unified", "--color", "--label", "expected", a, "--label", "got", b], check=False) - return False + info = json.loads(subprocess.check_output(["tools/image-info", filename])) + if info != case["expected"]: + with temporary_json_file(case["expected"]) as a, temporary_json_file(info) as b: + subprocess.run(["diff", "--unified", "--color", "--label", "expected", a, "--label", "got", b], check=False) + return False + except KeyError: + pass return True -def main(args): +def get_local_boot_test_case(image_type: str) -> (str, Dict[Any, Any]): + with open(f"test/cases/{image_type}_local_boot.json", "r") as fd: + test_case_dict = json.load(fd) + + pipeline_dict = test_case_dict["pipeline"] + return test_case_dict["metadata"]["filename"], pipeline_dict + + +def run_ssh_test(private_key): + cmd = ["ssh", + "-p", "1022", + "-i", private_key, + "-o", "StrictHostKeyChecking=no", + "redhat@localhost", + "systemctl is-system-running"] + for _ in range(40): + try: + sp = subprocess.run(cmd, timeout=120, check=True, stdout=subprocess.PIPE) + output = sp.stdout.decode('utf-8').strip() + print(output) + if output == "running": + print("ssh test success") + return 0 + except subprocess.TimeoutExpired: + print("ssh timeout expired") + except subprocess.CalledProcessError as e: + print(f"ssh error: {e}") + time.sleep(20) + + print("ssh test failure") + return 1 + + +def main(): + parser = argparse.ArgumentParser(description='Run test cases.') + parser.add_argument('--boot-test', type=str, nargs='*', help='Boot images produced by osbuild') + parser.add_argument('--image-info', type=str, nargs='*', + help='Build images and run image-info on them (default action)') + arg = parser.parse_args() + + # Run local boot test + if arg.boot_test is not None: + with osbuild_test_store() as store: + with create_ssh_keys() as keydir: + for test_case in arg.boot_test if arg.boot_test != [] else ["qcow2"]: + image_fname, pl_dict = get_local_boot_test_case(test_case) + print("starting osbuild") + _, output_id = run_osbuild(pl_dict, store) + print("osbuild success") + with qemu_boot_image(f"{store}/refs/{output_id}/{image_fname}"): + ret = run_ssh_test(f"{keydir}/id_rsa") + + return ret + failed = False with osbuild_test_store() as store: - for filename in args or glob.glob(f"{TEST_DIR}/cases/*.json"): + for filename in arg.image_info if arg.image_info != [] else glob.glob(f"{TEST_DIR}/cases/*.json"): name = os.path.basename(filename)[:-5] with open(filename) as f: case = json.load(f) @@ -84,6 +178,7 @@ def main(args): return 1 if failed else 0 -r = main(sys.argv[1:]) + +r = main() if r: sys.exit(r)