Initial commit: VMware vSphere API simulator scaffold.

Add the FastAPI app, PostgreSQL migrations, Docker/Helm packaging, API
contracts, docs, client examples, and the unit/integration/compatibility
test suite for local client and tooling labs without a real vCenter.
This commit is contained in:
2026-07-18 04:42:11 +03:00
commit f8d3cbdd59
422 changed files with 361335 additions and 0 deletions
+228
View File
@@ -0,0 +1,228 @@
**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 69, request/response editing, and runtime contract hot-swap. More
detail: [Web UI](docs/web-ui.md).
![Web UI light theme](docs/images/web-ui-light.png)
![Web UI dark theme](docs/images/web-ui-dark.png)
## 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 69 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`.
## 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:<pyproject version> + :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).