From 94d3a28adf52a12313c718e6368e031cfe6d49ba Mon Sep 17 00:00:00 2001 From: embeddevio Date: Wed, 28 Oct 2026 21:58:15 +0300 Subject: [PATCH] =?UTF-8?q?docs(#21):=20README=20netns=20=D0=B8=20runbook?= =?UTF-8?q?=20dev-stand=20=E2=80=94=20ci.sh,=20=D0=BF=D1=80=D0=B8=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D1=82=D0=B5=D1=82=20AWG=5FNS=5FEXEC=5FMODE,=20DEV?= =?UTF-8?q?=5FSKIP=5FBUILD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Приведение документации к фактическому поведению после ревью PR #53 (раунд 2): точка входа для CI без make (контракт 0/1/3/4), приоритет AWG_NS_EXEC_MODE над make-алиасом, сборка без сети (DEV_SKIP_BUILD=1). Refs #21 Refs #56 --- deploy/dev-stand.md | 21 ++++++++++++++++++++- tests/netns/README.md | 21 ++++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/deploy/dev-stand.md b/deploy/dev-stand.md index 175025e..60495f7 100644 --- a/deploy/dev-stand.md +++ b/deploy/dev-stand.md @@ -21,6 +21,15 @@ make dev-logs # логи контейнера make dev-down # остановить (каталоги состояния сохраняются) ``` +`dev-up` добавляет `--build`, когда в дереве есть `deploy/Dockerfile` (после мержа #18). +Если у хоста нет сети/DNS для `docker build` (офлайн-стенд, CI без прокси), сборку +нужно пропустить — образ `awg-dash:dev` уже должен существовать: + +```bash +make dev-up DEV_SKIP_BUILD=1 # up -d --no-build — использовать готовый образ +make dev-up DEV_UP_BUILD= # вообще не передавать флаги сборки +``` + До реализации FastAPI-каркаса (**#31**) `/api/v1/health` не отвечает — контейнер работает как агент и помечается `unhealthy`. Чтобы проверить плумбинг стенда (порт, healthcheck, тома, restart) **до** #31, используйте health-заглушку: @@ -71,6 +80,10 @@ make dev-verify-stub # AC-1 проходит на заглушке, в отч | `AWG_DASH_DOCKERFILE` | `deploy/Dockerfile` | путь к Dockerfile для build | | `COMPOSE_PROJECT_NAME` | `awg-dash-dev` | изоляция от других стендов | | `AWG_LOG_LEVEL` | `info` | уровень логирования приложения | +| `DEV_SKIP_BUILD` | — | `1` → `make dev-up` выполняет `up -d --no-build` (образ уже собран) | +| `DEV_UP_BUILD` | авто | переопределение флагов сборки (`--build`, пусто, `--no-build`) | +| `AWG_NS_EXEC_MODE` | `auto` | режим входа в netns: `auto|ip|nsenter` (issue #56) | +| `NETNS_EXEC_MODE` | `auto` | make-алиас `AWG_NS_EXEC_MODE` (приоритет у `AWG_NS_EXEC_MODE`) | ## Зависимости @@ -79,7 +92,7 @@ make dev-verify-stub # AC-1 проходит на заглушке, в отч | #16 (каркас репо, Makefile) | PR #47 | нужен `Makefile`, `requirements.txt`, `deploy/` | | #18 (образ, entrypoint) | PR #49 | нужен `deploy/Dockerfile` для `--build` | | #31 (каркас FastAPI, `/api/v1/health`) | Sprint 2 | без него AC-1 выполняется только с заглушкой | -| #17 (CI-пайплайн) | Sprint 0 | `make test-netns-ci`, `make test-manifests` — готовые гейты для пайплайна | +| #17 (CI-пайплайн) | Sprint 0 | гейты для пайплайна: `bash tests/netns/ci.sh` (коды 0/1/3/4), `make test-manifests`, `make test-deploy`, `make lint-shell` | ## Откат и уборка @@ -106,3 +119,9 @@ du -sh /opt/awg-dash-dev # состояние стенда маскирует отсутствие API. Не включайте `docker-compose.stub.yml` в staging. * **netns-стенд вне Docker** требует root: `make test-netns` вернёт код 3, если нет CAP_NET_ADMIN/CAP_SYS_ADMIN (например, в непривилегированном CI-раннере). +* **netns в контейнере (`make test-netns-ci`, `bash tests/netns/ci.sh`)**: `ip netns exec` + падает (`mount of /sys failed`), харнесс сам переходит на `nsenter`; контракт кодов + `0/1/3/4` действует на уровне контейнера. **make возвращает 2 на любом провале** — + в CI вызывайте `bash tests/netns/ci.sh`, иначе ветки 3 и 4 неразличимы (#56). +* **`--build` без сети**: после мержа #18 `dev-up` собирает образ; если на хосте нет + DNS/доступа к registry, используйте `DEV_SKIP_BUILD=1` (готовый `awg-dash:dev`). diff --git a/tests/netns/README.md b/tests/netns/README.md index 8458631..a4642f8 100644 --- a/tests/netns/README.md +++ b/tests/netns/README.md @@ -35,7 +35,9 @@ make test-netns # поднять стенд, прогнать т make test-netns-keep # оставить топологию и логи для отладки make test-netns NETNS_ARGS="--no-tests" # только поднять стенд make test-netns-ci # то же в привилегированном контейнере (путь для CI) - # в контейнере вход в netns идёт через nsenter (issue #56) + +bash tests/netns/ci.sh # точка входа для CI #17: контейнер без make + # (make отдаёт 2 на любом провале — см. ниже) bash tests/netns/topology.sh status # состояние топологии bash tests/netns/topology.sh down # снести топологию вручную @@ -49,15 +51,26 @@ backend netfilter — `nft` или `iptables` (в alpine-образе прило Коды возврата: `0` — тесты прошли, `1` — тесты упали, `3` — «заблокировано окружением» (нет прав на создание netns), `4` — ошибка самого стенда (сюда же нормализуются неожиданные коды утилит, например `255` от `ip netns exec` в контейнере). + +**В CI (#17) используйте `bash tests/netns/ci.sh`, а не `make test-netns-ci`:** +GNU make возвращает `2` на любой упавший рецепт, поэтому через make контракт +`0/1/3/4` не виден и пайплайн не отличит «раннеру не дали прав» (`3`) от +«регрессия стенда» (`4`). `ci.sh` запускает тот же контейнер напрямую и отдаёт +его код как есть (`2` у него означает «сломан вызов/нет docker/нет образа»). + Вход в namespace выполняется через `ns_exec()`: `ip netns exec` в контейнере падает (`mount of /sys failed`, issue #56), поэтому харнесс сам переключается на -`nsenter --net=/var/run/netns/`; режим форсируется `AWG_NS_EXEC_MODE`. +`nsenter --net=/var/run/netns/`; режим форсируется `AWG_NS_EXEC_MODE` +(`auto|ip|nsenter`). Тот же режим через make — `NETNS_EXEC_MODE` (алиас; +`AWG_NS_EXEC_MODE` имеет приоритет), например: +`AWG_NS_EXEC_MODE=ip make test-netns-ci`. ## Состав | Файл | Назначение | |---|---| | `run.sh` | точка входа: preflight → топология → мок → тесты → снос | +| `ci.sh` | точка входа для CI #17: тот же прогон в контейнере без make, коды `0/1/3/4` доходят до пайплайна | | `lib.sh` | конфигурация стенда + правила netfilter (nft/iptables) | | `topology.sh` | `up`/`down`/`status`/`killswitch on|off` | | `mock_wg_endpoint.py` | мок WireGuard-endpoint: отвечает на handshake initiation | @@ -92,7 +105,9 @@ backend netfilter — `nft` или `iptables` (в alpine-образе прило | `AWG_FWMARK` / `AWG_ROUTE_TABLE` | `51820` / `51820` | метка и таблица policy routing | | `AWG_FW_BACKEND` | `auto` | `nft`, `iptables` или автоопределение | | `AWG_NETNS_WORKDIR` | `mktemp -d` | каталог логов и отчёта стенда | -| `AWG_NS_EXEC_MODE` | `auto` | вход в netns: `ip`, `nsenter` или `auto` (проба) — issue #56 | +| `AWG_NS_EXEC_MODE` | `auto` | вход в netns: `ip`, `nsenter` или `auto` (проба) — issue #56; make-алиас — `NETNS_EXEC_MODE` | +| `AWG_NS_PRIVILEGED` | `1` | только для `ci.sh`: `0` — прогон без `privileged` (проверка ветки «код 3») | +| `AWG_DASH_TEST_ARTIFACTS` | `/artifacts` | каталог для `netns-report.json` (`ci.sh`) | ## Pitfalls