a3ce2d473c
Ship Proxmox, oVirt, VMware, and OpenStack behind one Postgres stack, Makefile helpers (up/clean/helm up|down/push), and a Helm chart with namespace, Let's Encrypt ingresses, migrate inits, and skip-if-seeded jobs.
352 lines
10 KiB
YAML
352 lines
10 KiB
YAML
# Self-contained lab stack: Proxmox + oVirt + VMware + OpenStack
|
|
# One PostgreSQL, four databases. No sibling source trees required.
|
|
#
|
|
# cd /Users/inecs/Разработка/simulators
|
|
# docker compose pull
|
|
# docker compose up -d
|
|
#
|
|
# Override tags: IMAGE_TAG=0.1.0 docker compose up -d
|
|
#
|
|
# Laboratory only — default passwords / TICKET_SIGNING_KEY are intentional.
|
|
|
|
name: api-simulators-lab
|
|
|
|
x-ticket: &ticket
|
|
TICKET_SIGNING_KEY: ${TICKET_SIGNING_KEY:-development-only-signing-key-change-me}
|
|
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
|
|
|
networks:
|
|
lab:
|
|
proxmox_net:
|
|
ovirt_net:
|
|
vmware_net:
|
|
openstack_net:
|
|
|
|
volumes:
|
|
postgres-data:
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:17.5-bookworm
|
|
restart: unless-stopped
|
|
networks: [lab, proxmox_net, ovirt_net, vmware_net, openstack_net]
|
|
environment:
|
|
POSTGRES_USER: lab
|
|
POSTGRES_PASSWORD: lab
|
|
POSTGRES_DB: postgres
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U lab -d postgres"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 12
|
|
start_period: 5s
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
- ./docker/postgres-init:/docker-entrypoint-initdb.d:ro
|
|
ports:
|
|
- "127.0.0.1:5432:5432"
|
|
|
|
# ── Proxmox VE API ──────────────────────────────────────
|
|
proxmox-migrate:
|
|
profiles: [init]
|
|
image: inecs/proxmox-api-simulator:${IMAGE_TAG:-latest}
|
|
networks: [proxmox_net]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://proxmox:proxmox@postgres:5432/proxmox_simulator
|
|
CONTRACT_SNAPSHOT: /app/contracts/pve-9.2.3.json
|
|
COMPATIBILITY_EVIDENCE: /app/evidence/pve-9.2.3.json
|
|
depends_on:
|
|
postgres: { condition: service_healthy }
|
|
entrypoint: ["python"]
|
|
command: ["-m", "app.db.migrate_cli"]
|
|
restart: "no"
|
|
|
|
proxmox:
|
|
image: inecs/proxmox-api-simulator:${IMAGE_TAG:-latest}
|
|
restart: unless-stopped
|
|
networks: [proxmox_net]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://proxmox:proxmox@postgres:5432/proxmox_simulator
|
|
CONTRACT_SNAPSHOT: /app/contracts/pve-9.2.3.json
|
|
COMPATIBILITY_EVIDENCE: /app/evidence/pve-9.2.3.json
|
|
TASK_WORKER_CONCURRENCY: "2"
|
|
SIMULATION_TIME_SCALE: "10"
|
|
depends_on:
|
|
postgres: { condition: service_healthy }
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD",
|
|
"python",
|
|
"-c",
|
|
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8006/health/ready', timeout=2)",
|
|
]
|
|
interval: 10s
|
|
timeout: 3s
|
|
retries: 10
|
|
start_period: 25s
|
|
ports:
|
|
- "8006:8006"
|
|
|
|
proxmox-seed:
|
|
profiles: [init]
|
|
image: inecs/proxmox-api-simulator:${IMAGE_TAG:-latest}
|
|
networks: [proxmox_net]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://proxmox:proxmox@postgres:5432/proxmox_simulator
|
|
SEED_PROFILE: ${PROXMOX_SEED_PROFILE:-small}
|
|
depends_on:
|
|
proxmox: { condition: service_healthy }
|
|
entrypoint: ["python"]
|
|
command: ["-m", "app.simulation.seed_cli"]
|
|
restart: "no"
|
|
|
|
# ── oVirt Engine API ────────────────────────────────────
|
|
ovirt-migrate:
|
|
profiles: [init]
|
|
image: inecs/ovirt-api-simulator:${IMAGE_TAG:-latest}
|
|
networks: [ovirt_net]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://ovirt:ovirt@postgres:5432/ovirt_simulator
|
|
OVIRT_SERIES: ${OVIRT_SERIES:-4.5}
|
|
depends_on:
|
|
postgres: { condition: service_healthy }
|
|
entrypoint: ["python"]
|
|
command: ["-m", "app.db.migrate_cli"]
|
|
restart: "no"
|
|
|
|
ovirt:
|
|
image: inecs/ovirt-api-simulator:${IMAGE_TAG:-latest}
|
|
restart: unless-stopped
|
|
networks:
|
|
ovirt_net:
|
|
aliases: [simulator]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://ovirt:ovirt@postgres:5432/ovirt_simulator
|
|
OVIRT_SERIES: ${OVIRT_SERIES:-4.5}
|
|
APP_PORT: "8080"
|
|
depends_on:
|
|
postgres: { condition: service_healthy }
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD",
|
|
"python",
|
|
"-c",
|
|
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health/ready', timeout=2)",
|
|
]
|
|
interval: 10s
|
|
timeout: 3s
|
|
retries: 10
|
|
start_period: 30s
|
|
expose:
|
|
- "8080"
|
|
|
|
ovirt-gateway:
|
|
image: nginx:1.28.0-alpine
|
|
restart: unless-stopped
|
|
networks: [ovirt_net]
|
|
depends_on:
|
|
ovirt: { condition: service_healthy }
|
|
ports:
|
|
- "7443:443"
|
|
- "7500:5000"
|
|
volumes:
|
|
- ./docker/ovirt/ovirt-engine.conf:/etc/nginx/conf.d/default.conf:ro
|
|
- ./docker/tls/server.crt:/etc/nginx/tls/server.crt:ro
|
|
- ./docker/tls/server.key:/etc/nginx/tls/server.key:ro
|
|
read_only: true
|
|
tmpfs: [/var/cache/nginx, /var/run, /tmp]
|
|
security_opt: [no-new-privileges:true]
|
|
|
|
ovirt-seed:
|
|
profiles: [init]
|
|
image: inecs/ovirt-api-simulator:${IMAGE_TAG:-latest}
|
|
networks: [ovirt_net]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://ovirt:ovirt@postgres:5432/ovirt_simulator
|
|
OVIRT_SERIES: ${OVIRT_SERIES:-4.5}
|
|
depends_on:
|
|
ovirt: { condition: service_healthy }
|
|
entrypoint: ["python"]
|
|
command: ["-m", "app.ovirt.seed_cli", "--profile", "${OVIRT_SEED_PROFILE:-minimal}"]
|
|
restart: "no"
|
|
|
|
# ── VMware vSphere API ──────────────────────────────────
|
|
vmware-migrate:
|
|
profiles: [init]
|
|
image: inecs/vmware-api-simulator:${IMAGE_TAG:-latest}
|
|
networks: [vmware_net]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://vmware:vmware@postgres:5432/vmware_simulator
|
|
ENABLE_PVE_STUB: "false"
|
|
APP_PORT: "8080"
|
|
depends_on:
|
|
postgres: { condition: service_healthy }
|
|
entrypoint: ["python"]
|
|
command: ["-m", "app.db.migrate_cli"]
|
|
restart: "no"
|
|
|
|
vmware:
|
|
image: inecs/vmware-api-simulator:${IMAGE_TAG:-latest}
|
|
restart: unless-stopped
|
|
networks:
|
|
vmware_net:
|
|
aliases: [simulator]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://vmware:vmware@postgres:5432/vmware_simulator
|
|
ENABLE_PVE_STUB: "false"
|
|
SEED_VSPHERE_PROFILE: ${VMWARE_SEED_PROFILE:-small}
|
|
APP_PORT: "8080"
|
|
TASK_WORKER_CONCURRENCY: "2"
|
|
SIMULATION_TIME_SCALE: "10"
|
|
depends_on:
|
|
postgres: { condition: service_healthy }
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD",
|
|
"python",
|
|
"-c",
|
|
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health/ready', timeout=2)",
|
|
]
|
|
interval: 10s
|
|
timeout: 3s
|
|
retries: 10
|
|
start_period: 25s
|
|
expose:
|
|
- "8080"
|
|
|
|
vmware-gateway:
|
|
image: nginx:1.28.0-alpine
|
|
restart: unless-stopped
|
|
networks: [vmware_net]
|
|
depends_on:
|
|
vmware: { condition: service_healthy }
|
|
ports:
|
|
- "8081:80"
|
|
- "8443:443"
|
|
volumes:
|
|
- ./docker/vmware/vmware-ports.conf:/etc/nginx/conf.d/default.conf:ro
|
|
- ./docker/tls/server.crt:/etc/nginx/tls/server.crt:ro
|
|
- ./docker/tls/server.key:/etc/nginx/tls/server.key:ro
|
|
read_only: true
|
|
tmpfs: [/var/cache/nginx, /var/run, /tmp]
|
|
security_opt: [no-new-privileges:true]
|
|
|
|
vmware-seed:
|
|
profiles: [init]
|
|
image: inecs/vmware-api-simulator:${IMAGE_TAG:-latest}
|
|
networks: [vmware_net]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://vmware:vmware@postgres:5432/vmware_simulator
|
|
ENABLE_PVE_STUB: "false"
|
|
SEED_PROFILE: ${VMWARE_SEED_PROFILE:-small}
|
|
SEED_VSPHERE_PROFILE: ${VMWARE_SEED_PROFILE:-small}
|
|
depends_on:
|
|
vmware: { condition: service_healthy }
|
|
entrypoint: ["python"]
|
|
command: ["-m", "app.simulation.seed_cli"]
|
|
restart: "no"
|
|
|
|
# ── OpenStack API ───────────────────────────────────────
|
|
openstack-migrate:
|
|
profiles: [init]
|
|
image: inecs/openstack-api-simulator:${IMAGE_TAG:-latest}
|
|
networks: [openstack_net]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://openstack:openstack@postgres:5432/openstack_simulator
|
|
APP_PORT: "8080"
|
|
depends_on:
|
|
postgres: { condition: service_healthy }
|
|
entrypoint: ["python"]
|
|
command: ["-m", "app.db.migrate_cli"]
|
|
restart: "no"
|
|
|
|
openstack:
|
|
image: inecs/openstack-api-simulator:${IMAGE_TAG:-latest}
|
|
restart: unless-stopped
|
|
networks:
|
|
openstack_net:
|
|
aliases: [simulator]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://openstack:openstack@postgres:5432/openstack_simulator
|
|
APP_PORT: "8080"
|
|
TASK_WORKER_CONCURRENCY: "2"
|
|
SIMULATION_TIME_SCALE: "10"
|
|
depends_on:
|
|
postgres: { condition: service_healthy }
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD",
|
|
"python",
|
|
"-c",
|
|
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health/ready', timeout=2)",
|
|
]
|
|
interval: 10s
|
|
timeout: 3s
|
|
retries: 10
|
|
start_period: 25s
|
|
expose:
|
|
- "8080"
|
|
|
|
openstack-gateway:
|
|
image: nginx:1.28.0-alpine
|
|
restart: unless-stopped
|
|
networks: [openstack_net]
|
|
depends_on:
|
|
openstack: { condition: service_healthy }
|
|
ports:
|
|
- "9080:80"
|
|
- "9443:443"
|
|
- "9500:5000"
|
|
- "5050:5050"
|
|
- "6385:6385"
|
|
- "8000:8000"
|
|
- "8003:8003"
|
|
- "8004:8004"
|
|
- "8042:8042"
|
|
- "8080:8080"
|
|
- "8774:8774"
|
|
- "8776:8776"
|
|
- "8779:8779"
|
|
- "8786:8786"
|
|
- "8989:8989"
|
|
- "9001:9001"
|
|
- "9090:9090"
|
|
- "9292:9292"
|
|
- "9696:9696"
|
|
- "9876:9876"
|
|
volumes:
|
|
- ./docker/openstack/openstack-ports.conf:/etc/nginx/conf.d/default.conf:ro
|
|
- ./docker/tls/server.crt:/etc/nginx/tls/server.crt:ro
|
|
- ./docker/tls/server.key:/etc/nginx/tls/server.key:ro
|
|
read_only: true
|
|
tmpfs: [/var/cache/nginx, /var/run, /tmp]
|
|
security_opt: [no-new-privileges:true]
|
|
|
|
openstack-seed:
|
|
profiles: [init]
|
|
image: inecs/openstack-api-simulator:${IMAGE_TAG:-latest}
|
|
networks: [openstack_net]
|
|
environment:
|
|
<<: *ticket
|
|
DATABASE_URL: postgresql://openstack:openstack@postgres:5432/openstack_simulator
|
|
depends_on:
|
|
openstack: { condition: service_healthy }
|
|
entrypoint: ["python"]
|
|
command: ["-m", "app.openstack.seed_cli", "--profile", "${OPENSTACK_SEED_PROFILE:-minimal}"]
|
|
restart: "no"
|