- Document the --backend-addr flag: it is the stub upstream service Traefik proxies allowed requests to (the traefik/whoami equivalent), not AppSec. - Move the .cache/ ignore rule from the per-suite .gitignore to the repo root .gitignore, and make the wording accurate: the cache persists across local runs but is recreated on every (fresh-runner) CI run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Binary e2e suite (Traefik binary + mock LAPI)
This suite runs Traefik as a downloaded binary with the plugin loaded from
the local source tree, and replaces Crowdsec with a small HTTP mock
(mocklapi/, a stdlib-only Go command). No Docker, no real
Crowdsec.
It is what CI runs (make e2e_mock). The Docker suite in
../scenarios is kept for local debugging against a real
Crowdsec, but is not exercised in CI.
Scope — what this suite does and does NOT test
These tests validate the plugin's own behaviour: the request flow through the Traefik middleware, the live / none / stream modes, caching, trusted-IP bypass, and ban / captcha page rendering.
They deliberately do not test that Crowdsec or its AppSec engine work correctly — that is validated and owned by the upstream maintainer (@maxlerebourg), not by this plugin. The mock only emulates the slice of the LAPI HTTP contract the plugin consumes.
So please don't open issues here about Crowdsec/AppSec detection accuracy based on this suite: the AppSec scenario is intentionally absent, and the mock returns whatever decisions the test tells it to.
What runs
| Component | How |
|---|---|
| Traefik | Binary v3.7.1, downloaded into .cache/ (reused across local runs; re-downloaded on fresh CI runners) |
| Plugin | Loaded via experimental.localPlugins from the repo root (symlinked into plugins-local/) |
| LAPI | mocklapi — a stdlib-only Go command (its own nested module), compiled and cached under .cache/, driven through /admin endpoints instead of cscli |
| Backend | A plain HTTP responder built into the mock |
Fixed ports (override with env vars if needed): Traefik 8000, LAPI 8090,
backend 8091.
Running locally
Prerequisites: bash, curl, go, tar. On first use the Traefik binary is
fetched and the mock is compiled into .cache/. That cache is reused across
local runs; CI runs on fresh runners, so both are recreated on every CI run.
# one scenario
make e2e_mock_stream-mode
# or directly
./tests/e2e/mock/scenarios/stream-mode/run.sh
# the whole suite
make e2e_mock
Layout
mock/
lib/
common.sh # stack lifecycle, Traefik download, mock build, assertions, admin client
traefik.yml # static Traefik config (shared by all scenarios)
mocklapi/
go.mod # nested module — kept out of the plugin's build/lint/vendor
main.go # mock LAPI + backend
scenarios/
<name>/
dynamic.yml # Traefik dynamic config (router + bouncer middleware + backend)
run.sh # assertions for the scenario
*.html # optional fixtures (ban / captcha templates)
dynamic.yml uses placeholders (@@APIKEY@@, @@LAPI_HOST@@,
@@BACKEND_URL@@, @@SCENARIO_DIR@@) that common.sh substitutes at runtime.
Adding a scenario
- Create
scenarios/<name>/dynamic.ymlandrun.sh(copystream-mode/as a template). - In
run.sh, define abodyfunction with the assertions and callrun_scenario "<name>" "$HERE" body. - Drive decisions with
lapi_add_decision <ip> [type] [duration],lapi_delete_decision <ip>,lapi_reset. - Add
<name>toE2E_MOCK_SCENARIOSin theMakefile.