Files
taodengandClaude Fable 5 7e9a175ce6 Initial public release — aci-sim v0.16.0
aci-sim is a stateful REST simulator of a 2-site Cisco ACI fabric
(per-site APIC + ND/NDO management planes) — for testing ACI automation
(Ansible cisco.aci / cisco.mso, aci-py, custom REST clients) and CI gates
without real hardware.

Highlights: APIC + NDO REST surface served from one in-memory MIT built
from a declarative topology.yaml; port mode + sandbox (real per-device IPs
on :443) run modes; LLDP/CDP neighbor visibility; NDO->APIC deploy mirror
(multi-site templates materialize onto the target sites' APIC stores);
real-APIC fvBD default attributes; file-backed state save/restore; an
`aci-sim` CLI (validate/show/graph/run/new/init/lldp); and an 888-test suite.

History squashed for the public release.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 20:06:36 +10:00

53 lines
2.0 KiB
Markdown

# CI gate example — fail a PR before it reaches real hardware
Pattern: run your network automation (Ansible / Terraform / Python / aci-py)
against a running `aci-sim`, then **assert the MIT reached the expected
end state**. A failed assertion fails the build. No hardware, deterministic,
resettable.
## Files
- **`assert_mit.py`** — the gate. Logs into the sim (or a real APIC) and checks
that the objects your change was supposed to create/modify are present.
Exit code = number of failed checks, so CI can gate on it.
- **`github-actions-aci-gate.yml`** — a copy-pasteable GitHub Actions workflow
wiring the three steps (start sim → run automation → assert).
## `assert_mit.py` check syntax
Each `--expect` (repeatable):
| Check | Meaning |
|---|---|
| `class:<cls>[>=N]` | the class query returns ≥ N objects (default N=1) |
| `mo:<dn>` | `GET /api/mo/<dn>.json` returns the object (exists) |
| `absent:<dn>` | the MO does NOT exist (e.g. after a `state=absent` / delete) |
| `attr:<dn>:<key>=<val>` | the MO at `<dn>` has attribute `<key>` == `<val>` |
## Try it locally
```bash
# 1. start the sim (ships MS-TN1 / SF-TN1-* tenants from topology.yaml)
aci-sim run &
# 2. assert the seeded end state
python examples/ci/assert_mit.py --host 127.0.0.1:8443 \
--expect "class:fvTenant>=1" \
--expect "mo:uni/tn-MS-TN1" \
--expect "attr:uni/tn-MS-TN1:name=MS-TN1" \
--expect "absent:uni/tn-DoesNotExist"
# → 4/4 checks passed, exit 0
```
Because `assert_mit.py` speaks the plain APIC REST API, you can point it at a
**real APIC** too (`--host <apic-ip> --user ... --password ...`) to diff
sim-vs-real, or to validate the same expectations against staging gear.
## Real-world shape
In practice step 2 is your existing playbook (see `../ansible/smoke.yml` for a
full cisco.aci create→idempotency example), and step 3's `--expect` list is the
objects that playbook is contracted to produce. When someone edits the playbook
in a way that stops creating those objects, the PR goes red — before anything
touches production.