Files
crowdsec-bouncer-traefik-pl…/tests/e2e/mock/README.md
T
mhxandClaude Opus 4.8 b67edfe308 🔥 e2e mock: simplify the Crowdsec LAPI mock
Per review, trim the mock to the minimum the plugin actually exercises:

- Drop the stream delta bookkeeping (startup flag + "already streamed" set).
  The plugin re-Sets/Deletes its cache on every poll, so reporting the whole
  active set as "new" and removed ones as "deleted" is enough.
- Shrink the Decision struct to the three fields the plugin reads
  (value/type/duration); drop id/origin/scope/scenario and the id counter.
- Drop API-key auth and the /admin/reset endpoint — no scenario exercises
  either. Also drop the now-unused lapi_reset helper.
- Replace the store struct + methods with two package-level maps + a mutex.

mocklapi/main.go: 234 -> 118 lines. All six scenarios still pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 12:03:19 +02:00

85 lines
3.3 KiB
Markdown

# 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/`](mocklapi/main.go), a stdlib-only Go command). No Docker, no real
Crowdsec.
It is what **CI runs** (`make e2e_mock`). A separate, local-only **Docker
suite** (real Traefik + Crowdsec, under `tests/e2e/scenarios`) is kept for
high-fidelity debugging against a real Crowdsec but is not exercised in CI; it
ships in its own PR (#333).
## 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](https://github.com/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.
```bash
# 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
1. Create `scenarios/<name>/dynamic.yml` and `run.sh` (copy `stream-mode/` as a
template).
2. In `run.sh`, define a `body` function with the assertions and call
`run_scenario "<name>" "$HERE" body`.
3. Drive decisions with `lapi_add_decision <ip> [type] [duration]` and
`lapi_delete_decision <ip>`.
4. Add `<name>` to `E2E_MOCK_SCENARIOS` in the `Makefile`.