Skip to content

Commit ca2a2b0

Browse files
examples: port the tests to test.thing
Drop our dependency on cockpit-bots (checked out from its git repository and requiring libvirt and other heavy dependencies) and switch over to using test.thing (vendored) via pytest. We can't yet use ephemeral key support for the UKI scenarios because they enable selinux and there is an outstanding bug preventing sshd from reading the key: https://bugzilla.redhat.com/show_bug.cgi?id=2374928 For this reason, we keep the old cockpit-tests ssh identity file around and use it instead. We do include the workarounds to enable ephemeral key support in the images to make them easier to use with `test.thing` interactively. Expand examples/README.md to describe how this is all intended to be used. Signed-off-by: Allison Karlitskaya <[email protected]>
1 parent eecb25b commit ca2a2b0

File tree

10 files changed

+1138
-81
lines changed

10 files changed

+1138
-81
lines changed

.github/workflows/examples.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ jobs:
3737

3838
- name: Setup /dev/kvm
3939
run: |
40+
set -eux
4041
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm.rules
42+
echo 'KERNEL=="vhost-vsock", GROUP="kvm", MODE="0666", OPTIONS+="static_node=vhost-vsock"' | sudo tee /etc/udev/rules.d/99-vhost-vsock.rules
4143
sudo udevadm control --reload-rules
42-
sudo udevadm trigger --name-match=kvm --settle
43-
ls -l /dev/kvm
44+
sudo udevadm trigger
45+
ls -l /dev/kvm /dev/vhost-vsock
4446
4547
- name: Install dependencies
4648
run: |
@@ -51,10 +53,8 @@ jobs:
5153
erofs-utils \
5254
fsverity \
5355
mtools \
54-
libvirt-daemon \
55-
libvirt-daemon-driver-qemu \
56-
python3-libvirt \
57-
qemu-system \
56+
python3-pytest-asyncio \
57+
qemu-kvm \
5858
systemd-boot-efi
5959
sudo apt-get build-dep systemd e2fsprogs
6060
@@ -71,6 +71,9 @@ jobs:
7171
mkdir ~/bin
7272
examples/common/install-patched-tools ~/bin
7373
74+
- name: Install systemd-ssh-proxy polyfill
75+
run: sudo cp examples/bls/test-thing.workarounds/systemd-ssh-proxy /usr/lib/systemd
76+
7477
- name: Run example tests
7578
run: |
7679
export PATH="${HOME}/bin:${PATH}"

examples/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
/*/*.qcow2
12
/*/VARS_CUSTOM.secboot.fd*
23
/*/cfsctl
34
/*/extra/usr/lib/dracut/modules.d/37composefs/composefs-setup-root
4-
/*/*.qcow2
55
/*/secureboot
66
/*/tmp/
77
/common/fix-verity/fix-verity.efi
88
/test/bots
9+
__pycache__/

examples/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,45 @@ a verified operating system image.
1212
- `unified`: similar to the `uki` example, but avoiding the intermediate `cfsctl` step by running `cfsctl` inside a build stage from the `Containerfile` itself.
1313
This involves bind-mounting the earlier build stage of the base image so that we can measure it from inside the stage that builds the UKI.
1414
- `unified-secureboot`: based on the `unified` example, adding signing for Secure Boot.
15+
16+
## Using the examples
17+
18+
The main use of the examples is to act as a scratch space for feature
19+
development (like initramfs integration) and to show how you can build a system
20+
image in various configurations using composefs. They are also run from CI and
21+
are very useful for local testing, however.
22+
23+
You can build the various images using the `build` script found in each
24+
subdirectory. It takes a single argument: the OS to build the image from
25+
(`fedora`, `rawhide`, `arch`, `ubuntu`, `rhel9`, etc.). You should not build
26+
multiple images in parallel due to conflicting feature flags and shared use of
27+
the tmp/ directory. After the image is built, you can run tests against it by
28+
saying something like:
29+
30+
```
31+
TEST_IMAGE=examples/bls/arch-bls-efi.qcow2 pytest examples/test
32+
```
33+
34+
Building and running tests on a particular image is supported via the
35+
`examples/test/run` script, which you can use like:
36+
37+
```
38+
examples/test/run bls rhel9
39+
```
40+
41+
The tests are run using [`test.thing`](https://codeberg.org/lis/test.thing). We
42+
keep a copy of it in-tree. You you can also use it to run the VM images for
43+
manual inspection:
44+
45+
```
46+
examples/testthing.py examples/bls/fedora-bls-efi.qcow2
47+
```
48+
49+
In that case, you should add this fragment to your ssh configuration:
50+
51+
```
52+
Host tt.*
53+
ControlPath ${XDG_RUNTIME_DIR}/test.thing/%h/ssh
54+
```
55+
56+
So you can access the test machine via `ssh tt.0` and so on.

examples/pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[tool.pytest.ini_options]
2+
addopts = "-sv"
3+
asyncio_mode = "auto"
4+
testpaths = ["test"]
5+
pythonpath = '.'

examples/test/identity

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpQIBAAKCAQEA1DrTSXQRF8isQQfPfK3U+eFC4zBrjur+Iy15kbHUYUeSHf5S
3+
jXPYbHYqD1lHj4GJajC9okle9rykKFYZMmJKXLI6987wZ8vfucXo9/kwS6BDAJto
4+
ZpZSj5sWCQ1PI0Ce8CbkazlTp5NIkjRfhXGP8mkNKMEhdNjaYceO49ilnNCIxhpb
5+
eH5dH5hybmQQNmnzf+CGCCLBFmc4g3sFbWhI1ldyJzES5ZX3ahjJZYRUfnndoUM/
6+
TzdkHGqZhL1EeFAsv5iV65HuYbchch4vBAn8jDMmHh8G1ixUCL3uAlosfarZLLyo
7+
3HrZ8U/llq7rXa93PXHyI/3NL/2YP3OMxE8baQIDAQABAoIBAQCxuOUwkKqzsQ9W
8+
kdTWArfj3RhnKigYEX9qM+2m7TT9lbKtvUiiPc2R3k4QdmIvsXlCXLigyzJkCsqp
9+
IJiPEbJV98bbuAan1Rlv92TFK36fBgC15G5D4kQXD/ce828/BSFT2C3WALamEPdn
10+
v8Xx+Ixjokcrxrdeoy4VTcjB0q21J4C2wKP1wEPeMJnuTcySiWQBdAECCbeZ4Vsj
11+
cmRdcvL6z8fedRPtDW7oec+IPkYoyXPktVt8WsQPYkwEVN4hZVBneJPCcuhikYkp
12+
T3WGmPV0MxhUvCZ6hSG8D2mscZXRq3itXVlKJsUWfIHaAIgGomWrPuqC23rOYCdT
13+
5oSZmTvFAoGBAPs1FbbxDDd1fx1hisfXHFasV/sycT6ggP/eUXpBYCqVdxPQvqcA
14+
ktplm5j04dnaQJdHZ8TPlwtL+xlWhmhFhlCFPtVpU1HzIBkp6DkSmmu0gvA/i07Z
15+
pzo5Z+HRZFzruTQx6NjDtvWwiXVLwmZn2oiLeM9xSqPu55OpITifEWNjAoGBANhH
16+
XwV6IvnbUWojs7uiSGsXuJOdB1YCJ+UF6xu8CqdbimaVakemVO02+cgbE6jzpUpo
17+
krbDKOle4fIbUYHPeyB0NMidpDxTAPCGmiJz7BCS1fCxkzRgC+TICjmk5zpaD2md
18+
HCrtzIeHNVpTE26BAjOIbo4QqOHBXk/WPen1iC3DAoGBALsD3DSj46puCMJA2ebI
19+
2EoWaDGUbgZny2GxiwrvHL7XIx1XbHg7zxhUSLBorrNW7nsxJ6m3ugUo/bjxV4LN
20+
L59Gc27ByMvbqmvRbRcAKIJCkrB1Pirnkr2f+xx8nLEotGqNNYIawlzKnqr6SbGf
21+
Y2wAGWKmPyEoPLMLWLYkhfdtAoGANsFa/Tf+wuMTqZuAVXCwhOxsfnKy+MNy9jiZ
22+
XVwuFlDGqVIKpjkmJyhT9KVmRM/qePwgqMSgBvVOnszrxcGRmpXRBzlh6yPYiQyK
23+
2U4f5dJG97j9W7U1TaaXcCCfqdZDMKnmB7hMn8NLbqK5uLBQrltMIgt1tjIOfofv
24+
BNx0raECgYEApAvjwDJ75otKz/mvL3rUf/SNpieODBOLHFQqJmF+4hrSOniHC5jf
25+
f5GS5IuYtBQ1gudBYlSs9fX6T39d2avPsZjfvvSbULXi3OlzWD8sbTtvQPuCaZGI
26+
Df9PUWMYZ3HRwwdsYovSOkT53fG6guy+vElUEDkrpZYczROZ6GUcx70=
27+
-----END RSA PRIVATE KEY-----

examples/test/identity.pub

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUOtNJdBEXyKxBB898rdT54ULjMGuO6v4jLXmRsdRhR5Id/lKNc9hsdioPWUePgYlqML2iSV72vKQoVhkyYkpcsjr3zvBny9+5xej3+TBLoEMAm2hmllKPmxYJDU8jQJ7wJuRrOVOnk0iSNF+FcY/yaQ0owSF02Nphx47j2KWc0IjGGlt4fl0fmHJuZBA2afN/4IYIIsEWZziDewVtaEjWV3InMRLllfdqGMllhFR+ed2hQz9PN2QcapmEvUR4UCy/mJXrke5htyFyHi8ECfyMMyYeHwbWLFQIve4CWix9qtksvKjcetnxT+WWrutdr3c9cfIj/c0v/Zg/c4zETxtp cockpit-test

examples/test/run

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,8 @@ set -eux
44

55
cd "${0%/*}/.."
66

7-
if [ ! -e test/bots ]; then
8-
if [ -h ~/.config/cockpit-dev/bots ]; then
9-
ln -sfT "$(realpath --relative-to=test ~/.config/cockpit-dev)/bots" test/bots
10-
else
11-
git clone https://github.com/cockpit-project/bots test/bots
12-
fi
13-
fi
14-
157
EXAMPLE="$1"
168
OS="$2"
179

1810
"${EXAMPLE}/build" "${OS}"
19-
test/run-tests "${EXAMPLE}/${OS}-${EXAMPLE}-efi.qcow2"
11+
TEST_IMAGE="${EXAMPLE}/${OS}-${EXAMPLE}-efi.qcow2" pytest test

examples/test/run-tests

Lines changed: 0 additions & 65 deletions
This file was deleted.

examples/test/test_basic.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/python3
2+
3+
import os
4+
from collections.abc import AsyncGenerator
5+
from pathlib import Path
6+
7+
import pytest
8+
9+
import testthing
10+
11+
12+
pytest_plugins = ["pytest_asyncio"]
13+
14+
15+
@pytest.fixture
16+
async def machine() -> AsyncGenerator[testthing.VirtualMachine, None]:
17+
image = os.getenv("TEST_IMAGE")
18+
if not image:
19+
raise RuntimeError("TEST_IMAGE environment variable must be set")
20+
private = Path(__file__).parent / "identity"
21+
private.chmod(0o600) # ssh will ignore it otherwise
22+
with testthing.IpcDirectory() as ipc:
23+
async with testthing.VirtualMachine(
24+
image=image, ipc=ipc, identity=(private, None), verbose=True
25+
) as vm:
26+
yield vm
27+
28+
29+
async def test_basic(machine: testthing.VirtualMachine) -> None:
30+
m = machine
31+
32+
# root filesystem is read-only
33+
with pytest.raises(testthing.SubprocessError):
34+
await m.execute("touch /a")
35+
36+
# the content of /sysroot is what we expect
37+
assert await m.execute("ls /sysroot") == "composefs\nlost+found\nstate\n"
38+
39+
# make sure /etc and /var persist across a reboot
40+
await m.write("/etc/persists.conf", "hihi conf")
41+
await m.write("/var/persists.db", "hihi db")
42+
await m.reboot()
43+
assert await m.execute("cat /etc/persists.conf") == "hihi conf"
44+
await m.execute("rm /etc/persists.conf")
45+
assert await m.execute("cat /var/persists.db") == "hihi db"
46+
await m.execute("rm /var/persists.db")

0 commit comments

Comments
 (0)