mirror of
https://github.com/dtzp555-max/aci-sim.git
synced 2026-07-21 21:15:12 +00:00
feat: APIC-style write validation, query-target=children, contract shadow mirroring (v0.21.0)
Three fidelity gaps surfaced by one broken TN2 var file (missing firewall block), all fixed: - writes: reject malformed fvSubnet/l3extSubnet/vnsRedirectDest ip values with an APIC-style 400 before any store mutation (deletes exempt) - query engine: support query-target=children (direct children, flat imdata, root excluded) — was silently returning empty - deploy mirror: materialize vzFilter/vzEntry, vzBrCP/vzSubj (+ filter and service-graph subject bindings) and vnsAbsGraph shadows per target site; undeploy removes them E2E-verified through the real pipeline (aci-py hidden push): a TN2 var missing the fw block now fails with 'Invalid value "." for property ip of vnsRedirectDest ... -> 400' and nothing lands; a complete var set builds both MS tenants with contract shadows + sgt-FW graph binding on both sites. Suite: 914 passed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
7fdf31aca9
commit
867c05c9c5
@@ -494,3 +494,62 @@ def test_app_level_undeploy_via_task_body():
|
||||
assert resp.status_code == 200
|
||||
|
||||
assert apic_states["1"].store.get(f"uni/tn-{TENANT_NAME}/ap-AP1/epg-Web") is None
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Contract/filter/service-graph shadow mirroring (2026-07-07 gap: vzBrCP=0
|
||||
# fabric-wide while mirrored EPGs carried fvRsProv/fvRsCons to those names)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _firewall_template(state) -> None:
|
||||
template = state.schema_details[SCHEMA_ID]["templates"][0]
|
||||
template["filters"] = [{
|
||||
"name": "flt-permit_ip_LAB0",
|
||||
"entries": [{"name": "permit_ip", "etherType": "ip", "ipProtocol": "unspecified"}],
|
||||
}]
|
||||
template["serviceGraphs"] = [{"name": "sgt-FW_LAB0"}]
|
||||
template["contracts"] = [{
|
||||
"name": "con-Firewall_LAB0",
|
||||
"scope": "context",
|
||||
"filterRelationships": [
|
||||
{"filterRef": f"/schemas/{SCHEMA_ID}/templates/{TEMPLATE_NAME}/filters/flt-permit_ip_LAB0"}
|
||||
],
|
||||
"serviceGraphRelationship": {
|
||||
"serviceGraphRef": f"/schemas/{SCHEMA_ID}/templates/{TEMPLATE_NAME}/serviceGraphs/sgt-FW_LAB0"
|
||||
},
|
||||
}]
|
||||
|
||||
|
||||
def test_mirror_materializes_contract_shadows() -> None:
|
||||
state = _build_state()
|
||||
_firewall_template(state)
|
||||
apic = _FakeApicState()
|
||||
mirror_template_to_sites(state, TEMPLATE_NAME, {"1": apic}, schema_id=SCHEMA_ID)
|
||||
store = apic.store
|
||||
tn = f"uni/tn-{TENANT_NAME}"
|
||||
con_dn = f"{tn}/brc-con-Firewall_LAB0"
|
||||
subj_dn = f"{con_dn}/subj-sub-Firewall_LAB0"
|
||||
assert store.get(con_dn) is not None
|
||||
assert store.get(con_dn).attrs["scope"] == "context"
|
||||
assert store.get(subj_dn) is not None
|
||||
filt_att = store.get(f"{subj_dn}/rssubjFiltAtt-flt-permit_ip_LAB0")
|
||||
assert filt_att is not None and filt_att.attrs["tnVzFilterName"] == "flt-permit_ip_LAB0"
|
||||
graph_att = store.get(f"{subj_dn}/rsSubjGraphAtt")
|
||||
assert graph_att is not None and graph_att.attrs["tnVnsAbsGraphName"] == "sgt-FW_LAB0"
|
||||
assert store.get(f"{tn}/flt-flt-permit_ip_LAB0") is not None
|
||||
assert store.get(f"{tn}/flt-flt-permit_ip_LAB0/e-permit_ip") is not None
|
||||
assert store.get(f"{tn}/AbsGraph-sgt-FW_LAB0") is not None
|
||||
|
||||
|
||||
def test_undeploy_removes_contract_shadows() -> None:
|
||||
state = _build_state()
|
||||
_firewall_template(state)
|
||||
apic = _FakeApicState()
|
||||
mirror_template_to_sites(state, TEMPLATE_NAME, {"1": apic}, schema_id=SCHEMA_ID)
|
||||
tn = f"uni/tn-{TENANT_NAME}"
|
||||
assert apic.store.get(f"{tn}/brc-con-Firewall_LAB0") is not None
|
||||
mirror_template_to_sites(state, TEMPLATE_NAME, {"1": apic}, schema_id=SCHEMA_ID, undeploy=True)
|
||||
assert apic.store.get(f"{tn}/brc-con-Firewall_LAB0") is None
|
||||
assert apic.store.get(f"{tn}/flt-flt-permit_ip_LAB0") is None
|
||||
assert apic.store.get(f"{tn}/AbsGraph-sgt-FW_LAB0") is None
|
||||
|
||||
Reference in New Issue
Block a user