Files
ovirt-api-simulator/Makefile
T
inecs 23c2f4bf4d Ignore Pulumi reports and allow multi-line make push commits.
Stop tracking pulumi-tests/reports artifacts and read commit messages
via Ctrl-D, matching the ProxMox simulator workflow.
2026-07-18 08:53:17 +03:00

252 lines
9.8 KiB
Makefile
Raw 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.
COMPOSE ?= docker compose
SERVICE_DEV := dev
SERVICE_SIM := simulator
PYTEST_OFFLINE := -m "not integration and not compatibility"
# Docker Hub release image (runtime target only — not the local bind-mount "dev" image).
DOCKERHUB_USER ?= inecs
IMAGE_NAME ?= ovirt-api-simulator
VERSION ?= $(shell sed -n 's/^version = "\(.*\)"/\1/p' pyproject.toml)
DOCKER_IMAGE ?= $(DOCKERHUB_USER)/$(IMAGE_NAME)
PUSH_LATEST ?= 1
COMPOSE_RELEASE ?= $(COMPOSE) -f docker-compose.release.yml
HELM_CHART ?= ./helm/ovirt-api-simulator
LAB ?= ./pulumi-tests
# Remotes used by `make push` (GitHub + antropoff).
GIT_REMOTES ?= origin antropoff
# Preferred host ports for `make up-local` (override / .env stay gitignored).
LOCAL_ENGINE_PORT ?= 6443
LOCAL_UI_PORT ?= 6080
.PHONY: help install format lint typecheck test test-unit test-integration test-contract \
test-surface test-versions coverage up down restart logs seed seed-small seed-large seed-big seed-demo \
audit-seed-dump smoke clean ci shell \
helm-template generate-packs \
release release-build release-up release-down release-seed \
test-pulumi-smoke test-pulumi pulumi-tests \
test-smoke-all test-all clean-test-resources push up-local down-local
help: ## Show available commands
@awk 'BEGIN {FS = ":.*## "}; /^[a-zA-Z0-9_-]+:.*## / {printf "%-22s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
install: ## Build runtime and development images
@test -f .env || cp .env.example .env
$(COMPOSE) build simulator $(SERVICE_DEV)
generate-packs: ## Regenerate contracts/ovirt series packs
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) python tools/ovirt_api_inventory/generate_packs.py
format: ## Format Python sources
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) ruff format .
lint: ## Run Ruff lint checks
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) ruff check app tests
typecheck: ## Run strict mypy checks
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) mypy app/ovirt app/web/routes.py app/main.py app/config.py app/lifespan.py
test: ## Run offline unit and contract tests
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest $(PYTEST_OFFLINE)
test-unit: ## Run unit tests
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest tests/unit tests/ovirt -q
test-integration: ## Run tests that require PostgreSQL
@test -f .env || cp .env.example .env
$(COMPOSE) up -d postgres migrate
$(COMPOSE) run --rm $(SERVICE_DEV) pytest -m integration tests/ovirt -q
test-contract: ## Validate oVirt contract packs
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest -m contract tests/ovirt -q
test-surface: ## Probe Engine API surface across series
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --wait
$(COMPOSE) run --rm --no-deps --entrypoint python $(SERVICE_SIM) -m pytest tests/ovirt -q --tb=line
test-versions: ## All Engine series packs with seeded inventory assertions
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --wait
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile minimal
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest -m integration tests/ovirt/test_api_versions.py -q --tb=short
coverage: ## Offline coverage
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest $(PYTEST_OFFLINE) --cov=app/ovirt --cov-report=term-missing
up: ## Start PostgreSQL, simulator, and Engine gateway
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --build --wait
# Writes gitignored docker-compose.override.yml (+ syncs ports into .env) when
# default 443/5000 are busy (common on macOS). Compose auto-merges the override.
up-local: ## Start stack with local port override (not committed)
@set -e; \
test -f .env || cp .env.example .env; \
pick_port() { \
preferred="$$1"; shift; \
for p in "$$preferred" "$$@"; do \
if ! lsof -nP -iTCP:"$$p" -sTCP:LISTEN >/dev/null 2>&1; then \
echo "$$p"; return 0; \
fi; \
done; \
echo "No free port among: $$preferred $$*" >&2; exit 1; \
}; \
engine_port=$$(pick_port "$(LOCAL_ENGINE_PORT)" 6443 7443 8443 16443); \
ui_port=$$(pick_port "$(LOCAL_UI_PORT)" 6080 7080 8080 16080); \
printf '%s\n' \
'# Generated by `make up-local` — gitignored, do not commit.' \
'services:' \
' api-gateway:' \
' ports:' \
" - \"$${engine_port}:443\"" \
" - \"$${ui_port}:5000\"" \
> docker-compose.override.yml; \
if grep -q '^OVIRT_ENGINE_PORT=' .env; then \
sed -i.bak -e "s/^OVIRT_ENGINE_PORT=.*/OVIRT_ENGINE_PORT=$${engine_port}/" \
-e "s/^OVIRT_UI_PORT=.*/OVIRT_UI_PORT=$${ui_port}/" .env && rm -f .env.bak; \
else \
printf '\nOVIRT_ENGINE_PORT=%s\nOVIRT_UI_PORT=%s\n' "$$engine_port" "$$ui_port" >> .env; \
fi; \
echo "Local ports → Engine https://127.0.0.1:$${engine_port} UI http://127.0.0.1:$${ui_port}"; \
echo "Wrote docker-compose.override.yml (gitignored)"; \
$(COMPOSE) up -d --build --wait; \
echo "up-local ok"
down-local: ## Stop stack and remove gitignored local port override
@$(COMPOSE) down
@rm -f docker-compose.override.yml
@if [ -f .env ]; then \
if grep -q '^OVIRT_ENGINE_PORT=' .env; then \
sed -i.bak -e 's/^OVIRT_ENGINE_PORT=.*/OVIRT_ENGINE_PORT=443/' \
-e 's/^OVIRT_UI_PORT=.*/OVIRT_UI_PORT=5000/' .env && rm -f .env.bak; \
fi; \
fi
@echo "down-local ok (removed docker-compose.override.yml)"
down: ## Stop local services
$(COMPOSE) down
restart: ## Rebuild and restart the stack
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --build --force-recreate --wait
logs: ## Follow logs
$(COMPOSE) logs -f
seed: ## Seed minimal lab
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile minimal
seed-small: ## Seed small cluster (3 hosts · 50 VMs)
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile small
seed-large: ## Seed large cluster (10 hosts · 1000 VMs)
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile large
seed-big: ## Seed big cluster (30 hosts · 2000 VMs)
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile big
seed-demo: seed-large ## Alias: large cluster (legacy name)
audit-seed-dump: ## Contract dump audit (collections+entities) vs live Engine
@set -a; [ -f .env ] && . ./.env; set +a; \
python3 tools/audit_seed_dump.py \
"https://127.0.0.1:$${OVIRT_ENGINE_PORT:-443}" \
"$${OVIRT_SERIES:-4.5}"
smoke: ## Quick Engine auth + list VMs smoke
@set -a; [ -f .env ] && . ./.env; set +a; \
curl -skf -u 'admin@internal:secret' -H 'Accept: application/json' -H 'Version: 4' \
"https://127.0.0.1:$${OVIRT_ENGINE_PORT:-443}/ovirt-engine/api/vms" >/dev/null
@echo "smoke ok"
helm-template: ## Render Helm chart
helm template ovirt-sim $(HELM_CHART)
clean: ## Remove caches
rm -rf .pytest_cache .mypy_cache .ruff_cache .coverage coverage.xml
find . -type d -name __pycache__ -prune -exec rm -rf {} +
ci: format lint test-unit ## Local CI gate
shell: ## Dev shell in container
$(COMPOSE) run --rm $(SERVICE_DEV) bash
release-build: ## Build the runtime image tagged for Docker Hub (no push)
@test -n "$(VERSION)" || (echo "VERSION is empty; set VERSION=... or version in pyproject.toml" >&2; exit 1)
@echo "Building $(DOCKER_IMAGE):$(VERSION) (target=runtime)"
docker build \
--target runtime \
--build-arg APP_VERSION=$(VERSION) \
-t $(DOCKER_IMAGE):$(VERSION) \
$(if $(filter 1 true yes,$(PUSH_LATEST)),-t $(DOCKER_IMAGE):latest,) \
.
release: release-build ## Build and push the runtime image to Docker Hub
@echo "Pushing $(DOCKER_IMAGE):$(VERSION)"
@docker push $(DOCKER_IMAGE):$(VERSION)
@if [ "$(PUSH_LATEST)" = "1" ] || [ "$(PUSH_LATEST)" = "true" ] || [ "$(PUSH_LATEST)" = "yes" ]; then \
echo "Pushing $(DOCKER_IMAGE):latest"; \
docker push $(DOCKER_IMAGE):latest; \
fi
@echo "Released $(DOCKER_IMAGE):$(VERSION)$(if $(filter 1 true yes,$(PUSH_LATEST)), and $(DOCKER_IMAGE):latest,)"
release-up: ## Pull and start the published Hub stack (docker-compose.release.yml)
IMAGE_TAG="$${IMAGE_TAG:-$(VERSION)}" DOCKER_IMAGE="$(DOCKER_IMAGE)" $(COMPOSE_RELEASE) pull
IMAGE_TAG="$${IMAGE_TAG:-$(VERSION)}" DOCKER_IMAGE="$(DOCKER_IMAGE)" $(COMPOSE_RELEASE) up -d --wait
release-down: ## Stop the published Hub stack
$(COMPOSE_RELEASE) down
release-seed: ## Seed the published Hub stack (PROFILE=minimal by default)
SEED_PROFILE="$${PROFILE:-minimal}" IMAGE_TAG="$${IMAGE_TAG:-$(VERSION)}" DOCKER_IMAGE="$(DOCKER_IMAGE)" \
$(COMPOSE_RELEASE) run --rm --entrypoint python simulator -m app.ovirt.seed_cli --profile "$${PROFILE:-minimal}"
# --- Pulumi contract-coverage lab (pulumi-tests) ---
test-pulumi-smoke: ## Pulumi contract-coverage smoke
$(MAKE) -C $(LAB) test-pulumi-smoke
test-pulumi: ## Pulumi full contract coverage (all series × all ops)
$(MAKE) -C $(LAB) test-pulumi
pulumi-tests: test-pulumi ## Alias: full Pulumi contract coverage suite
test-smoke-all: ## Client lab smoke
$(MAKE) -C $(LAB) test-smoke-all
test-all: ## Client lab full suite (Pulumi contract coverage)
$(MAKE) -C $(LAB) test-all
clean-test-resources: ## Cleanup lab-created resources
$(MAKE) -C $(LAB) clean-test-resources
# --- Git: stage, commit (prompt), push to both remotes ---
# Multi-line commit: paste message, then Ctrl-D (same UX as proxmox-api-simulator).
# Optional: make push MSG='one-line message'
push: ## git add . → multi-line commit (Ctrl-D) → push origin + antropoff
@set -e; \
git add .; \
echo "=== staged ==="; \
git status --short; \
echo; \
if git diff --cached --quiet; then \
echo "Nothing to commit — pushing current branch."; \
else \
if [ -n "$(MSG)" ]; then \
msg="$(MSG)"; \
else \
echo "Enter commit message, then Ctrl-D:"; \
msg=$$(cat </dev/tty); \
fi; \
if [ -z "$$msg" ]; then \
echo "Empty commit message, aborting." >&2; \
exit 1; \
fi; \
git commit -m "$$msg"; \
fi; \
echo "Pushing to remotes: $(GIT_REMOTES)"; \
for remote in $(GIT_REMOTES); do \
echo "$$remote ($$(git remote get-url --push "$$remote"))"; \
git push -u "$$remote" HEAD; \
done