Discovery — the read catalogue¶
Discover and describe any Cisco ACI class — offline.
The read catalogue ships with the package: metadata for all ~15,450 ACI classes (not just the ~2,200 with generated models), opened lazily on first use. This module is the public door to it — search for a class by name or label, describe its properties/faults/subclasses, or find which class carries a given property — with no APIC connection required.
Nothing here runs at import niwaki; the catalogue loads only when you import
niwaki.catalog and call one of these functions.
Example:
from niwaki import catalog
catalog.search("bridge domain") # → ['fvBD', ...] (ranked)
doc = catalog.describe("fvCEp") # label, properties, faults, subclasses
for prop in doc.props:
print(prop.readable, prop.kind) # readable field names + coercion kinds
catalog.find_prop("mac") # → [('fvCEp', 'mac'), ...]
catalog.concrete_subclasses("fvEPg") # → every concrete EPG class
catalog.fault_name("F0467") # → 'fltFvNwIssuesConfig-failed'
Functions¶
- niwaki.catalog.search(term, *, limit=50)[source]¶
Class names whose wire name or GUI label matches
term.Ranked by the full-text index where the runtime’s sqlite provides it, or a (broader, unranked) substring scan otherwise.
- niwaki.catalog.describe(class_name)[source]¶
Describe a class: its label, comment, properties, faults, and subclasses.
- Parameters:
class_name (str) – The wire class name, e.g.
"fvCEp".- Returns:
A
ClassDoc—name,label,comment,is_abstract,is_observable(informational only — not a subscribability gate, see the field’s own docstring), a tuple ofPropDoc, a{code: name}fault map, and (for an abstract class) its concrete subclasses.- Raises:
UnknownClassError – No such class in the catalogue (also a
KeyError).- Return type:
- niwaki.catalog.prop_meta(class_name, name)[source]¶
Describe one property of a class, addressed by its readable or wire name.
- Parameters:
- Returns:
A
PropDoc.- Raises:
UnknownClassError – The class or property is unknown (also a
KeyError).- Return type:
- niwaki.catalog.find_prop(term, *, limit=50)[source]¶
(class, wire property)pairs whose property name or label matchesterm.Answers “which class carries a MAC?” — the complement to
search().
- niwaki.catalog.concrete_subclasses(class_name)[source]¶
Every concrete descendant of a class, walked transitively.
The set an abstract-class query (e.g.
aci.query("fvEPg")) fans out to.
- niwaki.catalog.class_meta(class_name)[source]¶
A class’s readable↔wire name maps and per-property coercion kinds.
Lower-level than
describe(); the same metadata the result objects use to expose readable field names on non-generated classes. Also carriesis_stat— whether the APIC can ever push for this class (a stats class, e.g. a granularity variant likeeqptEgrBytes5min, never can).- Parameters:
class_name (str) – The wire class name.
- Returns:
A
ClassMeta.- Raises:
UnknownClassError – No such class in the catalogue (also a
KeyError).- Return type:
- niwaki.catalog.fault_name(code)[source]¶
The rule name behind a fault code, e.g.
"F0467"→"fltFvNwIssuesConfig-failed".This is a global lookup — it does not require knowing which class raised the fault. That complements
describe(), whosefaultsmapping is scoped to one class (the faults that class can raise): aManagedObjectread back fromfaultInstcarries acodebut not the class that raised it, so this is the function that turns it into a human-readable name.- Parameters:
code (str) – The fault code, e.g.
"F0467".- Returns:
The fault’s rule name, or
Noneif the code is not in the catalogue — this is expected for threshold-crossing alerts (tca-*rules), whose codes are minted at runtime from an operator’sstatsThresholdPolicyrather than defined statically in the class schema.- Return type:
str | None
Example:
faults = aci.query("faultInst").fetch() for f in faults: print(f["code"], catalog.fault_name(f["code"]))
- niwaki.catalog.dn_formats(class_name)[source]¶
Every DN shape the APIC uses for a class, as templates.
A class is rarely reachable at a single place in the tree. A subnet lives under a bridge domain, under an EPG, under a tenant, under an L2Out external EPG and under several service-graph nodes — a dozen shapes, one class. These are those shapes, verbatim from the schema, with the identifying values left as
{placeholder}.Quote them; do not rebuild them. A template is a fact about the controller, and reconstructing one by chaining parent RNs does not reproduce it: the containment graph is both wider than the DNs the APIC actually mints and, in places, missing parents that it does mint. A repeated placeholder is normal and is not a mistake to correct —
uni/tn-{name}/BD-{name}names a tenant and a bridge domain, each identified byname.- Parameters:
class_name (str) – The wire class name, e.g.
"fvBD".- Returns:
The templates in schema order, duplicates included — the schema’s list as it stands. Empty for a class the schema gives none, which is the common case for an abstract class: its places belong to the concrete classes behind it (
concrete_subclasses()).An empty string is a legitimate template — a container that prefixes nothing. It can be the whole answer (six classes, the root of the tree among them) or sit beside real templates in the same list, so filter the empties out rather than testing the first element.
The templates are not format strings: the same placeholder can name two different objects, so
str.formaton one silently builds a wrong DN.- Raises:
UnknownClassError – No such class in the catalogue. Also a
KeyError.- Return type:
Example:
catalog.dn_formats("fvBD") # ('uni/tn-{name}/BD-{name}',) len(catalog.dn_formats("fvSubnet")) # 12 — one class, twelve places
- niwaki.catalog.rn_format(class_name)[source]¶
The RN format of a class — the template for its own DN segment.
A class has exactly one, regardless of where it sits:
"BD-{name}"for a bridge domain,"subnet-[{ip}]"for a subnet. It is the inverse key of DN computation — the piece a reader needs to turn a DN read back from a fabric into its naming values.- Parameters:
class_name (str) – The wire class name, e.g.
"fvBD".- Returns:
The RN format string, empty when the class defines none.
- Raises:
UnknownClassError – No such class in the catalogue (also a
KeyError).- Return type:
Example:
catalog.rn_format("fvBD") # → "BD-{name}" catalog.rn_format("fvSubnet") # → "subnet-[{ip}]"
- niwaki.catalog.prop_flags(class_name)[source]¶
Every property’s schema flags for a class, keyed by wire name.
The raw material of data-driven normalisation: what is configuration (
is_configurable), what the controller computes (read_only,implicit), what never changes after creation (create_only), what names the object (is_naming), what the APIC never echoes back (secure). One catalogue query per class, then memoised.- Parameters:
class_name (str) – The wire class name, e.g.
"fvBD".- Returns:
Mapping of wire property name to its
PropFlags.- Raises:
UnknownClassError – No such class in the catalogue (also a
KeyError).- Return type:
Example:
flags = catalog.prop_flags("fvBD") flags["arpFlood"].is_configurable # → True flags["arpFlood"].read_only # → False
- niwaki.catalog.generated_classes()[source]¶
Wire names of every class the SDK generates a typed model for, sorted.
The set behind “generated” everywhere in this module: the ~2,200 concrete, configurable, non-deprecated classes that ship as Pydantic models with readable field names. Everything else the catalogue serves dynamically. Offline — no APIC connection required — and derived from the code generator’s own shipped index, so it cannot drift from the model files.
Every returned name resolves through
describe()andclass_meta()withoutKeyError, and every returned class is concrete and non-stat.- Returns:
Sorted, deduplicated wire class names, computed once per process.
- Return type:
Example:
classes = catalog.generated_classes() assert "fvBD" in classes # configurable → has a model assert "topSystem" not in classes # readable only → catalogue-served
- niwaki.catalog.schema_version()[source]¶
The APIC firmware the shipped catalogue and models were generated from.
Every typed model, curated vocabulary entry and filter operator in this SDK derives from one firmware’s schemas. This names it, read from the shipped artifact itself rather than from a constant that could drift from it.
Pair it with
niwaki.Niwaki.apic_version— the firmware a fabric reports at login — to answer “am I inside the envelope this SDK was built for?”. Offline, like everything else in this module.- Returns:
The version string, e.g.
"6.0(9c)".- Return type:
Example:
assert catalog.schema_version() == "6.0(9c)"
Result types¶
- class niwaki.catalog.ClassDoc(
- name,
- label,
- comment,
- is_abstract,
- is_observable,
- props,
- faults,
- concrete_subclasses,
Bases:
objectA class, as
describepresents it: identity, properties, faults, kin.- is_observable¶
APIC schema metadata, informational only — do not treat this as a gate on whether the class can be subscribed to. Empirically falsified live: a class with
is_observable=False(faultInst) was subscribed to successfully and delivered real push notifications. The flag that actually governs subscribability isisStat(seeClassMeta.is_stat).- Type:
- class niwaki.catalog.PropDoc(readable, wire, kind, is_naming, label, default, comment, enum_values)[source]¶
Bases:
objectOne property, as
describepresents it.
- class niwaki.catalog.ClassMeta(
- class_name,
- readable_to_wire,
- wire_to_readable,
- wire_to_kind,
- naming,
- is_stat,
- has_model=False,
Bases:
objectThe read metadata for one ACI class, assembled once and memoised.
- wire_to_kind¶
{wire_name: FieldKind value | None}— how to coerce a wire value on read (None= read as a plain string).
- is_stat¶
The class is a statistics class (a granularity variant of a stats family, e.g.
eqptEgrBytes5min). Cisco’s own docs state stats updates bypass the APIC’s event manager entirely — architecturally incapable of ever pushing — so this is what gatesStatsClassNotSubscribableError, notisObservable(seeClassDoc.is_observable).- Type:
- class niwaki.catalog.PropFlags(
- is_configurable,
- needs_prop_delimiters,
- create_only,
- read_write,
- read_only,
- is_naming,
- secure,
- implicit,
- mandatory,
- is_override,
- is_like,
- is_nxos_converged,
- is_deprecated,
- is_hidden,
Bases:
objectThe APIC schema flags of one property, unpacked from the catalogue.
One boolean per flag the 6.0 schemas declare, named 1:1 with Cisco’s own keys (snake-cased) — no editorial layer. This is the raw material of any data-driven normalisation: what is configuration (
is_configurable), what the controller computes (read_only,implicit), what never changes after creation (create_only), what names the object (is_naming), what the APIC never echoes back (secure).A caution proven on the live corpus:
securealone is not a secret policy.snmpCommunityPcarries its community string as a naming property (nosecureflag, and it rides inside the DN), andvnsCCred.valueis plainread_write. Flags feed a policy; they do not replace one.