Introduce local boot test case for QCOW2
The tests works by executing osbuild with predefined pipeline. Then the image boots and the testing script creates SSH connection to the running VM. If everything goes fine `systemctl is-system-running` is executed with result `running` and the test case passed. The JSON definition of the test case contains also a blueprint that should generate the desired pipeline, but it didn't work for me, so I'm including it for future use from the golang unit tests.
This commit is contained in:
parent
3aab64575b
commit
77c2ab0e1c
6 changed files with 317 additions and 18 deletions
11
.travis.yml
11
.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
|
||||
|
|
|
|||
|
|
@ -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) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
168
test/cases/qcow2_local_boot.json
Normal file
168
test/cases/qcow2_local_boot.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
test/keyring/id_rsa
Normal file
27
test/keyring/id_rsa
Normal file
|
|
@ -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-----
|
||||
1
test/keyring/id_rsa.pub
Normal file
1
test/keyring/id_rsa.pub
Normal file
|
|
@ -0,0 +1 @@
|
|||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC61wMCjOSHwbVb4VfVyl5sn497qW4PsdQ7Ty7aD6wDNZ/QjjULkDV/yW5WjDlDQ7UqFH0Sr7vywjqDizUAqK7zM5FsUKsUXWHWwg/ehKg8j9xKcMv11AkFoUoujtfAujnKODkk58XSA9whPr7qcw3vPrmog680pnMSzf9LC7J6kXfs6lkoKfBh9VnlxusCrw2yg0qI1fHAZBLPx7mW6+me71QZsS6sVz8v8KXyrXsKTdnF50FjzHcK9HXDBtSJS5wA3fkcRYymJe0o6WMWNdgSRVpoSiWaHHmFgdMUJaYoCfhXzyl7LtNb3Q+Sveg+tJK7JaRXBLMUllOlJ6ll5Hod root@localhost
|
||||
125
test/run
125
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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue