Files
vmware-api-simulator/Makefile
T
inecs 229a705987 Add SemVer VERSION, Jenkins CI/CD, and release 0.1.1.
Ship Harbor/Hub push with latest+version tags, deploy to vmware.devops.org.ru, and show the package version badge in Help → About.
2026-07-28 00:57:11 +03:00

338 lines
14 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 and not pve_stub"
# Docker Hub release image (runtime target only — not the local bind-mount "dev" image).
DOCKERHUB_USER ?= inecs
IMAGE_NAME ?= vmware-api-simulator
VERSION ?= $(shell cat VERSION 2>/dev/null || echo 0.1.0)
DOCKER_IMAGE ?= $(DOCKERHUB_USER)/$(IMAGE_NAME)
PUSH_LATEST ?= 1
COMPOSE_RELEASE ?= $(COMPOSE) -f docker-compose.release.yml
HELM_CHART ?= ./helm/vmware-api-simulator
# Preferred host ports for `make up-local` (gitignored docker-compose.override.yml).
# Override on the CLI if needed: make up-local LOCAL_HTTPS_PORT=9443
COMPOSE_OVERRIDE ?= docker-compose.override.yml
LOCAL_HTTP_PORT ?= 18080
LOCAL_HTTPS_PORT ?= 18443
LOCAL_POSTGRES_PORT ?= 15434
.PHONY: bump-patch bump-minor version-commit help install format lint typecheck test test-unit test-integration test-contract test-compatibility test-surface evidence coverage run dev up up-local down down-local restart logs docker-build docker-up docker-down docker-logs docker-restart db-up db-down db-migrate db-reset api-import api-diff seed clean ci ci-all shell push release release-build release-up release-down release-seed helm-deps helm-template \
pulumi-tests pulumi-tests-smoke test-pulumi-smoke test-pulumi test-smoke-all test-all clean-test-resources vsphere-universe vsphere-param-index vsphere-bundles vsphere-seed-dump
help: ## Show available commands
@awk 'BEGIN {FS = ":.*## "}; /^[a-zA-Z0-9_-]+:.*## / {printf "%-22s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
@echo
@echo "Version: $$(cat VERSION 2>/dev/null || echo 0.1.0) (make bump-patch | bump-minor)"
install: ## Build runtime and development images
@test -f .env || cp .env.example .env
$(COMPOSE) build simulator $(SERVICE_DEV)
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 .
typecheck: ## Run strict mypy checks
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) mypy
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
test-integration: ## Run tests that require PostgreSQL
@test -f .env || cp .env.example .env
$(COMPOSE) up -d postgres
$(COMPOSE) run --rm $(SERVICE_DEV) pytest -m integration
test-contract: ## Run offline API contract tests
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest -m contract
test-compatibility: ## Run client smoke flow against the Compose stack
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --build --wait
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.simulation.seed_cli
$(COMPOSE) run --rm $(SERVICE_DEV) pytest -m compatibility
test-surface: ## Probe every declared method on majors 6-9 (0x501 / 0xexception)
@test -f .env || cp .env.example .env
$(COMPOSE) up -d postgres
$(COMPOSE) run --rm $(SERVICE_DEV) pytest tests/compatibility/test_api_surface_probe.py -q
vsphere-surface: ## Probe native vSphere REST coverage registry against running gateway
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --wait
# From the tools container, hit the simulator service (not host-mapped :443).
$(COMPOSE) run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 $(SERVICE_DEV) \
python scripts/vsphere_surface_probe.py
vsphere-matrix: ## Full REST matrix: all verbs × majors 69 (no 5xx)
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --wait
$(COMPOSE) run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 $(SERVICE_DEV) \
python scripts/vsphere_full_matrix_probe.py
vsphere-seed-dump: ## 100% seed↔live inventory dump audit (PROFILE=small|large|big)
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --wait
SEED_VSPHERE_PROFILE="$${VSPHERE_PROFILE:-$${PROFILE:-large}}" \
SEED_VSPHERE_LARGE_VMS="$${VSPHERE_VMS:-1000}" \
SEED_VSPHERE_LARGE_HOSTS="$${VSPHERE_HOSTS:-10}" \
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.simulation.seed_cli
$(COMPOSE) --profile tools run --rm --no-deps \
-e VSPHERE_BASE=http://simulator:8080 \
-e SEED_VSPHERE_PROFILE="$${VSPHERE_PROFILE:-$${PROFILE:-large}}" \
-e SEED_VSPHERE_LARGE_VMS="$${VSPHERE_VMS:-1000}" \
-e SEED_VSPHERE_LARGE_HOSTS="$${VSPHERE_HOSTS:-10}" \
$(SERVICE_DEV) python scripts/vsphere_seed_dump_audit.py \
--profile "$${VSPHERE_PROFILE:-$${PROFILE:-large}}"
vsphere-universe: ## Regenerate Broadcom Automation API universe.json from operations index
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) python scripts/generate_vsphere_universe.py
vsphere-param-index: ## Build console param index from official Automation OpenAPI
python3 scripts/generate_vsphere_param_index.py
vsphere-bundles: ## Regenerate stub OpenAPI matrices + evidence ledgers
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) python scripts/write_vsphere_bundles.py
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) python scripts/write_vsphere_evidence.py
test-vsphere: ## Native vSphere unit + integration + surface + majors matrix
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --wait
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest \
tests/unit/test_vsphere_profiles.py \
tests/unit/test_vsphere_catalog.py \
tests/unit/test_vsphere_matrix.py \
tests/unit/test_vsphere_compatibility.py \
tests/unit/test_vsphere_universe.py \
tests/unit/test_vsphere_mappers.py \
tests/unit/test_property_collector.py \
tests/unit/test_web_assets.py \
tests/unit/test_web_console.py \
tests/integration/test_vsphere_api.py \
tests/integration/test_vsphere_api_surface_data.py \
tests/integration/test_vsphere_soap_depth.py \
tests/integration/test_vsphere_soap_create_vm.py \
tests/integration/test_vsphere_deep_realism.py \
tests/integration/test_vsphere_full_api.py -q
$(COMPOSE) run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 $(SERVICE_DEV) \
python scripts/vsphere_surface_probe.py
$(COMPOSE) run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 $(SERVICE_DEV) \
python scripts/vsphere_full_matrix_probe.py
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.simulation.seed_cli
$(COMPOSE) --profile tools run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 \
-e SEED_VSPHERE_PROFILE="$${VSPHERE_PROFILE:-$${PROFILE:-large}}" \
$(SERVICE_DEV) python scripts/vsphere_seed_dump_audit.py \
--profile "$${VSPHERE_PROFILE:-$${PROFILE:-large}}"
$(COMPOSE) run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 $(SERVICE_DEV) \
python scripts/vsphere_real_data_spotcheck.py
$(COMPOSE) run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 $(SERVICE_DEV) \
python scripts/vsphere_nonempty_probe.py
$(COMPOSE) run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 $(SERVICE_DEV) \
python scripts/run_client_cookbooks.py
client-cookbooks: ## Python/Ansible/Terraform/Pulumi-style cookbooks against gateway or simulator
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --wait
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.simulation.seed_cli
$(COMPOSE) run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 $(SERVICE_DEV) \
python scripts/run_client_cookbooks.py
# Hybrid pulumi-tests suite (pulumi-vsphere + REST matrix + CRUD + SOAP)
pulumi-tests: ## Run full hybrid suite (provider + REST×6-9 + CRUD + SOAP)
@$(MAKE) -C pulumi-tests test-pulumi
pulumi-tests-smoke: ## PU-INV + one-major REST smoke (no VM/tags/CRUD/SOAP)
@$(MAKE) -C pulumi-tests test-pulumi-smoke
test-pulumi-smoke test-pulumi test-smoke-all test-all clean-test-resources: ## Aliases → pulumi-tests/
@$(MAKE) -C pulumi-tests $@
evidence: ## Regenerate per-major verified surface evidence ledgers
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) python -m app.evidence_gen
coverage: ## Run offline tests with coverage enforcement
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest $(PYTEST_OFFLINE) --cov=app --cov-report=term-missing --cov-report=xml
run: ## Run the application in the foreground
@test -f .env || cp .env.example .env
$(COMPOSE) up --build
up: ## Start PostgreSQL, simulator, and TLS gateway
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --build --wait
up-local: ## Start on free local ports via gitignored compose override
@COMPOSE="$(COMPOSE)" COMPOSE_OVERRIDE="$(COMPOSE_OVERRIDE)" \
LOCAL_HTTP_PORT="$(LOCAL_HTTP_PORT)" \
LOCAL_HTTPS_PORT="$(LOCAL_HTTPS_PORT)" \
LOCAL_POSTGRES_PORT="$(LOCAL_POSTGRES_PORT)" \
bash scripts/up_local.sh
down: ## Stop local services
$(COMPOSE) down
down-local: ## Stop local stack and remove gitignored compose override
$(COMPOSE) down
@rm -f $(COMPOSE_OVERRIDE)
@echo "Stopped local stack and removed $(COMPOSE_OVERRIDE)"
restart: ## Rebuild and restart the stack
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --build --force-recreate --wait
logs: ## Follow logs from all services
$(COMPOSE) logs -f
dev: ## Run the application with auto-reload in Docker
@test -f .env || cp .env.example .env
$(COMPOSE) up -d postgres migrate
$(COMPOSE) up simulator
docker-build: ## Build runtime and development images
$(MAKE) install
docker-up: up ## Alias for up
docker-restart: ## Rebuild and recreate simulator and TLS gateway only
$(COMPOSE) up -d --build --force-recreate simulator api-gateway
docker-down: down ## Alias for down
docker-logs: ## Follow simulator logs only
$(COMPOSE) logs -f simulator
db-up: ## Start PostgreSQL only
@test -f .env || cp .env.example .env
$(COMPOSE) up -d postgres
db-down: ## Stop PostgreSQL
$(COMPOSE) stop postgres
db-migrate: ## Apply database migrations
@test -f .env || cp .env.example .env
$(COMPOSE) run --rm migrate
db-reset: ## Recreate the local database volume
$(COMPOSE) down -v
$(COMPOSE) up -d postgres
$(COMPOSE) run --rm migrate
api-import: ## Import an API snapshot
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) vmware-api-contract import $(ARGS)
api-diff: ## Compare API snapshots
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) vmware-api-contract diff $(ARGS)
seed: ## Seed simulation data (vSphere; PROFILE= / VSPHERE_PROFILE=small|large|big)
@test -f .env || cp .env.example .env
SEED_PROFILE="$${PROFILE:-small}" \
SEED_VSPHERE_PROFILE="$${VSPHERE_PROFILE:-$${PROFILE:-large}}" \
SEED_VSPHERE_LARGE_VMS="$${VSPHERE_VMS:-1000}" \
SEED_VSPHERE_LARGE_HOSTS="$${VSPHERE_HOSTS:-10}" \
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.simulation.seed_cli
shell: ## Open an interactive shell in the development container
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) bash
bump-patch: ## VERSION +0.0.1 (pyproject + Helm)
@PYTHONPATH=. python3 scripts/bump_version.py patch
@echo "VERSION → $$(cat VERSION)"
bump-minor: ## VERSION +0.1.0 (pyproject + Helm)
@PYTHONPATH=. python3 scripts/bump_version.py minor
@echo "VERSION → $$(cat VERSION)"
version-commit: ## Stage version files and commit "Bump version to …"
@git add VERSION pyproject.toml helm/vmware-api-simulator/Chart.yaml helm/vmware-api-simulator/values.yaml
@if git diff --cached --quiet; then \
echo "Nothing to commit for version files."; \
else \
git commit -m "Bump version to $$(cat VERSION)."; \
fi
push: ## bump-patch + commit version + push origin
@$(MAKE) bump-patch
@$(MAKE) version-commit
@set -e; \
git add .; \
echo "=== staged ==="; \
git status --short; \
echo; \
if git diff --cached --quiet; then \
echo "Nothing else to commit — pushing current branch."; \
else \
echo "Enter commit message for remaining changes, then Ctrl-D:"; \
msg=$$(cat </dev/tty); \
if [ -z "$$msg" ]; then echo "Empty commit message, aborting." >&2; exit 1; fi; \
git commit -m "$$msg"; \
fi; \
echo "Pushing to both remotes:"; \
git remote get-url --push --all origin | sed 's/^/ - /'; \
git push origin HEAD
clean: ## Remove generated local artifacts
rm -rf .coverage coverage.xml htmlcov .mypy_cache .pytest_cache .ruff_cache
rm -f $(COMPOSE_OVERRIDE)
ci: ## Offline quality gate + full API surface probe (Postgres)
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) sh -c '\
ruff format --check . && \
ruff check . && \
mypy && \
pytest $(PYTEST_OFFLINE) --cov=app --cov-report=term-missing --cov-report=xml'
$(MAKE) test-surface
ci-all: ## Full CI: offline + surface + remaining integration + client compatibility
$(MAKE) ci
$(MAKE) test-integration
$(MAKE) test-compatibility
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=small by default)
SEED_PROFILE="$${PROFILE:-small}" \
SEED_VSPHERE_PROFILE="$${VSPHERE_PROFILE:-$${PROFILE:-small}}" \
IMAGE_TAG="$${IMAGE_TAG:-$(VERSION)}" DOCKER_IMAGE="$(DOCKER_IMAGE)" \
$(COMPOSE_RELEASE) run --rm --entrypoint python simulator -m app.simulation.seed_cli
helm-deps: ## No-op placeholder (chart has no OCI dependencies)
@echo "Chart $(HELM_CHART) vendors PostgreSQL templates; no helm dependency update required."
helm-template: ## Render Helm manifests locally (requires helm)
helm template vmware-sim $(HELM_CHART) \
-f $(HELM_CHART)/values-ingress-example.yaml \
--set certManager.email=docs@example.com \
--set secret.ticketSigningKey=docs-only-signing-key