mirror of
https://github.com/dtzp555-max/aci-sim.git
synced 2026-07-19 09:46:33 +00:00
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>
75 lines
2.1 KiB
Python
75 lines
2.1 KiB
Python
"""Tests for the /_sim control-plane admin endpoints (Phase 5)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import copy
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
from aci_sim.build.orchestrator import build_site
|
|
from aci_sim.rest_aci.app import ApicSiteState, make_apic_app
|
|
from aci_sim.topology.loader import load_topology
|
|
|
|
TOPO_PATH = "topology.yaml"
|
|
|
|
|
|
@pytest.fixture
|
|
def client_and_state():
|
|
topo = load_topology(TOPO_PATH)
|
|
site = topo.sites[0]
|
|
store = build_site(topo, site)
|
|
state = ApicSiteState(
|
|
name=site.name,
|
|
site=site,
|
|
topo=topo,
|
|
store=store,
|
|
baseline=copy.deepcopy(store),
|
|
)
|
|
app = make_apic_app(state)
|
|
c = TestClient(app)
|
|
c.post(
|
|
"/api/aaaLogin.json",
|
|
json={"aaaUser": {"attributes": {"name": "admin", "pwd": "cisco"}}},
|
|
)
|
|
return c, state
|
|
|
|
|
|
def test_reset_removes_posted_tenant(client_and_state):
|
|
client, state = client_and_state
|
|
# POST a new tenant
|
|
client.post(
|
|
"/api/mo/uni/tn-TEMP.json",
|
|
json={"fvTenant": {"attributes": {"name": "TEMP", "dn": "uni/tn-TEMP"}}},
|
|
)
|
|
# Verify it's there
|
|
resp = client.get("/api/class/fvTenant.json")
|
|
names = [i["fvTenant"]["attributes"]["name"] for i in resp.json()["imdata"]]
|
|
assert "TEMP" in names
|
|
# Reset
|
|
r = client.post("/_sim/reset")
|
|
assert r.status_code == 200
|
|
# Verify it's gone
|
|
resp2 = client.get("/api/class/fvTenant.json")
|
|
names2 = [i["fvTenant"]["attributes"]["name"] for i in resp2.json()["imdata"]]
|
|
assert "TEMP" not in names2
|
|
|
|
|
|
def test_snapshot_restore(client_and_state):
|
|
client, state = client_and_state
|
|
# POST a tenant
|
|
client.post(
|
|
"/api/mo/uni/tn-SNAP.json",
|
|
json={"fvTenant": {"attributes": {"name": "SNAP", "dn": "uni/tn-SNAP"}}},
|
|
)
|
|
# Snapshot
|
|
client.post("/_sim/snapshot/s1")
|
|
# Reset to baseline (removes SNAP)
|
|
client.post("/_sim/reset")
|
|
# Restore
|
|
client.post("/_sim/restore/s1")
|
|
# Verify SNAP is back
|
|
resp = client.get("/api/class/fvTenant.json")
|
|
names = [i["fvTenant"]["attributes"]["name"] for i in resp.json()["imdata"]]
|
|
assert "SNAP" in names
|