Files
aci-sim/aci_sim/build/userprofile.py
T
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

43 lines
1.6 KiB
Python

"""build/userprofile.py — aaaUserEp login-probe MO (uni/userprofile-<user>).
CONTRACT.md §1: during/after login autoACI probes
GET /api/mo/uni/userprofile-<user>.json?query-target=subtree&target-subtree-class=aaaUserDomain
This must not 404 and must return >=1 aaaUserDomain row.
Real APIC exposes a per-user aaaUserEp at uni/userprofile-<user> with an
aaaUserDomain child (name="all" is the default/full-access domain every local
user gets). The simulator only ever authenticates as "admin" (see
rest_aci/auth.py, which defaults aaaLogin's username to "admin"), so the
simplest faithful variant is a single static admin profile rather than
dynamically creating one per logged-in user — this is the same set of MOs a
real APIC would already have provisioned for the built-in admin account, no
matter who authenticates.
Site-independent: call once per topology (site arg accepted for API
uniformity but not used in the selection logic), same convention as
build/access.py.
"""
from __future__ import annotations
from aci_sim.mit.mo import MO
from aci_sim.mit.store import MITStore
from aci_sim.topology.schema import Site, Topology
_ADMIN_USER = "admin"
def build(topo: Topology, site: Site, store: MITStore) -> None:
"""Emit uni/userprofile-admin (aaaUserEp) + its aaaUserDomain child."""
profile_dn = f"uni/userprofile-{_ADMIN_USER}"
profile_mo = MO(
"aaaUserEp",
dn=profile_dn,
name=_ADMIN_USER,
)
profile_mo.add_child(MO(
"aaaUserDomain",
dn=f"{profile_dn}/userdomain-all",
name="all",
))
store.add(profile_mo)