Sprint 0 / #21: dev/staging стенд — docker-compose, тома, netns-харнесс #53
@@ -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
|
||||
```
|
||||
Reference in New Issue
Block a user