Skip to content

Commit d5c88b5

Browse files
committed
docs: split container-based tests into host-side and in-container patterns
Pattern B (plugin runs inside the container) is the cpu-usage shape. New tests of that shape should target the same OS-platform matrix as cpu-usage so coverage stays consistent across plugins and adding a new distro is a single-line change everywhere. Also document the clean_up=False and ,Z bind-mount rules learned during the last sweep.
1 parent 932b29b commit d5c88b5

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

CONTRIBUTING.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,14 @@ sudo apt install python3.9-dev python3.10-dev python3.11-dev \
870870

871871
#### Container-based tests
872872

873-
For checks that must run against a real service (Keycloak, Redis, a database, a web API), use the `lib.lftest.run_container()` helper from the `linuxfabrik-lib` package. It wraps [testcontainers-python](https://testcontainers-python.readthedocs.io/) so that container lifecycle, port exposure, environment variables and log-based readiness waits are declarative rather than hand-rolled podman orchestration.
873+
Container-based tests come in two shapes:
874+
875+
* **Plugin runs from the host, service runs in the container.** Used when the plugin talks to a real service over the network (Keycloak, Redis, a database, a web API). Pull an upstream service image, expose its port, point the plugin at the container from outside. This is the common case.
876+
* **Plugin runs inside the container.** Used when the plugin reads host-local resources (`/proc`, `/sys`, distro-shipped binaries, distro-specific Python/psutil field availability) and there is no meaningful way to fixture the input. The plugin is bind-mounted into the container and executed via `container.exec()`. See `check-plugins/cpu-usage/unit-test/run` for the reference implementation.
877+
878+
##### Plugin runs from the host, service runs in the container
879+
880+
Use the `lib.lftest.run_container()` helper from the `linuxfabrik-lib` package. It wraps [testcontainers-python](https://testcontainers-python.readthedocs.io/) so that container lifecycle, port exposure, environment variables and log-based readiness waits are declarative rather than hand-rolled podman orchestration.
874881

875882
Minimal example (see `check-plugins/keycloak-version/unit-test/run` for the full reference):
876883

@@ -936,6 +943,31 @@ Rules and tips:
936943
* **Keep hand-rolled podman orchestration out of new tests.** If you find a plugin that still builds containers via `subprocess.run(['podman', 'build', ...])`, migrate it to `lib.lftest.run_container()`; the old pattern is being retired.
937944

938945

946+
##### Plugin runs inside the container
947+
948+
Some plugins can only be tested meaningfully when they run inside a distribution they target, because the data source is host-local (`/proc`, `/sys`, a distro binary like `mariadb --version`, or a `psutil` field whose availability depends on kernel version + python version + distro packaging). There is no network endpoint we can redirect, and a static fixture would hide the thing we actually want to test: "does this plugin run cleanly on the distros our customers run".
949+
950+
For that case, use a `Containerfile` per target distro under `unit-test/containerfiles/<distro>-v<version>` that installs python3, the plugin's requirements and keeps the container alive via `CMD ["sleep", "infinity"]`. Iterate over the file list via `lib.lftest.attach_each()` so every distro shows up as its own `test_<distro>` method. Bind-mount `lib/` and the plugin script into `/tmp` and run them via `container.exec()`.
951+
952+
The canonical distro matrix is the cpu-usage `CONTAINERFILES` list. **Where possible, new "plugin runs inside the container" tests should target the same OS platforms** so the coverage stays consistent across plugins and adding a new distro is a single-line change everywhere:
953+
954+
```text
955+
archlinux-vlatest
956+
debian-v11 / v12 / v13
957+
fedora-v35 / v40 / v41 / v42 / v43
958+
rhel-v8 / v9 / v10
959+
sles-v15 / v16
960+
ubuntu-v2004 / v2204 / v2404 / v2604
961+
```
962+
963+
Rules and tips:
964+
965+
* **Reuse cpu-usage's `containerfiles/`** as a starting point for a new plugin - the per-distro bootstrap (pacman / apt / dnf / zypper + venv + `pip install -r requirements.txt --require-hashes`) is identical, only the bind-mount path for the plugin script changes.
966+
* **`clean_up=False` on `DockerImage`**. Testcontainers' default cleans up the built image and prunes dangling parent layers on exit, which turns every run into a full rebuild. `clean_up=False` keeps the image around so subsequent runs hit podman's layer cache and finish in seconds.
967+
* **`,Z` on bind mounts**. On SELinux-enforcing hosts (RHEL, Fedora, Rocky) unrelabelled bind mounts are denied by the container runtime. `mode='ro,Z'` relabels the source so the container can read it; without the `Z` flag the plugin inside the container sees "Permission denied" on `import lib`.
968+
* **Rootless podman caveats** - same as for the service-container pattern: `TESTCONTAINERS_RYUK_DISABLED=true` must be set, `CONTAINER_HOST` / `DOCKER_HOST` must point at the rootless socket. `tools/run-unit-tests` does this automatically.
969+
970+
939971
### sudoers File
940972

941973
If the plugin requires `sudo`-permissions to run, please add the plugin to the `sudoers`-files for all supported operating systems in `assets/sudoers/`. The OS name should match the ansible variables `ansible_facts['distribution'] + ansible_facts['distribution_major_version']` (eg `CentOS7`). Use symbolic links to prevent duplicate files.

0 commit comments

Comments
 (0)