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>
This commit is contained in:
2026-07-05 20:06:36 +10:00
co-authored by Claude Fable 5
commit 7e9a175ce6
117 changed files with 31769 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
"""PR-14: classic ND bare /login + /logout endpoints (used by aci-py, cisco.nd)."""
from __future__ import annotations
import copy
from fastapi.testclient import TestClient
from aci_sim.ndo.app import make_ndo_app
from aci_sim.ndo.model import build_ndo_model
from aci_sim.topology.loader import load_topology
def _client():
topo = load_topology("topology.yaml")
state = build_ndo_model(topo, sandbox=False)
return TestClient(make_ndo_app(copy.deepcopy(state)), raise_server_exceptions=False)
def test_bare_login_returns_token_and_jwttoken():
c = _client()
r = c.post("/login", json={"userName": "admin", "userPasswd": "cisco", "domain": "local"})
assert r.status_code == 200
body = r.json()
assert body["token"] and body["token"] == body["jwttoken"]
assert body["userName"] == "admin"
def test_bare_logout_ok():
c = _client()
assert c.post("/logout").status_code == 200
def test_new_auth_login_still_works():
c = _client()
r = c.post("/api/v1/auth/login", json={"userName": "admin", "userPasswd": "cisco"})
assert r.status_code == 200 and r.json()["token"]