T
Testcontainers
Fixtures & lifecycle availableSpin ephemeral service containers up for a run and down after.
$ loadr plugin install testcontainers
# Ephemeral test fixtures, stood up by the `loadr-plugin-testcontainers` native
# SERVICE plugin.
#
# A service plugin has a start/stop lifecycle: loadr calls `start(config)` once
# before the run and `stop()` once after. On start this plugin talks to the
# Docker Engine directly over its HTTP API on /var/run/docker.sock (no Docker
# client library, no CLI shell-out, no testcontainers SDK — hand-rolled HTTP/1.1
# over a Unix socket) and, for each declared container:
#
# 1. POST /containers/create (pulling the image first if it isn't local)
# 2. POST /containers/{id}/start
# 3. reads the ephemeral host port Docker assigned
# 4. blocks until the `wait` condition is satisfied
#
# Each published port is exported as an env var named
# LOADR_TC_<IMAGE>_<CONTAINER_PORT>
# (image basename upper-cased, tag stripped), so requests reference the
# host-assigned ephemeral port through normal ${env.…} interpolation. On stop
# the plugin removes every container it created; teardown is idempotent and a
# start that fails partway rolls back what it already created.
#
# Build + install the plugin, then run:
# cargo build -p loadr-plugin-testcontainers --release
# mkdir -p dist && cp plugins/loadr-plugin-testcontainers/plugin.toml dist/ \
# && cp target/release/libloadr_plugin_testcontainers.so dist/
# loadr plugin install dist
# loadr run examples/plugins/testcontainers.yaml
#
# Requires a running Docker Engine reachable on the local socket (or $DOCKER_HOST).
name: testcontainers
description: Stand up throwaway Postgres + Redis fixtures for the run, then tear them down
plugins:
# Resolve `testcontainers` by name from the plugins dir (after
# `loadr plugin install`). To run straight from a build tree instead, set:
# path: target/release/libloadr_plugin_testcontainers.so
- name: testcontainers
config:
# How long start() waits for ALL containers to become ready before it
# rolls everything back and fails the run.
startup_timeout: 60s
containers:
- image: postgres:16
# Publish 5432 to an ephemeral host port -> LOADR_TC_POSTGRES_5432.
port: 5432
# Block until Postgres actually accepts connections, not just "running".
wait: "log:database system is ready to accept connections"
env:
POSTGRES_PASSWORD: test
- image: redis:7-alpine
port: 6379
wait: "log:Ready to accept connections"
scenarios:
main:
executor: constant-vus
vus: 20
duration: 30s
flow:
# Both requests reach the containers through the ephemeral host ports the
# plugin exported as LOADR_TC_* env vars — never a hard-coded host port,
# so concurrent runs on one machine never clash.
- request:
name: query
protocol: postgres
url: postgres://postgres:test@127.0.0.1:${env.LOADR_TC_POSTGRES_5432}/postgres
plugin:
query: "SELECT 1"
- request:
name: cache ping
url: redis://127.0.0.1:${env.LOADR_TC_REDIS_6379}
plugin:
command: ["PING"]
thresholds:
checks: [ "rate>0.99" ]
A real run: install from the signed index, then watch the plugin work.
A runtime plugin, never in the binary
Installing pulls a per-platform driver from the signed index, verifies its SHA-256 and checks its ABI before it ever loads. Remove it any time with loadr plugin remove testcontainers.