94d3a28adf
Приведение документации к фактическому поведению после ревью PR #53 (раунд 2): точка входа для CI без make (контракт 0/1/3/4), приоритет AWG_NS_EXEC_MODE над make-алиасом, сборка без сети (DEV_SKIP_BUILD=1). Refs #21 Refs #56
128 lines
9.0 KiB
Markdown
128 lines
9.0 KiB
Markdown
# dev/staging стенд awg-dash — runbook
|
||
|
||
Задача **#21** (эпик **#15**). Стенд для локальной разработки и проверки
|
||
acceptance criteria до появления staging-окружения.
|
||
|
||
* Docker-хост: **192.168.1.147** (`ssh root@192.168.1.147`), Docker 29.4.x + compose v5.
|
||
* Каталог состояния: **`/opt/awg-dash-dev/{config,data}`** (bind mount → `/config`, `/data`).
|
||
* Compose project: **`awg-dash-dev`** (изолирован от PoC-контейнеров `amneziawg-client`).
|
||
* Хост-порт приложения: **8180** (`AWG_DASH_PORT`), внутри контейнера — **8080**.
|
||
Порт 8080 на dev-хосте занят другим сервисом (drawio), поэтому проброс нестандартный.
|
||
|
||
## Быстрый старт
|
||
|
||
```bash
|
||
# на Docker-хосте, из корня репозитория
|
||
export AWG_DASH_HOST_DIR=/opt/awg-dash-dev
|
||
make dev-up # docker compose up -d --build (проект awg-dash-dev)
|
||
make dev-verify # проверка AC: health 200 + состояние переживает restart
|
||
curl -fsS http://127.0.0.1:8180/api/v1/health
|
||
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-заглушку:
|
||
|
||
```bash
|
||
make dev-up-stub # + deploy/docker-compose.stub.yml (DEV-ONLY, api_stub.py)
|
||
make dev-verify-stub # AC-1 проходит на заглушке, в отчёте api=stub
|
||
```
|
||
|
||
Заглушка отвечает `{"status":"ok","stub":true,...}` только на `/api/v1/health` и
|
||
никогда не должна использоваться в staging/prod.
|
||
|
||
## Проверка AC (#21)
|
||
|
||
| AC | Команда | Ожидание |
|
||
|---|---|---|
|
||
| AC-1: health 200 | `curl -fsS -o /dev/null -w '%{http_code}' http://127.0.0.1:8180/api/v1/health` | `200` (после мержа #31; до него — заглушка через `dev-verify-stub`) |
|
||
| AC-2: состояние переживает restart | `make dev-verify` | маркеры в `/config` и `/data` совпадают до и после `docker compose restart` и `--force-recreate` |
|
||
| AC-3: netns + мок-endpoint | `make test-netns` | 8/8 тестов, netns `awgt21-{client,gw,uplink}` создаются и сносятся |
|
||
|
||
`deploy/verify-dev-stand.sh` (за `make dev-verify`) печатает отчёт и возвращает:
|
||
|
||
| Код | Значение |
|
||
|---|---|
|
||
| 0 | AC-1 и AC-2 выполнены |
|
||
| 1 | регрессия стенда (health не 200 с заглушкой, состояние не сохранилось) |
|
||
| 2 | AC-1 заблокирован: API (#31) ещё не реализован, стенд при этом поднят |
|
||
| 3 | заблокировано окружением: нет docker/compose или compose-файлов |
|
||
|
||
## Состав стенда
|
||
|
||
| Файл | Назначение |
|
||
|---|---|
|
||
| `docker-compose.dev.yml` | приложение: порт 8080 (наружу `${AWG_DASH_PORT:-8180}`), bind mount `/config` `/data`, healthcheck, NET_ADMIN/NET_RAW/SYS_MODULE, `/dev/net/tun` |
|
||
| `docker-compose.stub.yml` | DEV-ONLY оверрайд: health-заглушка до #31 (`api_stub.py`) |
|
||
| `docker-compose.test.yml` | тестовый стенд: привилегированный `netns`-раннер + `app` для API-тестов |
|
||
| `api_stub.py` | минимальный HTTP-сервер `/api/v1/health` (только dev) |
|
||
| `verify-dev-stand.sh` | проверка AC на Docker-хосте + JSON-отчёт |
|
||
| `../tests/netns/` | netns-харнесс: топология client/gw/uplink + мок WireGuard-endpoint |
|
||
|
||
## Переменные окружения
|
||
|
||
| Переменная | По умолчанию | Назначение |
|
||
|---|---|---|
|
||
| `AWG_DASH_PORT` | `8180` | хост-порт приложения |
|
||
| `AWG_DASH_HOST_DIR` | `/opt/awg-dash-dev` | каталог состояния на хосте |
|
||
| `AWG_DASH_IMAGE` | `awg-dash:dev` | имя образа (build или pull) |
|
||
| `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`) |
|
||
|
||
## Зависимости
|
||
|
||
| Зависимость | Состояние | Влияние на стенд |
|
||
|---|---|---|
|
||
| #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 | гейты для пайплайна: `bash tests/netns/ci.sh` (коды 0/1/3/4), `make test-manifests`, `make test-deploy`, `make lint-shell` |
|
||
|
||
## Откат и уборка
|
||
|
||
```bash
|
||
make dev-down # остановить контейнеры проекта awg-dash-dev
|
||
make dev-reset # down --remove-orphans (состояние сохраняется)
|
||
docker image rm awg-dash:dev # откатить образ (пересобрать из предыдущего коммита)
|
||
du -sh /opt/awg-dash-dev # состояние стенда
|
||
```
|
||
|
||
Перед откатом образа проверьте проект: `docker compose -p awg-dash-dev ls`.
|
||
Состояние (`/opt/awg-dash-dev`) не удаляется автоматически — это осознанно: там
|
||
конфиги туннеля (`/config/awg0.conf`). Удаляйте вручную и только после бэкапа.
|
||
|
||
## Pitfalls
|
||
|
||
* **Порт 8080 занят** на dev-хосте — наружу публикуется 8180. Меняйте `AWG_DASH_PORT`.
|
||
* **`/dev/net/tun` обязателен**: без него entrypoint падает (`fail '/dev/net/tun не проброшен'`).
|
||
* **Права на каталоги состояния**: entrypoint делает `chown awg:awg /config /data`;
|
||
каталоги создаются на хосте от root — не меняйте владельца на хосте вручную.
|
||
* **`docker compose restart` сохраняет тома**; `down -v` — нет. Никогда не используйте
|
||
`down -v` на этом стенде: это удалит `/config` и `/data`.
|
||
* **Заглушка `api_stub.py`** — только dev: она отвечает 200 на `/api/v1/health` и
|
||
маскирует отсутствие 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`).
|