e672901741
Реализация замечаний ревью 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
150 lines
7.9 KiB
Makefile
150 lines
7.9 KiB
Makefile
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
|