**Language / Язык:** [English](README.md) | [Русский](README.ru.md) # vmware-api-simulator Stateful asynchronous [VMware vSphere](https://www.vmware.com/products/vsphere.html) API simulator for testing API clients and infrastructure tooling without a real ESXi/vCenter cluster. The simulator is backed by PostgreSQL and exposes native vCenter surfaces: **REST** Automation API (`/api`, legacy `/rest`) and **SOAP** VIM/PBM (`/sdk`). Semantic handlers persist inventory, sessions, tasks, tags, content libraries, and permissions; power/clone/relocate/snapshot operations run as durable CIS tasks with real task ids. ## Verified API coverage Coverage is tracked against the public [vSphere Automation API operations index](https://developer.broadcom.com/xapis/vsphere-automation-api/latest/operation-index/) (~1037 unique verb+path routes in the simulator registry). **Two layers (read this before the table):** | Layer | Share (major 9) | Meaning | |---|---:|---| | Core deep handlers | ~104 routes (~10%) | Inventory, VM lifecycle, tasks, tagging, content library, appliance, authz — real PostgreSQL semantics | | DB-backed stub surface | remaining registry (~90%) | Seeded non-empty JSON for the rest of the Broadcom route table (lab stand-ins, not production parity) | | Catalog major | vSphere label | Catalog floor / universe | Floor coverage | |---|---|---:|---:| | 6 | 7.0 | 31 / 1077 | 2.9% | | 7 | 7.0 U3 | 77 / 1077 | 7.2% | | 8 | 8.0 | 103 / 1077 | 9.6% | | 9 | 8.0 U2 (Automation 9.1 surface) | **1077 / 1077** | **100% route registry** | At major 9 the **full route registry** is served (no known path 501s): deep handlers plus stubs. Hot-swap (`POST /ui/api/contract/apply?major=N`) only changes the **catalog** major used by the Web UI / evidence reports. See [Compatibility](docs/compatibility.md), [compatibility 0.1.0](docs/compatibility-0.1.0.md), and [API coverage](docs/api-coverage.md). > This is measurable route-registry and handler coverage for a laboratory > simulator — not a claim that every vSphere edge case or ESXi-hardware > behavior is reproduced identically to production vCenter. ## Quick start (published image) Image: [`inecs/vmware-api-simulator`](https://hub.docker.com/r/inecs/vmware-api-simulator) Requires a git checkout of this repository (Compose mounts `docker/gateway/` and `docker/tls/` next to the compose file). ### Docker Compose ```bash docker compose -f docker-compose.release.yml up -d --wait # seed runs automatically; re-run manually if you wiped the DB: # docker compose -f docker-compose.release.yml run --rm --entrypoint python \ # simulator -m app.simulation.seed_cli curl -sk https://localhost/health/ready SID=$(curl -sk -u 'administrator@vsphere.local:VMware1!' -X POST \ https://localhost/api/session | tr -d '"') curl -sk -H "vmware-api-session-id: $SID" https://localhost/api/vcenter/vm ``` Or: `make release-up` (seed is part of the release stack) ### Helm (Kubernetes + Ingress + Let's Encrypt) ```bash helm upgrade --install vmware-sim ./helm/vmware-api-simulator \ -n vmware-sim --create-namespace \ -f ./helm/vmware-api-simulator/values-ingress-example.yaml \ --set certManager.email=you@example.com \ --set ingress.hosts[0].host=vmware-sim.example.com \ --set ingress.tls[0].hosts[0]=vmware-sim.example.com \ --set secret.ticketSigningKey="$(openssl rand -hex 32)" ``` Requires an Ingress controller and cert-manager. Details: [Kubernetes / Helm](docs/kubernetes.md). - Lab UI + REST (Compose gateway): [https://localhost/](https://localhost/) - FastAPI schema docs: [https://localhost/docs](https://localhost/docs) - Default seeded admin: `administrator@vsphere.local` / `VMware1!` ## Quick start (development checkout) Build and run the bind-mounted development stack from this repository: ```bash make install make up make seed PROFILE=small curl -sk https://localhost/health/ready curl -sk https://localhost/api/appliance/system/version ``` - HTTPS gateway (primary vCenter entry): `https://localhost` - HTTP lab face: `http://localhost` - PostgreSQL (localhost only): `5434` - Internal FastAPI process (not published to the host): `8080` - The checked-in `docker/tls/server.key` is a **lab-only** localhost cert; do not reuse it outside local Compose. - FastAPI schema docs: [https://localhost/docs](https://localhost/docs) ### Web UI Interactive console with light/dark themes, endpoint catalog for vSphere majors 6–9, request/response editing, and runtime contract hot-swap. ![Web UI main console](docs/images/web-ui-main.png) Full walkthrough and more screenshots: [Web UI](docs/web-ui.md). ## Credentials (seed) Password `VMware1!` for all seeded principals: | User | Role | |---|---| | `administrator@vsphere.local` | Administrator | | `readonly@vsphere.local` | ReadOnly | | `operator@vsphere.local` | VirtualMachinePowerUser | | `vmadmin@vsphere.local` | VirtualMachineAdministrator | ## Documentation Documentation is bilingual. Use the **Language / Язык** switcher at the top of each page, or open the Russian root [README.ru.md](README.ru.md). Index: [docs/README.md](docs/README.md) · [docs/ru/README.md](docs/ru/README.md). | Guide | Description | |---|---| | [Getting started](docs/getting-started.md) | First successful lab session | | [Configuration](docs/configuration.md) | Environment variables and Compose | | [Authentication](docs/authentication.md) | Sessions, `vmware-api-session-id`, privileges | | [API versions](docs/api-versions.md) | Catalog majors 6–9 and hot-swap | | [API surface](docs/api-surface.md) | REST/SOAP routing, coverage registry, stubs | | [API coverage](docs/api-coverage.md) | Broadcom universe vs implemented surface | | [Clients & examples](docs/clients.md) | Python, Go, Java, Perl, Ansible, Terraform, Pulumi | | [Seed profiles](docs/seed-profiles.md) | Deterministic inventory fixtures | | [Domains](docs/domains/README.md) | Session, inventory, VM, storage, networking, tagging, SOAP, tasks, … | | [Web UI](docs/web-ui.md) | Interactive console and catalogs | | [Operations](docs/operations.md) | Reseed, migrate, release, upgrade | | [Kubernetes / Helm](docs/kubernetes.md) | Hub image + Ingress + Let's Encrypt | | [Security](docs/security.md) | Lab threat model and credentials | | [Observability](docs/observability.md) | Health endpoints and logging | | [Ports](docs/ports.md) | Published host ports and internal services | | [Troubleshooting](docs/troubleshooting.md) | Common failure modes | | [FAQ](docs/faq.md) | Short answers | | [Architecture](docs/architecture.md) | Component boundaries | | [Compatibility](docs/compatibility.md) | Evidence model and release matrix | Runnable cookbooks live under [`examples/`](examples/README.md). The [`pulumi-vsphere`](https://www.pulumi.com/registry/packages/vsphere/) lab suite (nonempty output checks, HTML report) lives under [`pulumi-tests/`](pulumi-tests/README.md) — run with `make pulumi-tests`. Latest lab run (**2026-07-18**): offline **161 passed**; `test-vsphere` probes green; full `pulumi-tests` **7/7** with REST matrix **1987/1987** (`critical=0`). See [pulumi-tests/README.md](pulumi-tests/README.md#latest-lab-run-2026-07-18). ## Python (requests) against the HTTPS gateway ```python import requests requests.packages.urllib3.disable_warnings() session = requests.post( "https://localhost/api/session", auth=("administrator@vsphere.local", "VMware1!"), verify=False, # local self-signed development certificate only ) headers = {"vmware-api-session-id": session.json()} vms = requests.get("https://localhost/api/vcenter/vm", headers=headers, verify=False) print(vms.json()) ``` SOAP / VIM clients (pyvmomi, govmomi, `hashicorp/vsphere` Terraform provider, Pulumi) point at `https://localhost/sdk` with the same credentials. ## Common Make targets ```bash make up / make down / make logs / make dev make seed # large vSphere seed (10 hosts / 1000 VMs) VSPHERE_PROFILE=small make seed # compact inventory (3 hosts / 5 VMs) make test # unit + contract (offline) make test-vsphere # native vSphere unit + integration + surface + matrix make vsphere-surface # probe REST coverage registry against the running gateway make vsphere-matrix # full REST matrix: all verbs × majors 6-9 (no 5xx) make evidence # regenerate evidence/vsphere-*.json ledgers make db-migrate make shell make ci # ruff + mypy + offline pytest + surface probe make release # build + push runtime image to Docker Hub make release-up # pull/start docker-compose.release.yml make release-seed PROFILE=small ``` Docker Hub release (requires `docker login` as the Hub owner; see [Operations](docs/operations.md)): ```bash make release # inecs/vmware-api-simulator: + :latest make release VERSION=0.2.0 # override tag make release-build # build/tag only, no push make release-up && make release-seed # run the published stack locally ``` ## What this is not - Not a hypervisor: no ESXi/KVM execution on bare metal or nested hosts. - Not a drop-in multi-tenant production vCenter replacement. - No Supervisor/Tanzu control plane, no NSX Manager, no deep vSAN, no SAML/OIDC federation, no VECS certificate store — lab-shaped stand-ins exist for some of these (seeded, non-binary-compatible data). HttpNfcLease / content-library transfer **handshakes** are implemented on `/nfc` and related REST/SOAP paths, but not production-binary-compatible NFC uploads; see [docs/api-coverage.md](docs/api-coverage.md). - Remote IdP / LDAP / live NSX / live ACME directories are simulated locally; they do not call real external systems. - An optional legacy Proxmox VE stub plane exists behind `ENABLE_PVE_STUB` (**off** by default) from a shared platform lineage; it is not the primary surface of this project. ## License Apache-2.0 — see [LICENSE](LICENSE). Web UI console guide: [docs/web-ui.md](docs/web-ui.md).