Files
embeddevio e672901741 deploy(#21): контракт кодов netns без make, AWG_NS_EXEC_MODE в приоритете, DEV_SKIP_BUILD
Реализация замечаний ревью PR #53 (issuecomment-664):

1. tests/netns/ci.sh — точка входа для CI #17 без make: docker compose run --rm -T
   netns, код контейнера возвращается как есть (0/1/3/4; 2 — сломан вызов/нет
   docker/образа). make test-netns-ci делегирует в неё, в комментарии таргета
   зафиксировано «make → 2».
2. NETNS_EXEC_MODE ?= $(if $(AWG_NS_EXEC_MODE),$(AWG_NS_EXEC_MODE),auto) —
   документированный AWG_NS_EXEC_MODE больше не перекрывается make-алиасом.
3. DEV_SKIP_BUILD=1 → up -d --no-build; DEV_UP_BUILD переопределяем (?) —
   dev-up работает на хосте без DNS/сети для сборки.

Refs #21
Refs #56
2026-10-28 21:57:44 +03:00

150 lines
7.9 KiB
Makefile
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
PY ?= python3
VENV ?= .venv
BIN := $(VENV)/bin
IMAGE ?= awg-dash:dev
COMPOSE_DEV := deploy/docker-compose.dev.yml
COMPOSE_TEST := deploy/docker-compose.test.yml
COMPOSE_STUB := deploy/docker-compose.stub.yml
VERIFY := deploy/verify-dev-stand.sh
COMPOSE ?= docker compose
# Состояние dev-стенда: bind mount для /config и /data (AC-2 задачи #21).
HOST_DIR ?= /opt/awg-dash-dev
# Хост-порт стенда. На dev-хосте 8080 занят другим сервисом — по умолчанию 8180;
# внутри контейнера приложение всегда на 8080.
DASH_PORT ?= 8180
NETNS_ARGS ?=
VERIFY_ARGS ?=
MANIFEST_ARGS ?=
# Режим входа в netns: auto|ip|nsenter (issue #56). Документированное имя —
# AWG_NS_EXEC_MODE (его читают lib.sh/run.sh и tests/netns/ci.sh); NETNS_EXEC_MODE —
# make-алиас. Раньше здесь стояло `?= auto`, из-за чего AWG_NS_EXEC_MODE=ip на
# `make test-netns-ci` молча игнорировался (замечание ревью #56).
NETNS_EXEC_MODE ?= $(if $(AWG_NS_EXEC_MODE),$(AWG_NS_EXEC_MODE),auto)
.PHONY: help venv lint fmt test build dev-up dev-up-app dev-up-stub dev-down dev-logs dev-verify \
dev-verify-stub dev-reset test-netns test-netns-keep test-netns-ci test-manifests lint-shell \
test-deploy
help:
@grep -E '^[a-zA-Z_-]+:' $(MAKEFILE_LIST) | sed 's/:.*//' | sort -u
venv:
$(PY) -m venv $(VENV)
$(BIN)/pip install -U pip
$(BIN)/pip install -r requirements-dev.txt
lint:
$(BIN)/ruff check backend
$(BIN)/mypy backend
fmt:
$(BIN)/ruff format backend
$(BIN)/ruff check --fix backend
test:
$(BIN)/pytest
build:
@test -f deploy/Dockerfile || { echo 'deploy/Dockerfile ещё нет — задача #18'; exit 1; }
docker build -f deploy/Dockerfile -t $(IMAGE) .
# --- dev/staging стенд (задача #21) ------------------------------------------
# Пока FastAPI-каркас (#31) не реализован, API в образе не поднимается и AC-1
# (`curl :8080/api/v1/health` -> 200) недостижим. Чтобы гейт #21 проверялся на
# живом стенде, `dev-up` автоматически добавляет оверрайд с health-заглушкой
# (deploy/docker-compose.stub.yml), ПОКА файла приложения нет. После мержа #31
# оверрайд отключается сам. Явные режимы: dev-up-app / dev-up-stub.
API_APP ?= backend/awg_api/app.py
ifneq ($(wildcard $(API_APP)),)
COMPOSE_DEV_EFFECTIVE := -f $(COMPOSE_DEV)
STUB_MODE := 0
else
COMPOSE_DEV_EFFECTIVE := -f $(COMPOSE_DEV) -f $(COMPOSE_STUB)
STUB_MODE := 1
endif
# deploy/Dockerfile приходит с задачей #18; до этого образ собирается отдельно,
# поэтому --build не форсируем, если Dockerfile отсутствует в дереве.
# После мержа #18 файл есть → --build обязателен, но не всегда возможен: на
# стенд-хосте нет DNS/сети для pull базового образа. Явные кнобы:
# make dev-up DEV_SKIP_BUILD=1 → up -d --no-build (использовать готовый образ)
# make dev-up DEV_UP_BUILD= → вообще не передавать флаги сборки
DEV_UP_BUILD ?= $(if $(wildcard deploy/Dockerfile),--build,)
ifeq ($(DEV_SKIP_BUILD),1)
DEV_UP_BUILD := --no-build
endif
DEV_ENV := AWG_DASH_PORT=$(DASH_PORT) AWG_DASH_HOST_DIR=$(HOST_DIR)
DEV_VERIFY_ARGS := $(if $(filter 1,$(STUB_MODE)),--stub,)
dev-up:
@test -f $(COMPOSE_DEV) || { echo '$(COMPOSE_DEV) ещё нет — задача #21'; exit 1; }
@command -v docker >/dev/null 2>&1 || { echo 'нет docker: dev-стенд поднимается на Docker-хосте (см. deploy/dev-stand.md)'; exit 1; }
@[ "$(STUB_MODE)" = "0" ] || echo 'dev-up: API (#31) ещё не в дереве — поднимаю стенд с health-заглушкой (deploy/docker-compose.stub.yml)'
$(DEV_ENV) $(COMPOSE) $(COMPOSE_DEV_EFFECTIVE) up -d $(DEV_UP_BUILD)
# Только реальный образ: проверка отказа API без заглушки / режим после #31.
dev-up-app:
@test -f $(COMPOSE_DEV) || { echo '$(COMPOSE_DEV) ещё нет — задача #21'; exit 1; }
$(DEV_ENV) $(COMPOSE) -f $(COMPOSE_DEV) up -d $(DEV_UP_BUILD)
# Только health-заглушка (проверка плумбинга стенда до #31).
dev-up-stub:
@test -f $(COMPOSE_STUB) || { echo '$(COMPOSE_STUB) ещё нет — задача #21'; exit 1; }
$(DEV_ENV) $(COMPOSE) -f $(COMPOSE_DEV) -f $(COMPOSE_STUB) up -d $(DEV_UP_BUILD)
dev-down:
$(DEV_ENV) $(COMPOSE) $(COMPOSE_DEV_EFFECTIVE) down
dev-logs:
$(DEV_ENV) $(COMPOSE) $(COMPOSE_DEV_EFFECTIVE) logs -f --tail=100
# Проверка AC #21 на Docker-хосте: health 200 + состояние переживает restart.
dev-verify:
$(DEV_ENV) bash $(VERIFY) $(DEV_VERIFY_ARGS) $(VERIFY_ARGS)
dev-verify-stub:
$(DEV_ENV) bash $(VERIFY) --stub $(VERIFY_ARGS)
# Останавливает стенд; каталоги состояния сохраняются (удалять вручную).
dev-reset:
$(DEV_ENV) $(COMPOSE) $(COMPOSE_DEV_EFFECTIVE) down --remove-orphans
@echo "каталоги состояния сохранены: $(HOST_DIR)/config, $(HOST_DIR)/data (удалять вручную)"
# --- netns-стенд (задача #21) ------------------------------------------------
test-netns:
@test -d tests/netns || { echo 'tests/netns ещё нет — задача #21'; exit 1; }
bash tests/netns/run.sh $(NETNS_ARGS)
# То же, но топология и логи остаются для отладки (снести: tests/netns/topology.sh down).
test-netns-keep:
bash tests/netns/run.sh --keep-topology --keep-logs $(NETNS_ARGS)
# Тот же стенд в привилегированном контейнере — путь для CI (#17).
# Внутри контейнера `ip netns exec` падает с "mount of /sys failed: Operation
# not permitted" (iproute2 6.x), поэтому харнесс сам переключается на
# `nsenter --net=/var/run/netns/<ns>` (issue #56). Режим задаётся
# AWG_NS_EXEC_MODE=ip|nsenter|auto (make-алиас — NETNS_EXEC_MODE).
#
# ВАЖНО: make возвращает 2 на любой упавший рецепт, поэтому контракт кодов
# 0/1/3/4 через этот таргет НЕ виден (см. deploy/VERIFICATION-21.md §6.1).
# В пайплайне #17 используйте точку входа без make:
# bash tests/netns/ci.sh # те же 0/1/3/4, что отдаёт контейнер
test-netns-ci:
@test -d tests/netns || { echo 'tests/netns ещё нет — задача #21'; exit 1; }
AWG_DASH_IMAGE=$(IMAGE) AWG_NS_EXEC_MODE=$(NETNS_EXEC_MODE) bash tests/netns/ci.sh $(NETNS_ARGS)
# --- статические проверки манифестов и скриптов ------------------------------
test-manifests:
$(PY) tests/deploy/validate_compose.py $(MANIFEST_ARGS)
# Тесты стенда с покрытием: гейт DoD «тесты ≥70 %» для #21/#56.
# Отдельный tests/deploy/pytest.ini обязателен: без него `pytest tests/deploy`
# наследует addopts корневого pyproject.toml (--cov=awg_agent --cov=awg_api),
# покрытие выходит 0.00 % и RC=1 — гейт приходилось гонять с --no-cov.
test-deploy:
@test -d tests/deploy || { echo 'tests/deploy ещё нет — задача #21'; exit 1; }
$(PY) -m pytest tests/deploy -c tests/deploy/pytest.ini
lint-shell:
@command -v shellcheck >/dev/null 2>&1 || { echo 'shellcheck не установлен (apt-get install shellcheck)'; exit 1; }
shellcheck -x -S style tests/netns/*.sh deploy/*.sh