From f5e8272c3ac51a6467712fd9d80362e4439b6ba4 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Thu, 22 Oct 2026 00:16:00 +0300 Subject: [PATCH] =?UTF-8?q?docs(#21):=20=D0=BE=D1=82=D1=87=D1=91=D1=82=20?= =?UTF-8?q?=D0=BE=20=D1=84=D0=B0=D0=BA=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA?= =?UTF-8?q?=D0=B8=D1=85=20=D0=BF=D1=80=D0=BE=D0=B3=D0=BE=D0=BD=D0=B0=D1=85?= =?UTF-8?q?=20=D0=B3=D0=B5=D0=B9=D1=82=D0=BE=D0=B2=20=D0=B8=20AC=20=D0=BD?= =?UTF-8?q?=D0=B0=20192.168.1.147=20(HEAD=207af9caba)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #21 Refs #15 --- deploy/VERIFICATION-21.md | 127 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 deploy/VERIFICATION-21.md diff --git a/deploy/VERIFICATION-21.md b/deploy/VERIFICATION-21.md new file mode 100644 index 0000000..11349b4 --- /dev/null +++ b/deploy/VERIFICATION-21.md @@ -0,0 +1,127 @@ +# Проверка dev/staging стенда (#21) — фактические прогоны на Docker-хосте + +Дата: 2026-10-22 · Хост: `192.168.1.147` (Debian 13, Docker 29.4.1, compose v5.1.3, kernel 6.17) +Ветка: `feat/21-dev-stand`, HEAD `7af9caba` · Ref: #21, #15, #17, #18, #31 + +## 0. Стенд запускает именно то, что в ветке + +Каталог стенда `(/opt/awg-dash-dev/repo)` не является git-чекаутом (`git clone` по HTTP обрывается +на этом Gitea — `fetch-pack: invalid index-pack output`), поэтому файлы сверены побайтово +через git-blob-SHA с деревом HEAD: + +| файл | git blob (HEAD == хост) | +|---|---| +| `Makefile` | `d13af0e752cb0dfc28e94ed1ad3a4ea448d58811` | +| `deploy/docker-compose.dev.yml` | `6bed89a5ea2a197aa9f6fd6bcda6d8131303114d` | +| `deploy/docker-compose.stub.yml` | `936efb38dfff4ba8b942c9757acd4ba9c39c4064` | +| `deploy/docker-compose.test.yml` | `da01e80a459580cd063359c46560adb8285434d1` | +| `deploy/verify-dev-stand.sh` | `c4e13f11f9023700be531ebb312ad33d7beea4d8` | +| `deploy/api_stub.py` | `848922dc543a6a2abffa49c02efeba383f02455f` | +| `tests/deploy/validate_compose.py` | `0fa8b3c02675a364f4f5b447220680a7818faa5a` | +| `tests/netns/*` (10 файлов) | совпадают с деревом (см. `git ls-tree feat/21-dev-stand tests/netns`) | + +## 1. Предварительные пакеты на стенд-хосте + +```bash +apt-get install -y make python3-yaml python3-pytest python3-pytest-cov shellcheck +``` + +(`make` на хосте отсутствовал — без него гейты `make *` невоспроизводимы; пакеты добавлены +сверх существующего набора, ничего не удалялось и не переконфигурировалось.) + +## 2. Гейты (реальные прогоны) + +Лог целиком: `/opt/awg-dash-dev/verify-final-1792617226.log` (на хосте). + +| гейт | команда | результат | +|---|---|---| +| манифесты | `make test-manifests` | exit 0, `validate-compose: ok (1 предупреждений)`¹ | +| статический анализ шелла | `make lint-shell` | exit 0 | +| unit-тесты манифестов | `python3 -m pytest tests/deploy -q --no-cov` | exit 0 | +| netns-харнесс (AC-3) | `make test-netns` | exit 0, `8 ok / 0 fail / 0 err`, отчёт `/tmp/awg-netns/report.json` | +| AC-1 (health 200) | `make dev-up` + `curl :8180/api/v1/health` | HTTP 200, контейнер `healthy` | +| AC-2 (состояние переживает рестарт) | `make dev-verify` | `[ ok ] AC-1`, `[ ok ] AC-2` ×2, exit 0 | +| логи | `make dev-logs` | стрим логов, есть `[api-stub] ... GET /api/v1/health 200` | + +¹ предупреждение: `build.dockerfile deploy/Dockerfile отсутствует в дереве (ожидаемо до мержа #18)`. +Образ `awg-dash:dev` для стенда собран из Dockerfile PR #49 (ветка `feat/18-docker-runtime`), в дерево +этой ветки он не входит: `make build` вернёт внятную ошибку до мержа #18. Валидатор переключается в +режим ошибки флагом `make test-manifests MANIFEST_ARGS=--require-dockerfile` — этот режим нужно включить +в CI гейте после мержа #18. + +### AC-1 — детали + +``` +$ make dev-up +# (авто-режим: backend/awg_api/app.py отсутствует (#31) → + deploy/docker-compose.stub.yml) +$ curl -s -w '\nHTTP=%{http_code}\n' http://127.0.0.1:8180/api/v1/health +{"issue": "#31", "note": "заглушка dev-стенда: реальный API появится в #31", "status": "ok", + "stub": true, "stub_env": "1", "uptime_s": 14.909} +HTTP=200 +$ docker ps --filter name=awg-dash-dev +awg-dash-dev Up 15 seconds (healthy) 0.0.0.0:8180->8080/tcp, [::]:8180->8080/tcp +``` + +Почему с заглушкой: FastAPI-каркас (#31) ещё не реализован, сам образ HTTP не поднимает (entrypoint +пишет `awg_api/app.py ещё не реализован` и ждёт). Чтобы AC-1 #21 проверялся на живом compose-стенде +уже в Sprint 0, `make dev-up` добавляет оверрайд `docker-compose.stub.yml` **только пока +`backend/awg_api/app.py` отсутствует**; ответ явно помечен `"stub": true`. После мержа #31 оверрайд +не добавляется, `make dev-up` поднимает реальный API без правок Makefile. + +### AC-2 — детали + +``` +$ make dev-verify +[verify][ ok ] AC-1: http://127.0.0.1:8180/api/v1/health -> 200 (api=stub) +[verify] AC-2: пишу маркеры в /config и /data и перезапускаю контейнер +[verify][ ok ] AC-2: /config и /data пережили restart и пересоздание контейнера +[verify][ ok ] AC-2: маркеры видны на хосте (/opt/awg-dash-dev/{config,data}) — это bind mount, а не слой контейнера + +$ ls /opt/awg-dash-dev/config /opt/awg-dash-dev/data +/opt/awg-dash-dev/config/.ac2-marker (24 байта) +/opt/awg-dash-dev/data/.ac2-marker (24 байта) +``` + +Проверяется два сценария: `docker compose restart` (как в AC) и `up -d --force-recreate` (сильнее). + +### AC-3 (netns) — детали + +``` +[netns] создаю netns: client=awgt21-client gw=awgt21-gw uplink=awgt21-uplink +[ ok ] стенд поднят: awgt21-client(10.213.0.2) -> awgt21-gw(10.213.0.1/10.214.0.1) -> awgt21-uplink(10.214.0.2) +[ ok ] policy routing: fwmark 51820 -> table 51820 (default via 10.214.0.2) +[ ok ] mock endpoint: udp/51820 в awgt21-uplink; детектор утечки: 198.51.100.9:9999/udp +Ran 8 tests in 5.447s — OK +test_01_namespaces_and_links ... test_08_killswitch_blocks_direct_egress — все ok +[ ok ] топология снесена, namespace'ы удалены (ip netns list пусто) +``` + +`report.json`: `{"suite": "tests/netns", "tests": 8, "passed": 8, "failures": 0, "errors": 0, +"skipped": 0, "returncode": 0, "duration_s": 5.447}` + +## 3. Что чинилось в этой итерации + +| проблема | причина | правка | +|---|---|---| +| `make dev-up` давал `unhealthy` и AC-1 не выполнялся | API (#31) не реализован | `Makefile`: авто-подключение stub-оверрайда, пока нет `backend/awg_api/app.py`; `dev-up-app` / `dev-up-stub` для явных режимов | +| `make dev-verify` печатал `[verify][fail] нет монтирования /config` при реально сохранённых томах и падал | `verify-dev-stand.sh` кэшировал id контейнера и делал `docker inspect` по нему после `--force-recreate` → `no such object` | перезапрос id (`cid()`) после пересоздания и явный `fatal_env` вместо ложного fail | +| `dev-up` падал без `deploy/Dockerfile` (`--build`) | Dockerfile живёт в #18, ветка не смёржена | `--build` форсируется только при наличии `deploy/Dockerfile` | + +## 4. Ограничения и что делать дальше + +1. **CI-гейты (DoD) не автоматизированы:** Gitea Actions runner для `embeddevio/awg-dash` не зарегистрирован + (см. отчёт в #17, run #1 остаётся `queued`). Все гейты в таблице §2 прогнаны **вручную** на стенд-хосте; + после регистрации runner'а в #17 они переносятся в workflow без изменений команд. +2. **Порт:** на `192.168.1.147` хост-порт 8080 занят (`drawio`), поэтому стенд публикуется как `8180:8080` + (контейнерный порт приложения — 8080, `AWG_DASH_PORT` переопределяет хост-порт). +3. **Сборка образа** — только после мержа #18; до этого образ `awg-dash:dev` собирается из ветки #18 вручную. +4. **Prod/staging:** stub-оверрайд и `deploy/api_stub.py` — DEV-ONLY. В staging/prod поднимается только + `docker-compose.dev.yml` (или прод-манифест) без stub-файла. + +## 5. Откат / очистка + +```bash +make dev-down # остановить стенд, каталоги /opt/awg-dash-dev/{config,data} сохраняются +make dev-reset # + удалить осиротевшие контейнеры/сети проекта +make test-netns # netns-харнесс сносит топологию сам; аварийно: bash tests/netns/topology.sh down +```