From 077917f011b960c99c51fc85f91770d298b21f97 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Thu, 5 Feb 2026 15:52:36 +0000 Subject: [PATCH 01/58] feat(schema): add base infrastructure schema Add core infrastructure models for Device, Interface, IPAddress, and Platform based on the arista-evpn-vxlan-clab topology. Ref: #41 --- schemas/base.yml | 336 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 schemas/base.yml diff --git a/schemas/base.yml b/schemas/base.yml new file mode 100644 index 0000000..8bf762f --- /dev/null +++ b/schemas/base.yml @@ -0,0 +1,336 @@ +# Base Infrastructure Schema for EVPN-VXLAN Fabric +# This schema defines core infrastructure objects required for fabric orchestration +--- +version: "1.0" +generics: + - name: Interface + namespace: Infra + description: Generic interface - parent for all interface types + label: Interface + include_in_menu: false + hierarchical: false + attributes: + - name: name + kind: Text + description: Interface name (e.g., Ethernet1, Loopback0) + - name: description + kind: Text + optional: true + - name: enabled + kind: Boolean + default_value: true + - name: mtu + kind: Number + optional: true + description: Maximum Transmission Unit + relationships: + - name: device + peer: InfraDevice + cardinality: one + kind: Parent + - name: ip_addresses + peer: InfraIPAddress + cardinality: many + kind: Component + +nodes: + # ============================================================================= + # Location + # ============================================================================= + - name: Site + namespace: Location + description: Physical site or data center + label: Site + icon: mingcute--building-4-line + default_filter: name__value + order_by: + - name__value + display_labels: + - name__value + attributes: + - name: name + kind: Text + unique: true + - name: description + kind: Text + optional: true + - name: facility + kind: Text + optional: true + description: Facility identifier or code + + # ============================================================================= + # Platform + # ============================================================================= + - name: Platform + namespace: Infra + description: Device platform/OS (e.g., Arista EOS, Cisco NX-OS) + label: Platform + icon: mdi--chip + default_filter: name__value + order_by: + - name__value + display_labels: + - name__value + attributes: + - name: name + kind: Text + unique: true + description: Platform name (e.g., arista_eos, cisco_nxos) + - name: description + kind: Text + optional: true + - name: napalm_driver + kind: Text + optional: true + description: NAPALM driver name + - name: netmiko_device_type + kind: Text + optional: true + description: Netmiko device type + + # ============================================================================= + # Device + # ============================================================================= + - name: Device + namespace: Infra + description: Network device (spine, leaf, etc.) + label: Device + icon: mdi--server-network + default_filter: name__value + order_by: + - name__value + display_labels: + - name__value + attributes: + - name: name + kind: Text + unique: true + description: Device hostname + - name: description + kind: Text + optional: true + - name: role + kind: Dropdown + choices: + - name: spine + label: Spine + color: "#3b82f6" + - name: leaf + label: Leaf + color: "#22c55e" + - name: border_leaf + label: Border Leaf + color: "#f59e0b" + description: Fabric role + - name: router_id + kind: IPHost + optional: true + description: BGP Router ID (typically Loopback0) + - name: status + kind: Dropdown + default_value: active + choices: + - name: active + label: Active + color: "#22c55e" + - name: planned + label: Planned + color: "#3b82f6" + - name: maintenance + label: Maintenance + color: "#f59e0b" + - name: decommissioned + label: Decommissioned + color: "#ef4444" + relationships: + - name: site + peer: LocationSite + cardinality: one + optional: true + - name: platform + peer: InfraPlatform + cardinality: one + optional: true + - name: asn + peer: InfraAutonomousSystem + cardinality: one + optional: true + description: BGP Autonomous System + - name: interfaces + peer: InfraInterface + cardinality: many + kind: Component + - name: mlag_domain + peer: InfraMlagDomain + cardinality: one + optional: true + + # ============================================================================= + # Interface Types (inherit from InfraInterface generic) + # ============================================================================= + - name: InterfaceEthernet + namespace: Infra + description: Physical Ethernet interface + label: Ethernet Interface + icon: mdi--ethernet + inherit_from: + - InfraInterface + default_filter: name__value + display_labels: + - name__value + attributes: + - name: speed + kind: Dropdown + optional: true + choices: + - name: "1000" + label: 1 Gbps + - name: "10000" + label: 10 Gbps + - name: "25000" + label: 25 Gbps + - name: "40000" + label: 40 Gbps + - name: "100000" + label: 100 Gbps + - name: mode + kind: Dropdown + optional: true + choices: + - name: access + label: Access + - name: trunk + label: Trunk + - name: routed + label: Routed (L3) + description: Switchport mode + relationships: + - name: lag + peer: InfraInterfaceLag + cardinality: one + optional: true + description: Parent LAG interface + - name: connected_interface + peer: InfraInterfaceEthernet + cardinality: one + optional: true + description: Connected peer interface + + - name: InterfaceLoopback + namespace: Infra + description: Loopback interface + label: Loopback Interface + icon: mdi--reload + inherit_from: + - InfraInterface + default_filter: name__value + display_labels: + - name__value + + - name: InterfaceVlan + namespace: Infra + description: VLAN SVI interface + label: VLAN Interface + icon: mdi--lan + inherit_from: + - InfraInterface + default_filter: name__value + display_labels: + - name__value + relationships: + - name: vlan + peer: InfraVLAN + cardinality: one + optional: true + + - name: InterfaceLag + namespace: Infra + description: Link Aggregation (Port-Channel) interface + label: LAG Interface + icon: mdi--link-variant + inherit_from: + - InfraInterface + default_filter: name__value + display_labels: + - name__value + attributes: + - name: lacp_mode + kind: Dropdown + optional: true + choices: + - name: active + label: Active + - name: passive + label: Passive + - name: static + label: Static (No LACP) + - name: mlag_id + kind: Number + optional: true + description: MLAG interface ID + relationships: + - name: members + peer: InfraInterfaceEthernet + cardinality: many + kind: Component + + - name: InterfaceVxlan + namespace: Infra + description: VXLAN tunnel interface + label: VXLAN Interface + icon: mdi--tunnel + inherit_from: + - InfraInterface + default_filter: name__value + display_labels: + - name__value + attributes: + - name: udp_port + kind: Number + default_value: 4789 + relationships: + - name: source_interface + peer: InfraInterfaceLoopback + cardinality: one + description: VTEP source interface (typically Loopback1) + + # ============================================================================= + # IP Address + # ============================================================================= + - name: IPAddress + namespace: Infra + description: IP Address assignment + label: IP Address + icon: mdi--ip-network + default_filter: address__value + order_by: + - address__value + display_labels: + - address__value + attributes: + - name: address + kind: IPNetwork + description: IP address with prefix (e.g., 10.0.1.1/31) + - name: description + kind: Text + optional: true + - name: status + kind: Dropdown + default_value: active + choices: + - name: active + label: Active + color: "#22c55e" + - name: reserved + label: Reserved + color: "#3b82f6" + - name: deprecated + label: Deprecated + color: "#ef4444" + relationships: + - name: interface + peer: InfraInterface + cardinality: one + optional: true + kind: Parent -- 2.53.0 From 535f24a920e4e70efebf8d2aace2f3fd2e01671a Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Thu, 5 Feb 2026 15:52:58 +0000 Subject: [PATCH 02/58] feat(schema): add VLAN and VXLAN schema Add models for VLAN, VNI, VTEP, VLAN-VNI mappings, and EVPN instances. Supports L2VNI and L3VNI types for EVPN-VXLAN fabric. Ref: #41 --- schemas/vlan_vxlan.yml | 204 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 schemas/vlan_vxlan.yml diff --git a/schemas/vlan_vxlan.yml b/schemas/vlan_vxlan.yml new file mode 100644 index 0000000..a30bac3 --- /dev/null +++ b/schemas/vlan_vxlan.yml @@ -0,0 +1,204 @@ +# VLAN and VXLAN Schema for EVPN-VXLAN Fabric +# Defines VLAN, VNI mappings, and VTEP configuration +--- +version: "1.0" +nodes: + # ============================================================================= + # VLAN + # ============================================================================= + - name: VLAN + namespace: Infra + description: Virtual LAN configuration + label: VLAN + icon: mdi--lan-connect + default_filter: vlan_id__value + order_by: + - vlan_id__value + display_labels: + - vlan_id__value + - name__value + attributes: + - name: vlan_id + kind: Number + description: VLAN ID (1-4094) + - name: name + kind: Text + description: VLAN name + - name: description + kind: Text + optional: true + - name: status + kind: Dropdown + default_value: active + choices: + - name: active + label: Active + color: "#22c55e" + - name: reserved + label: Reserved + color: "#3b82f6" + - name: deprecated + label: Deprecated + color: "#ef4444" + - name: vlan_type + kind: Dropdown + default_value: standard + choices: + - name: standard + label: Standard + - name: mlag_peer + label: MLAG Peer + - name: mlag_ibgp + label: MLAG iBGP + description: VLAN purpose + relationships: + - name: vni + peer: InfraVNI + cardinality: one + optional: true + description: Associated L2VNI for VXLAN + - name: site + peer: LocationSite + cardinality: one + optional: true + + # ============================================================================= + # VNI (VXLAN Network Identifier) + # ============================================================================= + - name: VNI + namespace: Infra + description: VXLAN Network Identifier + label: VNI + icon: mdi--tunnel-outline + default_filter: vni__value + order_by: + - vni__value + display_labels: + - vni__value + attributes: + - name: vni + kind: Number + unique: true + description: VNI value (1-16777215) + - name: description + kind: Text + optional: true + - name: vni_type + kind: Dropdown + default_value: l2vni + choices: + - name: l2vni + label: L2 VNI + color: "#3b82f6" + - name: l3vni + label: L3 VNI + color: "#22c55e" + description: VNI type for EVPN + relationships: + - name: vlan + peer: InfraVLAN + cardinality: one + optional: true + description: Associated VLAN for L2VNI + - name: vrf + peer: InfraVRF + cardinality: one + optional: true + description: Associated VRF for L3VNI + + # ============================================================================= + # VTEP (VXLAN Tunnel Endpoint) + # ============================================================================= + - name: VTEP + namespace: Infra + description: VXLAN Tunnel Endpoint configuration + label: VTEP + icon: mdi--server-network-outline + default_filter: source_address__value + display_labels: + - device__name__value + attributes: + - name: source_address + kind: IPHost + description: VTEP source IP (typically from Loopback1) + - name: udp_port + kind: Number + default_value: 4789 + - name: learn_restrict + kind: Dropdown + default_value: any + choices: + - name: any + label: Any + - name: flood + label: Flood + description: MAC learning restriction mode + relationships: + - name: device + peer: InfraDevice + cardinality: one + kind: Parent + - name: source_interface + peer: InfraInterfaceLoopback + cardinality: one + description: Source interface for VTEP + - name: vlan_vni_mappings + peer: InfraVlanVniMapping + cardinality: many + kind: Component + + # ============================================================================= + # VLAN to VNI Mapping (per-device) + # ============================================================================= + - name: VlanVniMapping + namespace: Infra + description: VLAN to VNI mapping on a VTEP + label: VLAN-VNI Mapping + icon: mdi--swap-horizontal + display_labels: + - vlan__vlan_id__value + - vni__vni__value + relationships: + - name: vtep + peer: InfraVTEP + cardinality: one + kind: Parent + - name: vlan + peer: InfraVLAN + cardinality: one + - name: vni + peer: InfraVNI + cardinality: one + + # ============================================================================= + # EVPN Instance (per VLAN) + # ============================================================================= + - name: EVPNInstance + namespace: Infra + description: EVPN instance configuration (route targets for L2 extension) + label: EVPN Instance + icon: mdi--cloud-sync + default_filter: vlan__vlan_id__value + display_labels: + - vlan__vlan_id__value + attributes: + - name: rd + kind: Text + description: "Route Distinguisher (format: ASN:VNI or IP:VNI)" + - name: route_target_import + kind: Text + description: "Import Route Target (format: VNI:VNI)" + - name: route_target_export + kind: Text + description: "Export Route Target (format: VNI:VNI)" + - name: redistribute_learned + kind: Boolean + default_value: true + relationships: + - name: vlan + peer: InfraVLAN + cardinality: one + - name: device + peer: InfraDevice + cardinality: one + kind: Parent -- 2.53.0 From d87ffcaca6bb76590a8100c5b1444806e1893a07 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Thu, 5 Feb 2026 15:53:11 +0000 Subject: [PATCH 03/58] feat(schema): add VRF schema Add models for VRF, Route Target, and VRF-Device assignments. Supports L3VNI association for symmetric IRB routing. Ref: #41 --- schemas/vrf.yml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 schemas/vrf.yml diff --git a/schemas/vrf.yml b/schemas/vrf.yml new file mode 100644 index 0000000..aa8a10d --- /dev/null +++ b/schemas/vrf.yml @@ -0,0 +1,109 @@ +# VRF Schema for EVPN-VXLAN Fabric +# Defines VRF and Route Target configuration for L3 VPN +--- +version: "1.0" +nodes: + # ============================================================================= + # VRF (Virtual Routing and Forwarding) + # ============================================================================= + - name: VRF + namespace: Infra + description: Virtual Routing and Forwarding instance + label: VRF + icon: mdi--router + default_filter: name__value + order_by: + - name__value + display_labels: + - name__value + attributes: + - name: name + kind: Text + description: VRF name + - name: description + kind: Text + optional: true + - name: rd + kind: Text + optional: true + description: "Route Distinguisher (format: ASN:NN or IP:NN)" + - name: vrf_id + kind: Number + optional: true + description: VRF table ID + relationships: + - name: l3vni + peer: InfraVNI + cardinality: one + optional: true + description: L3 VNI for symmetric IRB + - name: import_targets + peer: InfraRouteTarget + cardinality: many + optional: true + - name: export_targets + peer: InfraRouteTarget + cardinality: many + optional: true + - name: interfaces + peer: InfraInterface + cardinality: many + optional: true + description: Interfaces assigned to this VRF + + # ============================================================================= + # Route Target + # ============================================================================= + - name: RouteTarget + namespace: Infra + description: BGP Route Target for VPN import/export + label: Route Target + icon: mdi--target + default_filter: target__value + order_by: + - target__value + display_labels: + - target__value + attributes: + - name: target + kind: Text + unique: true + description: "Route Target value (format: ASN:NN or IP:NN)" + - name: description + kind: Text + optional: true + + # ============================================================================= + # VRF Device Assignment + # ============================================================================= + - name: VRFDeviceAssignment + namespace: Infra + description: VRF assignment to a specific device + label: VRF Assignment + icon: mdi--router-network + display_labels: + - vrf__name__value + - device__name__value + attributes: + - name: rd + kind: Text + optional: true + description: "Device-specific RD (overrides VRF default)" + relationships: + - name: vrf + peer: InfraVRF + cardinality: one + - name: device + peer: InfraDevice + cardinality: one + kind: Parent + - name: import_targets + peer: InfraRouteTarget + cardinality: many + optional: true + description: Device-specific import RTs + - name: export_targets + peer: InfraRouteTarget + cardinality: many + optional: true + description: Device-specific export RTs -- 2.53.0 From 3e96b0ff1ade6375b5bca8e689b69a65f56160ca Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Thu, 5 Feb 2026 15:53:32 +0000 Subject: [PATCH 04/58] feat(schema): add BGP schema Add models for Autonomous System, BGP Router Config, Peer Groups, BGP Sessions, and Address Families. Supports underlay and EVPN overlay. Ref: #41 --- schemas/bgp.yml | 239 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 schemas/bgp.yml diff --git a/schemas/bgp.yml b/schemas/bgp.yml new file mode 100644 index 0000000..32e3b1a --- /dev/null +++ b/schemas/bgp.yml @@ -0,0 +1,239 @@ +# BGP Schema for EVPN-VXLAN Fabric +# Defines Autonomous System, Peer Groups, and BGP Sessions +--- +version: "1.0" +nodes: + # ============================================================================= + # Autonomous System + # ============================================================================= + - name: AutonomousSystem + namespace: Infra + description: BGP Autonomous System + label: Autonomous System + icon: mdi--cloud-outline + default_filter: asn__value + order_by: + - asn__value + display_labels: + - asn__value + - description__value + attributes: + - name: asn + kind: Number + unique: true + description: AS Number (e.g., 65000) + - name: description + kind: Text + optional: true + - name: as_type + kind: Dropdown + default_value: private + choices: + - name: private + label: Private + - name: public + label: Public + + # ============================================================================= + # BGP Router Configuration (per device) + # ============================================================================= + - name: BGPRouterConfig + namespace: Infra + description: BGP router configuration on a device + label: BGP Router Config + icon: mdi--router-wireless + display_labels: + - device__name__value + attributes: + - name: router_id + kind: IPHost + description: BGP Router ID + - name: default_ipv4_unicast + kind: Boolean + default_value: false + description: Enable default IPv4 unicast + - name: log_neighbor_changes + kind: Boolean + default_value: true + - name: ecmp_max_paths + kind: Number + default_value: 4 + description: Maximum ECMP paths + - name: ecmp_max_ecmp + kind: Number + default_value: 64 + description: Maximum ECMP routes + relationships: + - name: device + peer: InfraDevice + cardinality: one + kind: Parent + - name: local_asn + peer: InfraAutonomousSystem + cardinality: one + - name: peer_groups + peer: InfraBGPPeerGroup + cardinality: many + kind: Component + - name: sessions + peer: InfraBGPSession + cardinality: many + kind: Component + + # ============================================================================= + # BGP Peer Group + # ============================================================================= + - name: BGPPeerGroup + namespace: Infra + description: BGP peer group template + label: BGP Peer Group + icon: mdi--account-group + default_filter: name__value + display_labels: + - name__value + attributes: + - name: name + kind: Text + description: Peer group name (e.g., underlay, evpn) + - name: description + kind: Text + optional: true + - name: update_source + kind: Text + optional: true + description: Update source interface (e.g., Loopback0) + - name: ebgp_multihop + kind: Number + optional: true + description: eBGP multihop TTL + - name: send_community + kind: Dropdown + default_value: none + choices: + - name: none + label: None + - name: standard + label: Standard + - name: extended + label: Extended + - name: both + label: Both + - name: next_hop_self + kind: Boolean + default_value: false + - name: next_hop_unchanged + kind: Boolean + default_value: false + description: Keep next-hop unchanged (for route reflector) + - name: maximum_routes + kind: Number + optional: true + - name: maximum_routes_warning_only + kind: Boolean + default_value: true + - name: peer_group_type + kind: Dropdown + default_value: underlay + choices: + - name: underlay + label: Underlay IPv4 + - name: underlay_ibgp + label: Underlay iBGP + - name: evpn + label: EVPN Overlay + relationships: + - name: bgp_config + peer: InfraBGPRouterConfig + cardinality: one + kind: Parent + - name: remote_asn + peer: InfraAutonomousSystem + cardinality: one + optional: true + + # ============================================================================= + # BGP Session (Neighbor) + # ============================================================================= + - name: BGPSession + namespace: Infra + description: BGP neighbor session + label: BGP Session + icon: mdi--connection + default_filter: peer_address__value + display_labels: + - peer_address__value + attributes: + - name: peer_address + kind: IPHost + description: Neighbor IP address + - name: description + kind: Text + optional: true + - name: enabled + kind: Boolean + default_value: true + relationships: + - name: bgp_config + peer: InfraBGPRouterConfig + cardinality: one + kind: Parent + - name: peer_group + peer: InfraBGPPeerGroup + cardinality: one + optional: true + - name: remote_asn + peer: InfraAutonomousSystem + cardinality: one + optional: true + description: Override peer group remote-as + - name: peer_device + peer: InfraDevice + cardinality: one + optional: true + description: Remote peer device (for documentation) + + # ============================================================================= + # BGP Address Family Configuration + # ============================================================================= + - name: BGPAddressFamily + namespace: Infra + description: BGP address family configuration + label: BGP Address Family + icon: mdi--format-list-bulleted + display_labels: + - afi__value + - safi__value + attributes: + - name: afi + kind: Dropdown + choices: + - name: ipv4 + label: IPv4 + - name: ipv6 + label: IPv6 + - name: evpn + label: EVPN + description: Address Family Identifier + - name: safi + kind: Dropdown + default_value: unicast + choices: + - name: unicast + label: Unicast + - name: multicast + label: Multicast + description: Sub Address Family Identifier + relationships: + - name: bgp_config + peer: InfraBGPRouterConfig + cardinality: one + kind: Parent + - name: active_peer_groups + peer: InfraBGPPeerGroup + cardinality: many + description: Peer groups activated in this AF + - name: networks + peer: InfraIPAddress + cardinality: many + optional: true + description: Networks to advertise -- 2.53.0 From e3ef0b376323d9bed26944362c630d70b270e617 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Thu, 5 Feb 2026 15:53:49 +0000 Subject: [PATCH 05/58] feat(schema): add MLAG schema Add models for MLAG Domain, Peer Config, and MLAG Interfaces. Supports dual-primary detection and heartbeat configuration. Ref: #41 --- schemas/mlag.yml | 133 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 schemas/mlag.yml diff --git a/schemas/mlag.yml b/schemas/mlag.yml new file mode 100644 index 0000000..6797b47 --- /dev/null +++ b/schemas/mlag.yml @@ -0,0 +1,133 @@ +# MLAG Schema for EVPN-VXLAN Fabric +# Defines MLAG domain and peer configuration +--- +version: "1.0" +nodes: + # ============================================================================= + # MLAG Domain + # ============================================================================= + - name: MlagDomain + namespace: Infra + description: MLAG domain configuration for leaf pair + label: MLAG Domain + icon: mdi--link-variant + default_filter: domain_id__value + display_labels: + - domain_id__value + attributes: + - name: domain_id + kind: Text + description: MLAG domain identifier (e.g., leafs) + - name: description + kind: Text + optional: true + - name: virtual_mac + kind: Text + description: "Shared virtual MAC (format: xxxx.xxxx.xxxx)" + - name: heartbeat_vrf + kind: Text + default_value: mgmt + description: VRF for heartbeat (typically mgmt) + - name: dual_primary_detection + kind: Boolean + default_value: true + - name: dual_primary_delay + kind: Number + default_value: 10 + description: Delay in seconds before dual-primary action + - name: dual_primary_action + kind: Dropdown + default_value: errdisable + choices: + - name: errdisable + label: Error Disable Interfaces + - name: none + label: No Action + relationships: + - name: devices + peer: InfraDevice + cardinality: many + min_count: 2 + max_count: 2 + description: MLAG peer devices + - name: peer_vlan + peer: InfraVLAN + cardinality: one + description: VLAN for MLAG peer-link control traffic + - name: ibgp_vlan + peer: InfraVLAN + cardinality: one + optional: true + description: VLAN for iBGP peering between MLAG peers + + # ============================================================================= + # MLAG Peer Configuration (per device) + # ============================================================================= + - name: MlagPeerConfig + namespace: Infra + description: MLAG configuration on a specific device + label: MLAG Peer Config + icon: mdi--server-network + display_labels: + - device__name__value + attributes: + - name: local_interface_ip + kind: IPNetwork + description: IP on MLAG peer VLAN SVI + - name: peer_address + kind: IPHost + description: Peer's MLAG SVI IP address + - name: heartbeat_peer_ip + kind: IPHost + description: Peer's management IP for heartbeat + relationships: + - name: device + peer: InfraDevice + cardinality: one + kind: Parent + - name: mlag_domain + peer: InfraMlagDomain + cardinality: one + - name: local_interface + peer: InfraInterfaceVlan + cardinality: one + description: Local MLAG SVI + - name: peer_link + peer: InfraInterfaceLag + cardinality: one + description: Peer-link port-channel + + # ============================================================================= + # MLAG Interface (MLAG-enabled LAG) + # ============================================================================= + - name: MlagInterface + namespace: Infra + description: MLAG interface configuration + label: MLAG Interface + icon: mdi--ethernet-cable + display_labels: + - mlag_id__value + attributes: + - name: mlag_id + kind: Number + description: MLAG interface ID + - name: description + kind: Text + optional: true + - name: lacp_fallback_timeout + kind: Number + default_value: 5 + description: LACP fallback timeout in seconds + - name: lacp_fallback_individual + kind: Boolean + default_value: true + relationships: + - name: mlag_domain + peer: InfraMlagDomain + cardinality: one + - name: lag_interfaces + peer: InfraInterfaceLag + cardinality: many + min_count: 1 + max_count: 2 + description: LAG interfaces on each MLAG peer -- 2.53.0 From bd46d5f0465a59e29e7de32251c6316bdc157a6a Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Thu, 5 Feb 2026 15:54:07 +0000 Subject: [PATCH 06/58] feat(schema): add extensions schema Add Fabric, Underlay Link, and Host Connection models for fabric-wide configuration and topology documentation. Ref: #41 --- schemas/extensions.yml | 147 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 schemas/extensions.yml diff --git a/schemas/extensions.yml b/schemas/extensions.yml new file mode 100644 index 0000000..87e20fd --- /dev/null +++ b/schemas/extensions.yml @@ -0,0 +1,147 @@ +# Extensions Schema for EVPN-VXLAN Fabric +# Custom attributes and fabric-specific configurations +--- +version: "1.0" +nodes: + # ============================================================================= + # Fabric (Top-level container for all fabric objects) + # ============================================================================= + - name: Fabric + namespace: Infra + description: EVPN-VXLAN Fabric definition + label: Fabric + icon: mdi--vector-polygon + default_filter: name__value + order_by: + - name__value + display_labels: + - name__value + attributes: + - name: name + kind: Text + unique: true + description: Fabric name (e.g., arista-evpn-fabric) + - name: description + kind: Text + optional: true + - name: underlay_protocol + kind: Dropdown + default_value: ebgp + choices: + - name: ebgp + label: eBGP + - name: ospf + label: OSPF + - name: isis + label: IS-IS + - name: overlay_protocol + kind: Dropdown + default_value: evpn + choices: + - name: evpn + label: EVPN + - name: ingress_replication + label: Ingress Replication + - name: anycast_gateway_mac + kind: Text + optional: true + description: "Shared MAC for anycast gateway (format: xxxx.xxxx.xxxx)" + relationships: + - name: spine_asn + peer: InfraAutonomousSystem + cardinality: one + optional: true + description: AS used by spine layer + - name: sites + peer: LocationSite + cardinality: many + optional: true + + # ============================================================================= + # Underlay P2P Link + # ============================================================================= + - name: UnderlayLink + namespace: Infra + description: Point-to-point underlay link between devices + label: Underlay Link + icon: mdi--cable-data + display_labels: + - local_device__name__value + - remote_device__name__value + attributes: + - name: local_ip + kind: IPNetwork + description: Local interface IP with mask + - name: remote_ip + kind: IPNetwork + description: Remote interface IP with mask + - name: mtu + kind: Number + default_value: 9214 + relationships: + - name: fabric + peer: InfraFabric + cardinality: one + kind: Parent + - name: local_device + peer: InfraDevice + cardinality: one + - name: local_interface + peer: InfraInterfaceEthernet + cardinality: one + - name: remote_device + peer: InfraDevice + cardinality: one + - name: remote_interface + peer: InfraInterfaceEthernet + cardinality: one + + # ============================================================================= + # Host Connection + # ============================================================================= + - name: HostConnection + namespace: Infra + description: Host connection to fabric (single or dual-homed) + label: Host Connection + icon: mdi--desktop-tower + default_filter: hostname__value + display_labels: + - hostname__value + attributes: + - name: hostname + kind: Text + description: Connected host name + - name: description + kind: Text + optional: true + - name: connection_type + kind: Dropdown + default_value: dual_homed + choices: + - name: single_homed + label: Single-Homed + - name: dual_homed + label: Dual-Homed (MLAG) + - name: lacp_mode + kind: Dropdown + default_value: active + choices: + - name: active + label: Active + - name: passive + label: Passive + relationships: + - name: vlans + peer: InfraVLAN + cardinality: many + description: VLANs allowed on this connection + - name: mlag_interface + peer: InfraMlagInterface + cardinality: one + optional: true + description: MLAG interface for dual-homed + - name: lag_interface + peer: InfraInterfaceLag + cardinality: one + optional: true + description: LAG for single-homed -- 2.53.0 From f03698dec51c9175be21a5dc7579a34ea55a3a1b Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Thu, 5 Feb 2026 15:54:38 +0000 Subject: [PATCH 07/58] docs(schema): add schema documentation and ERD Document all schema files, entity relationships, and mapping to the reference arista-evpn-vxlan-clab topology. Ref: #41 --- schemas/README.md | 113 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 schemas/README.md diff --git a/schemas/README.md b/schemas/README.md new file mode 100644 index 0000000..58f9ab2 --- /dev/null +++ b/schemas/README.md @@ -0,0 +1,113 @@ +# Infrahub Schema for EVPN-VXLAN Fabric + +This directory contains the Infrahub schema definitions for modeling an EVPN-VXLAN fabric. The schema is designed to represent the [arista-evpn-vxlan-clab](https://gitea.arnodo.fr/Damien/arista-evpn-vxlan-clab) topology. + +## Schema Files + +| File | Description | +|------|-------------| +| `base.yml` | Core infrastructure: Device, Interface types, IP Address, Platform, Site | +| `vlan_vxlan.yml` | VLAN, VNI, VTEP, EVPN Instance | +| `vrf.yml` | VRF, Route Target, VRF assignments | +| `bgp.yml` | Autonomous System, BGP Config, Peer Groups, Sessions | +| `mlag.yml` | MLAG Domain, Peer Config, MLAG Interfaces | +| `extensions.yml` | Fabric, Underlay Links, Host Connections | + +## Entity Relationship Diagram + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ FABRIC TOPOLOGY │ +└─────────────────────────────────────────────────────────────────────────────┘ + + ┌──────────────┐ + │ InfraFabric │ + └──────┬───────┘ + │ + ┌──────────────────────┼──────────────────────┐ + │ │ │ + ▼ ▼ ▼ + ┌────────────┐ ┌─────────────┐ ┌────────────┐ + │ LocationSite│ │ InfraDevice │ │InfraAutono-│ + └────────────┘ │ (spine/ │ │mousSystem │ + │ leaf) │ └─────┬──────┘ + └──────┬──────┘ │ + │ │ + ┌────────────────────────────┼─────────────────────┤ + │ │ │ + ▼ ▼ ▼ +┌──────────────┐ ┌──────────────┐ ┌──────────────┐ +│InfraInterface│ │InfraMlagDomain│ │InfraBGPRouter│ +│ (generic) │ │ (leaf pair) │ │ Config │ +└──────┬───────┘ └──────────────┘ └──────┬───────┘ + │ │ + │ ┌─────────────────────────┬───────────────────┤ + │ │ │ │ + ▼ ▼ ▼ ▼ +┌──────────────┐ ┌──────────────┐ ┌──────────────┐ +│InterfaceTypes│ │InfraBGPPeer- │ │ InfraBGP- │ +│ - Ethernet │ │ Group │ │ Session │ +│ - Loopback │ │ (underlay, │ │ (neighbors) │ +│ - Vlan │ │ evpn) │ └──────────────┘ +│ - Lag │ └──────────────┘ +│ - Vxlan │ +└──────┬───────┘ + │ + ▼ +┌──────────────┐ ┌──────────────┐ ┌──────────────┐ +│InfraIPAddress│◄────►│ InfraVLAN │◄────►│ InfraVNI │ +└──────────────┘ └──────────────┘ └──────────────┘ + │ + ▼ + ┌──────────────┐ + │ InfraVTEP │ + └──────────────┘ +``` + +## Reference Topology Mapping + +The schema models this topology from `arista-evpn-vxlan-clab`: + +| Physical | Infrahub Model | +|----------|----------------| +| spine1, spine2 | InfraDevice (role: spine) | +| leaf1-8 | InfraDevice (role: leaf) | +| AS 65000 | InfraAutonomousSystem (spines) | +| AS 65001-65004 | InfraAutonomousSystem (leaf pairs) | +| VLAN 40, 34, 78 | InfraVLAN + InfraVNI | +| VLAN 4090, 4091 | InfraVLAN (vlan_type: mlag_peer/mlag_ibgp) | +| leaf1+leaf2 pair | InfraMlagDomain | +| Port-Channel999 | InfraInterfaceLag (peer-link) | +| Port-Channel1 | InfraMlagInterface (host-facing) | +| Ethernet1-8 | InfraInterfaceEthernet | +| Loopback0, Loopback1 | InfraInterfaceLoopback | +| Vxlan1 | InfraInterfaceVxlan | +| peer groups | InfraBGPPeerGroup | + +## Usage + +### Loading the Schema + +```bash +# From the fabric-orchestrator root directory +infrahubctl schema load schemas/ +``` + +### Validation + +```bash +infrahubctl schema check schemas/ +``` + +## Key Design Decisions + +1. **Generic Interface**: All interface types inherit from `InfraInterface` generic for polymorphic queries +2. **MLAG as Domain**: MLAG is modeled as a domain containing exactly 2 devices, with per-device config +3. **BGP Hierarchy**: BGPRouterConfig → PeerGroups → Sessions allows template-based configuration +4. **VTEP Independence**: VTEP is separate from Device to support shared VTEP scenarios +5. **EVPN Instance per VLAN**: Allows device-specific RD/RT while referencing common VLAN/VNI + +## Related Issues + +- Parent issue: [#41 - Define Infrahub Schema for EVPN-VXLAN Fabric](https://gitea.arnodo.fr/Damien/fabric-orchestrator/issues/41) +- Depends on: Schema being loaded before transforms (#30, #31, #32, #33) -- 2.53.0 From ea6b66d6391744d95a0d0d4eb75ac14c1aea1e06 Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 6 Feb 2026 09:00:27 +0100 Subject: [PATCH 08/58] docs: reformat README tables for better raw readability Update Markdown tables including InfraHub comparison, Prefect benefits, and project progress phases to use consistent column padding. This improves the visual alignment and readability when viewing the raw source file. --- .infrahub.yml | 3 +++ README.md | 68 +++++++++++++++++++++++++-------------------------- 2 files changed, 37 insertions(+), 34 deletions(-) create mode 100644 .infrahub.yml diff --git a/.infrahub.yml b/.infrahub.yml new file mode 100644 index 0000000..38dd224 --- /dev/null +++ b/.infrahub.yml @@ -0,0 +1,3 @@ +--- +schemas: + - schemas \ No newline at end of file diff --git a/README.md b/README.md index ba59d4a..2015aa5 100644 --- a/README.md +++ b/README.md @@ -24,14 +24,14 @@ Think `terraform plan` and `terraform apply`, but for your network fabric — po We chose [InfraHub](https://github.com/opsmill/infrahub) over NetBox as Source of Truth for several reasons: -| Feature | NetBox | InfraHub | -|---------|--------|----------| -| **Schema** | Fixed DCIM/IPAM model | Fully customizable YAML schema | -| **Git Integration** | External sync needed | Native - branches = data branches | -| **Versioning** | Changelog only | True Git-like versioning with merges | -| **Test/Redeploy** | Dump/restore | `git clone` = complete environment | -| **Transforms** | Limited | Built-in Jinja2 + Python transforms | -| **GraphQL** | Yes | Yes (auto-generated from schema) | +| Feature | NetBox | InfraHub | +| ------------------- | --------------------- | ------------------------------------ | +| **Schema** | Fixed DCIM/IPAM model | Fully customizable YAML schema | +| **Git Integration** | External sync needed | Native - branches = data branches | +| **Versioning** | Changelog only | True Git-like versioning with merges | +| **Test/Redeploy** | Dump/restore | `git clone` = complete environment | +| **Transforms** | Limited | Built-in Jinja2 + Python transforms | +| **GraphQL** | Yes | Yes (auto-generated from schema) | **Key benefits for this project:** @@ -98,16 +98,16 @@ git push ## 🎛 Why Prefect? -| Feature | Benefit | -|---------|---------| -| **Python-native workflows** | Use `@flow` and `@task` decorators — no YAML, just Python | -| **Free secrets management** | Native `Secret` blocks for credentials (free in OSS) | -| **Built-in UI** | Dashboard, logs, metrics, execution history via `prefect server start` | -| **No containerization required** | Run flows directly with `.serve()` — no Docker needed | -| **Event-driven triggers** | Schedule, webhooks (via FastAPI), flow triggers out of the box | -| **Task dependencies** | Automatic dependency ordering via task result passing or `wait_for` | -| **Retry & error handling** | Built-in retry policies with `@task(retries=3)` | -| **Human-in-the-loop** | Native `pause_flow_run()` for approval workflows | +| Feature | Benefit | +| -------------------------------- | ---------------------------------------------------------------------- | +| **Python-native workflows** | Use `@flow` and `@task` decorators — no YAML, just Python | +| **Free secrets management** | Native `Secret` blocks for credentials (free in OSS) | +| **Built-in UI** | Dashboard, logs, metrics, execution history via `prefect server start` | +| **No containerization required** | Run flows directly with `.serve()` — no Docker needed | +| **Event-driven triggers** | Schedule, webhooks (via FastAPI), flow triggers out of the box | +| **Task dependencies** | Automatic dependency ordering via task result passing or `wait_for` | +| **Retry & error handling** | Built-in retry policies with `@task(retries=3)` | +| **Human-in-the-loop** | Native `pause_flow_run()` for approval workflows | ## 🎯 Target Fabric @@ -124,12 +124,12 @@ Reference: [arista-evpn-vxlan-clab](https://gitea.arnodo.fr/Damien/arista-evpn-v Progress is tracked via issues. See [all issues](https://gitea.arnodo.fr/Damien/fabric-orchestrator/issues) or filter by phase: -| Phase | Description | Status | -|-------|-------------|--------| -| **Phase 1** | YANG Path Discovery - Map EOS 4.35.0F YANG models, validate gNMI | ✅ Complete | +| Phase | Description | Status | +| ----------- | -------------------------------------------------------------------- | ------------- | +| **Phase 1** | YANG Path Discovery - Map EOS 4.35.0F YANG models, validate gNMI | ✅ Complete | | **Phase 2** | InfraHub Setup & Core Reconciler - Schema, diff engine, YANG mappers | 🔄 In Progress | -| **Phase 3** | Full Fabric Coverage - BGP, MLAG, VRFs mappers | 📋 Planned | -| **Phase 4** | Prefect Integration - Flows, webhooks, drift detection | 📋 Planned | +| **Phase 3** | Full Fabric Coverage - BGP, MLAG, VRFs mappers | 📋 Planned | +| **Phase 4** | Prefect Integration - Flows, webhooks, drift detection | 📋 Planned | ## 📁 Project Structure @@ -197,17 +197,17 @@ fabric-orchestrator/ ## 🛠️ Technology Stack -| Component | Technology | Purpose | -|-----------|------------|---------| -| Source of Truth | **InfraHub** | Intent definition via custom schema | -| Data Storage | **This Git repo** | Schema + data versioned together | -| Orchestrator | **Prefect** | Python-native workflow orchestration | -| Transport | gNMI | Configuration and telemetry | -| Data Models | YANG (OpenConfig + Arista) | Structured configuration | -| Python Library | pygnmi + infrahub-sdk | gNMI/InfraHub interactions | -| CLI | Click + Rich | YANG discovery tools | -| Validation | Pydantic v2 | Intent data validation | -| Lab | ContainerLab + cEOS | Development environment | +| Component | Technology | Purpose | +| --------------- | -------------------------- | ------------------------------------ | +| Source of Truth | **InfraHub** | Intent definition via custom schema | +| Data Storage | **This Git repo** | Schema + data versioned together | +| Orchestrator | **Prefect** | Python-native workflow orchestration | +| Transport | gNMI | Configuration and telemetry | +| Data Models | YANG (OpenConfig + Arista) | Structured configuration | +| Python Library | pygnmi + infrahub-sdk | gNMI/InfraHub interactions | +| CLI | Click + Rich | YANG discovery tools | +| Validation | Pydantic v2 | Intent data validation | +| Lab | ContainerLab + cEOS | Development environment | ## 🔗 Related Projects -- 2.53.0 From 443642c2a1ada477acac17372c6daed59fa2c49b Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 08:28:42 +0000 Subject: [PATCH 09/58] fix(schema): rename rd to route_distinguisher (min 3 chars) Infrahub requires attribute names to have at least 3 characters. Ref: #41 --- schemas/vrf.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schemas/vrf.yml b/schemas/vrf.yml index aa8a10d..8503dcc 100644 --- a/schemas/vrf.yml +++ b/schemas/vrf.yml @@ -23,7 +23,7 @@ nodes: - name: description kind: Text optional: true - - name: rd + - name: route_distinguisher kind: Text optional: true description: "Route Distinguisher (format: ASN:NN or IP:NN)" @@ -85,7 +85,7 @@ nodes: - vrf__name__value - device__name__value attributes: - - name: rd + - name: route_distinguisher kind: Text optional: true description: "Device-specific RD (overrides VRF default)" -- 2.53.0 From c2a92c340db0a2af1fac7076e9d1fd50de3f9a8c Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 08:29:12 +0000 Subject: [PATCH 10/58] fix(schema): rename rd to route_distinguisher in EVPNInstance Infrahub requires attribute names to have at least 3 characters. Ref: #41 --- schemas/vlan_vxlan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas/vlan_vxlan.yml b/schemas/vlan_vxlan.yml index a30bac3..765a8a7 100644 --- a/schemas/vlan_vxlan.yml +++ b/schemas/vlan_vxlan.yml @@ -182,7 +182,7 @@ nodes: display_labels: - vlan__vlan_id__value attributes: - - name: rd + - name: route_distinguisher kind: Text description: "Route Distinguisher (format: ASN:VNI or IP:VNI)" - name: route_target_import -- 2.53.0 From afa268ad2df2679c71398ecc210bf652c32dfc94 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 08:51:47 +0000 Subject: [PATCH 11/58] fix(schema): add unique identifiers for UnderlayLink relationships Infrahub requires unique identifiers when multiple relationships point to the same peer type with the same direction. Ref: #41 --- schemas/extensions.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/schemas/extensions.yml b/schemas/extensions.yml index 87e20fd..b726e27 100644 --- a/schemas/extensions.yml +++ b/schemas/extensions.yml @@ -85,15 +85,19 @@ nodes: kind: Parent - name: local_device peer: InfraDevice + identifier: underlaylink__local_device cardinality: one - name: local_interface peer: InfraInterfaceEthernet + identifier: underlaylink__local_interface cardinality: one - name: remote_device peer: InfraDevice + identifier: underlaylink__remote_device cardinality: one - name: remote_interface peer: InfraInterfaceEthernet + identifier: underlaylink__remote_interface cardinality: one # ============================================================================= -- 2.53.0 From 4f5fef7203824b3d30d3a46038afb5a49bf53f4f Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 08:55:08 +0000 Subject: [PATCH 12/58] fix(schema): use direction outbound for UnderlayLink relationships Use outbound direction to avoid bidirectional relationship conflicts when multiple relationships point to the same peer type. Ref: #41 --- schemas/extensions.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/schemas/extensions.yml b/schemas/extensions.yml index b726e27..07724bd 100644 --- a/schemas/extensions.yml +++ b/schemas/extensions.yml @@ -85,20 +85,24 @@ nodes: kind: Parent - name: local_device peer: InfraDevice - identifier: underlaylink__local_device + identifier: underlay_link_local_device cardinality: one + direction: outbound - name: local_interface peer: InfraInterfaceEthernet - identifier: underlaylink__local_interface + identifier: underlay_link_local_interface cardinality: one + direction: outbound - name: remote_device peer: InfraDevice - identifier: underlaylink__remote_device + identifier: underlay_link_remote_device cardinality: one + direction: outbound - name: remote_interface peer: InfraInterfaceEthernet - identifier: underlaylink__remote_interface + identifier: underlay_link_remote_interface cardinality: one + direction: outbound # ============================================================================= # Host Connection -- 2.53.0 From 6d08b19b5fd84852493d6321ad79c6639db55306 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 09:04:39 +0000 Subject: [PATCH 13/58] fix(schema): add unique identifiers for MlagDomain VLAN relationships Add identifier and direction: outbound for peer_vlan and ibgp_vlan to avoid bidirectional relationship conflicts. Ref: #41 --- schemas/mlag.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/schemas/mlag.yml b/schemas/mlag.yml index 6797b47..2b5f419 100644 --- a/schemas/mlag.yml +++ b/schemas/mlag.yml @@ -52,11 +52,15 @@ nodes: description: MLAG peer devices - name: peer_vlan peer: InfraVLAN + identifier: mlag_domain_peer_vlan cardinality: one + direction: outbound description: VLAN for MLAG peer-link control traffic - name: ibgp_vlan peer: InfraVLAN + identifier: mlag_domain_ibgp_vlan cardinality: one + direction: outbound optional: true description: VLAN for iBGP peering between MLAG peers -- 2.53.0 From 8114b6d973fcef2bfd1960c35877f0838cdceedc Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 09:09:31 +0000 Subject: [PATCH 14/58] fix(schema): add unique identifiers for VRF RouteTarget relationships Add identifier and direction: outbound for import/export targets in VRF and VRFDeviceAssignment to avoid bidirectional conflicts. Ref: #41 --- schemas/vrf.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/schemas/vrf.yml b/schemas/vrf.yml index 8503dcc..19c64bb 100644 --- a/schemas/vrf.yml +++ b/schemas/vrf.yml @@ -39,11 +39,15 @@ nodes: description: L3 VNI for symmetric IRB - name: import_targets peer: InfraRouteTarget + identifier: vrf_import_targets cardinality: many + direction: outbound optional: true - name: export_targets peer: InfraRouteTarget + identifier: vrf_export_targets cardinality: many + direction: outbound optional: true - name: interfaces peer: InfraInterface @@ -99,11 +103,15 @@ nodes: kind: Parent - name: import_targets peer: InfraRouteTarget + identifier: vrf_assignment_import_targets cardinality: many + direction: outbound optional: true description: Device-specific import RTs - name: export_targets peer: InfraRouteTarget + identifier: vrf_assignment_export_targets cardinality: many + direction: outbound optional: true description: Device-specific export RTs -- 2.53.0 From eb809812af4583ba85a297d024b04efae8425fae Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 09:12:15 +0000 Subject: [PATCH 15/58] fix(schema): add direction outbound for self-referencing relationship InterfaceEthernet.connected_interface is a self-reference that requires direction: outbound to avoid bidirectional conflicts per Infrahub docs. Ref: #41 --- schemas/base.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/schemas/base.yml b/schemas/base.yml index 8bf762f..f48ff72 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -213,6 +213,8 @@ nodes: description: Parent LAG interface - name: connected_interface peer: InfraInterfaceEthernet + identifier: ethernet_connected_to + direction: outbound cardinality: one optional: true description: Connected peer interface -- 2.53.0 From 4e9c2d3009bda45b9ff9f49b3f65924da32d0249 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 13:06:58 +0000 Subject: [PATCH 16/58] fix(schema): replace deprecated default_filter with human_friendly_id in base.yml --- schemas/base.yml | 64 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/schemas/base.yml b/schemas/base.yml index f48ff72..cf6bd83 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -9,6 +9,8 @@ generics: label: Interface include_in_menu: false hierarchical: false + display_labels: + - name__value attributes: - name: name kind: Text @@ -34,15 +36,16 @@ generics: kind: Component nodes: - # ============================================================================= + # ========================================================================== # Location - # ============================================================================= + # ========================================================================== - name: Site namespace: Location description: Physical site or data center label: Site icon: mingcute--building-4-line - default_filter: name__value + human_friendly_id: + - name__value order_by: - name__value display_labels: @@ -59,15 +62,16 @@ nodes: optional: true description: Facility identifier or code - # ============================================================================= + # ========================================================================== # Platform - # ============================================================================= + # ========================================================================== - name: Platform namespace: Infra description: Device platform/OS (e.g., Arista EOS, Cisco NX-OS) label: Platform icon: mdi--chip - default_filter: name__value + human_friendly_id: + - name__value order_by: - name__value display_labels: @@ -89,15 +93,16 @@ nodes: optional: true description: Netmiko device type - # ============================================================================= + # ========================================================================== # Device - # ============================================================================= + # ========================================================================== - name: Device namespace: Infra description: Network device (spine, leaf, etc.) label: Device icon: mdi--server-network - default_filter: name__value + human_friendly_id: + - name__value order_by: - name__value display_labels: @@ -166,9 +171,9 @@ nodes: cardinality: one optional: true - # ============================================================================= + # ========================================================================== # Interface Types (inherit from InfraInterface generic) - # ============================================================================= + # ========================================================================== - name: InterfaceEthernet namespace: Infra description: Physical Ethernet interface @@ -176,7 +181,11 @@ nodes: icon: mdi--ethernet inherit_from: - InfraInterface - default_filter: name__value + uniqueness_constraints: + - ["device", "name__value"] + human_friendly_id: + - device__name__value + - name__value display_labels: - name__value attributes: @@ -226,7 +235,11 @@ nodes: icon: mdi--reload inherit_from: - InfraInterface - default_filter: name__value + uniqueness_constraints: + - ["device", "name__value"] + human_friendly_id: + - device__name__value + - name__value display_labels: - name__value @@ -237,7 +250,11 @@ nodes: icon: mdi--lan inherit_from: - InfraInterface - default_filter: name__value + uniqueness_constraints: + - ["device", "name__value"] + human_friendly_id: + - device__name__value + - name__value display_labels: - name__value relationships: @@ -253,7 +270,11 @@ nodes: icon: mdi--link-variant inherit_from: - InfraInterface - default_filter: name__value + uniqueness_constraints: + - ["device", "name__value"] + human_friendly_id: + - device__name__value + - name__value display_labels: - name__value attributes: @@ -284,7 +305,11 @@ nodes: icon: mdi--tunnel inherit_from: - InfraInterface - default_filter: name__value + uniqueness_constraints: + - ["device", "name__value"] + human_friendly_id: + - device__name__value + - name__value display_labels: - name__value attributes: @@ -297,15 +322,16 @@ nodes: cardinality: one description: VTEP source interface (typically Loopback1) - # ============================================================================= + # ========================================================================== # IP Address - # ============================================================================= + # ========================================================================== - name: IPAddress namespace: Infra description: IP Address assignment label: IP Address icon: mdi--ip-network - default_filter: address__value + human_friendly_id: + - address__value order_by: - address__value display_labels: -- 2.53.0 From c22a5b6ab4e59433f45e6eae8bc4a902976bf70f Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 13:07:24 +0000 Subject: [PATCH 17/58] fix(schema): display_labels must only reference attributes, not relationships --- schemas/bgp.yml | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/schemas/bgp.yml b/schemas/bgp.yml index 32e3b1a..87cd1fc 100644 --- a/schemas/bgp.yml +++ b/schemas/bgp.yml @@ -3,15 +3,16 @@ --- version: "1.0" nodes: - # ============================================================================= + # ========================================================================== # Autonomous System - # ============================================================================= + # ========================================================================== - name: AutonomousSystem namespace: Infra description: BGP Autonomous System label: Autonomous System icon: mdi--cloud-outline - default_filter: asn__value + human_friendly_id: + - asn__value order_by: - asn__value display_labels: @@ -34,16 +35,18 @@ nodes: - name: public label: Public - # ============================================================================= + # ========================================================================== # BGP Router Configuration (per device) - # ============================================================================= + # ========================================================================== - name: BGPRouterConfig namespace: Infra description: BGP router configuration on a device label: BGP Router Config icon: mdi--router-wireless - display_labels: + human_friendly_id: - device__name__value + display_labels: + - router_id__value attributes: - name: router_id kind: IPHost @@ -80,15 +83,16 @@ nodes: cardinality: many kind: Component - # ============================================================================= + # ========================================================================== # BGP Peer Group - # ============================================================================= + # ========================================================================== - name: BGPPeerGroup namespace: Infra description: BGP peer group template label: BGP Peer Group icon: mdi--account-group - default_filter: name__value + human_friendly_id: + - name__value display_labels: - name__value attributes: @@ -151,15 +155,16 @@ nodes: cardinality: one optional: true - # ============================================================================= + # ========================================================================== # BGP Session (Neighbor) - # ============================================================================= + # ========================================================================== - name: BGPSession namespace: Infra description: BGP neighbor session label: BGP Session icon: mdi--connection - default_filter: peer_address__value + human_friendly_id: + - peer_address__value display_labels: - peer_address__value attributes: @@ -192,9 +197,9 @@ nodes: optional: true description: Remote peer device (for documentation) - # ============================================================================= + # ========================================================================== # BGP Address Family Configuration - # ============================================================================= + # ========================================================================== - name: BGPAddressFamily namespace: Infra description: BGP address family configuration -- 2.53.0 From 42d03699d9360b135f51a4ba08c474c888dc8114 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 13:07:44 +0000 Subject: [PATCH 18/58] fix(schema): display_labels must only reference local attributes in extensions.yml --- schemas/extensions.yml | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/schemas/extensions.yml b/schemas/extensions.yml index 07724bd..51d8ecd 100644 --- a/schemas/extensions.yml +++ b/schemas/extensions.yml @@ -3,15 +3,16 @@ --- version: "1.0" nodes: - # ============================================================================= + # ========================================================================== # Fabric (Top-level container for all fabric objects) - # ============================================================================= + # ========================================================================== - name: Fabric namespace: Infra description: EVPN-VXLAN Fabric definition label: Fabric icon: mdi--vector-polygon - default_filter: name__value + human_friendly_id: + - name__value order_by: - name__value display_labels: @@ -57,18 +58,20 @@ nodes: cardinality: many optional: true - # ============================================================================= + # ========================================================================== # Underlay P2P Link - # ============================================================================= + # ========================================================================== - name: UnderlayLink namespace: Infra description: Point-to-point underlay link between devices label: Underlay Link icon: mdi--cable-data display_labels: - - local_device__name__value - - remote_device__name__value + - description__value attributes: + - name: description + kind: Text + description: Link description (e.g., spine1:eth1 <-> leaf1:eth11) - name: local_ip kind: IPNetwork description: Local interface IP with mask @@ -104,15 +107,16 @@ nodes: cardinality: one direction: outbound - # ============================================================================= + # ========================================================================== # Host Connection - # ============================================================================= + # ========================================================================== - name: HostConnection namespace: Infra description: Host connection to fabric (single or dual-homed) label: Host Connection icon: mdi--desktop-tower - default_filter: hostname__value + human_friendly_id: + - hostname__value display_labels: - hostname__value attributes: -- 2.53.0 From 95bd2ee6c8bee71d342637675c17c6f6f4193992 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 13:08:04 +0000 Subject: [PATCH 19/58] fix(schema): display_labels must only reference local attributes in mlag.yml --- schemas/mlag.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/schemas/mlag.yml b/schemas/mlag.yml index 2b5f419..8d73251 100644 --- a/schemas/mlag.yml +++ b/schemas/mlag.yml @@ -3,15 +3,16 @@ --- version: "1.0" nodes: - # ============================================================================= + # ========================================================================== # MLAG Domain - # ============================================================================= + # ========================================================================== - name: MlagDomain namespace: Infra description: MLAG domain configuration for leaf pair label: MLAG Domain icon: mdi--link-variant - default_filter: domain_id__value + human_friendly_id: + - domain_id__value display_labels: - domain_id__value attributes: @@ -64,16 +65,18 @@ nodes: optional: true description: VLAN for iBGP peering between MLAG peers - # ============================================================================= + # ========================================================================== # MLAG Peer Configuration (per device) - # ============================================================================= + # ========================================================================== - name: MlagPeerConfig namespace: Infra description: MLAG configuration on a specific device label: MLAG Peer Config icon: mdi--server-network - display_labels: + human_friendly_id: - device__name__value + display_labels: + - local_interface_ip__value attributes: - name: local_interface_ip kind: IPNetwork @@ -101,9 +104,9 @@ nodes: cardinality: one description: Peer-link port-channel - # ============================================================================= + # ========================================================================== # MLAG Interface (MLAG-enabled LAG) - # ============================================================================= + # ========================================================================== - name: MlagInterface namespace: Infra description: MLAG interface configuration -- 2.53.0 From 2ca08a4f4151f873f9459ecda4f0e904a01dff39 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 13:08:30 +0000 Subject: [PATCH 20/58] fix(schema): display_labels must only reference local attributes in vlan_vxlan.yml --- schemas/vlan_vxlan.yml | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/schemas/vlan_vxlan.yml b/schemas/vlan_vxlan.yml index 765a8a7..6cddb4d 100644 --- a/schemas/vlan_vxlan.yml +++ b/schemas/vlan_vxlan.yml @@ -3,15 +3,16 @@ --- version: "1.0" nodes: - # ============================================================================= + # ========================================================================== # VLAN - # ============================================================================= + # ========================================================================== - name: VLAN namespace: Infra description: Virtual LAN configuration label: VLAN icon: mdi--lan-connect - default_filter: vlan_id__value + human_friendly_id: + - vlan_id__value order_by: - vlan_id__value display_labels: @@ -62,15 +63,16 @@ nodes: cardinality: one optional: true - # ============================================================================= + # ========================================================================== # VNI (VXLAN Network Identifier) - # ============================================================================= + # ========================================================================== - name: VNI namespace: Infra description: VXLAN Network Identifier label: VNI icon: mdi--tunnel-outline - default_filter: vni__value + human_friendly_id: + - vni__value order_by: - vni__value display_labels: @@ -106,17 +108,18 @@ nodes: optional: true description: Associated VRF for L3VNI - # ============================================================================= + # ========================================================================== # VTEP (VXLAN Tunnel Endpoint) - # ============================================================================= + # ========================================================================== - name: VTEP namespace: Infra description: VXLAN Tunnel Endpoint configuration label: VTEP icon: mdi--server-network-outline - default_filter: source_address__value - display_labels: + human_friendly_id: - device__name__value + display_labels: + - source_address__value attributes: - name: source_address kind: IPHost @@ -147,17 +150,21 @@ nodes: cardinality: many kind: Component - # ============================================================================= + # ========================================================================== # VLAN to VNI Mapping (per-device) - # ============================================================================= + # ========================================================================== - name: VlanVniMapping namespace: Infra description: VLAN to VNI mapping on a VTEP label: VLAN-VNI Mapping icon: mdi--swap-horizontal display_labels: - - vlan__vlan_id__value - - vni__vni__value + - description__value + attributes: + - name: description + kind: Text + optional: true + description: "Mapping description (e.g., VLAN 40 <-> VNI 10040)" relationships: - name: vtep peer: InfraVTEP @@ -170,17 +177,16 @@ nodes: peer: InfraVNI cardinality: one - # ============================================================================= + # ========================================================================== # EVPN Instance (per VLAN) - # ============================================================================= + # ========================================================================== - name: EVPNInstance namespace: Infra description: EVPN instance configuration (route targets for L2 extension) label: EVPN Instance icon: mdi--cloud-sync - default_filter: vlan__vlan_id__value display_labels: - - vlan__vlan_id__value + - route_distinguisher__value attributes: - name: route_distinguisher kind: Text -- 2.53.0 From 52c335aeb00defe7adb9a2c0084b913b1d44c8fa Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 13:08:59 +0000 Subject: [PATCH 21/58] fix(schema): display_labels must only reference local attributes in vrf.yml --- schemas/vrf.yml | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/schemas/vrf.yml b/schemas/vrf.yml index 19c64bb..1010596 100644 --- a/schemas/vrf.yml +++ b/schemas/vrf.yml @@ -3,15 +3,16 @@ --- version: "1.0" nodes: - # ============================================================================= + # ========================================================================== # VRF (Virtual Routing and Forwarding) - # ============================================================================= + # ========================================================================== - name: VRF namespace: Infra description: Virtual Routing and Forwarding instance label: VRF icon: mdi--router - default_filter: name__value + human_friendly_id: + - name__value order_by: - name__value display_labels: @@ -55,15 +56,16 @@ nodes: optional: true description: Interfaces assigned to this VRF - # ============================================================================= + # ========================================================================== # Route Target - # ============================================================================= + # ========================================================================== - name: RouteTarget namespace: Infra description: BGP Route Target for VPN import/export label: Route Target icon: mdi--target - default_filter: target__value + human_friendly_id: + - target__value order_by: - target__value display_labels: @@ -77,17 +79,19 @@ nodes: kind: Text optional: true - # ============================================================================= + # ========================================================================== # VRF Device Assignment - # ============================================================================= + # ========================================================================== - name: VRFDeviceAssignment namespace: Infra description: VRF assignment to a specific device label: VRF Assignment icon: mdi--router-network - display_labels: - - vrf__name__value + human_friendly_id: - device__name__value + - vrf__name__value + display_labels: + - route_distinguisher__value attributes: - name: route_distinguisher kind: Text -- 2.53.0 From 4aadf763a34ca0da2a22206cba696c157d92032f Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 13:11:52 +0000 Subject: [PATCH 22/58] fix(schema): add optional: false on device relationship for uniqueness_constraints --- schemas/base.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/schemas/base.yml b/schemas/base.yml index cf6bd83..0c220c0 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -30,6 +30,7 @@ generics: peer: InfraDevice cardinality: one kind: Parent + optional: false - name: ip_addresses peer: InfraIPAddress cardinality: many -- 2.53.0 From ef6877551f47987ba860a5ecd24be6dac913e621 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 15:07:01 +0000 Subject: [PATCH 23/58] fix(schema): IPAddress.interface - replace Parent with Attribute kind Parent relationships cannot be optional in Infrahub. Since an IP address can exist without being assigned to an interface (reserved, planned), we use kind: Attribute instead of kind: Parent. Also change InfraInterface.ip_addresses from Component to Generic since Component requires a matching Parent on the other side. Both sides now use explicit identifier: interface__ip_addresses for proper bidirectional linking. --- schemas/base.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/schemas/base.yml b/schemas/base.yml index 0c220c0..9494c4e 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -33,8 +33,9 @@ generics: optional: false - name: ip_addresses peer: InfraIPAddress + identifier: interface__ip_addresses cardinality: many - kind: Component + kind: Generic nodes: # ========================================================================== @@ -360,6 +361,7 @@ nodes: relationships: - name: interface peer: InfraInterface + identifier: interface__ip_addresses cardinality: one optional: true - kind: Parent + kind: Attribute -- 2.53.0 From adb02fc25c9031b6407910d79c869d0eab23abfe Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 15:08:57 +0000 Subject: [PATCH 24/58] fix(schema): add explicit optional: false to all Parent relationships in bgp.yml --- schemas/bgp.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/schemas/bgp.yml b/schemas/bgp.yml index 87cd1fc..2e7b5e4 100644 --- a/schemas/bgp.yml +++ b/schemas/bgp.yml @@ -71,6 +71,7 @@ nodes: peer: InfraDevice cardinality: one kind: Parent + optional: false - name: local_asn peer: InfraAutonomousSystem cardinality: one @@ -150,6 +151,7 @@ nodes: peer: InfraBGPRouterConfig cardinality: one kind: Parent + optional: false - name: remote_asn peer: InfraAutonomousSystem cardinality: one @@ -182,6 +184,7 @@ nodes: peer: InfraBGPRouterConfig cardinality: one kind: Parent + optional: false - name: peer_group peer: InfraBGPPeerGroup cardinality: one @@ -233,6 +236,7 @@ nodes: peer: InfraBGPRouterConfig cardinality: one kind: Parent + optional: false - name: active_peer_groups peer: InfraBGPPeerGroup cardinality: many -- 2.53.0 From 67a54e349db8cddcb39bae9beac5a948ac9de72c Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 15:09:25 +0000 Subject: [PATCH 25/58] fix(schema): add explicit optional: false to Parent relationships in mlag.yml --- schemas/mlag.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/schemas/mlag.yml b/schemas/mlag.yml index 8d73251..c549b81 100644 --- a/schemas/mlag.yml +++ b/schemas/mlag.yml @@ -92,6 +92,7 @@ nodes: peer: InfraDevice cardinality: one kind: Parent + optional: false - name: mlag_domain peer: InfraMlagDomain cardinality: one -- 2.53.0 From a12e24d00c8c4b116847587af302a08e426fe744 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 15:10:00 +0000 Subject: [PATCH 26/58] fix(schema): add explicit optional: false to all Parent relationships in vlan_vxlan.yml --- schemas/vlan_vxlan.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/schemas/vlan_vxlan.yml b/schemas/vlan_vxlan.yml index 6cddb4d..feef0c1 100644 --- a/schemas/vlan_vxlan.yml +++ b/schemas/vlan_vxlan.yml @@ -141,6 +141,7 @@ nodes: peer: InfraDevice cardinality: one kind: Parent + optional: false - name: source_interface peer: InfraInterfaceLoopback cardinality: one @@ -170,6 +171,7 @@ nodes: peer: InfraVTEP cardinality: one kind: Parent + optional: false - name: vlan peer: InfraVLAN cardinality: one @@ -208,3 +210,4 @@ nodes: peer: InfraDevice cardinality: one kind: Parent + optional: false -- 2.53.0 From 0c0ab1b214c937029c7bc9cd6478496b0a3cfcdd Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 15:10:16 +0000 Subject: [PATCH 27/58] fix(schema): add explicit optional: false to Parent relationships in vrf.yml --- schemas/vrf.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/schemas/vrf.yml b/schemas/vrf.yml index 1010596..802429e 100644 --- a/schemas/vrf.yml +++ b/schemas/vrf.yml @@ -105,6 +105,7 @@ nodes: peer: InfraDevice cardinality: one kind: Parent + optional: false - name: import_targets peer: InfraRouteTarget identifier: vrf_assignment_import_targets -- 2.53.0 From d7e2d9f0e06be48a42dccb024f03ee5256bd5f7f Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 19:19:55 +0000 Subject: [PATCH 28/58] fix(schema): add optional: false on UnderlayLink.fabric parent relationship --- schemas/extensions.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/schemas/extensions.yml b/schemas/extensions.yml index 51d8ecd..ef67628 100644 --- a/schemas/extensions.yml +++ b/schemas/extensions.yml @@ -86,6 +86,7 @@ nodes: peer: InfraFabric cardinality: one kind: Parent + optional: false - name: local_device peer: InfraDevice identifier: underlay_link_local_device -- 2.53.0 From 0e96e8aca8f322557627392fee4c6beb84850d64 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 19:20:56 +0000 Subject: [PATCH 29/58] fix(schema): add explicit optional: false on VRFDeviceAssignment.vrf for human_friendly_id --- schemas/vrf.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/schemas/vrf.yml b/schemas/vrf.yml index 802429e..25360d0 100644 --- a/schemas/vrf.yml +++ b/schemas/vrf.yml @@ -101,6 +101,7 @@ nodes: - name: vrf peer: InfraVRF cardinality: one + optional: false - name: device peer: InfraDevice cardinality: one -- 2.53.0 From 99f34b9639bc0eadfe27bd5158b3ecc77f26a323 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 6 Feb 2026 19:39:28 +0000 Subject: [PATCH 30/58] fix(schema): add unique: true on VRF.name for HFID peer traversal --- schemas/vrf.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/schemas/vrf.yml b/schemas/vrf.yml index 25360d0..1d83ac2 100644 --- a/schemas/vrf.yml +++ b/schemas/vrf.yml @@ -20,6 +20,7 @@ nodes: attributes: - name: name kind: Text + unique: true description: VRF name - name: description kind: Text -- 2.53.0 From a917715a47406716445b7c5b48aeea4c31dda73b Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Sat, 7 Feb 2026 09:03:11 +0000 Subject: [PATCH 31/58] refactor(schema): replace deprecated display_labels with display_label across all nodes --- schemas/base.yml | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/schemas/base.yml b/schemas/base.yml index 9494c4e..9455494 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -9,8 +9,7 @@ generics: label: Interface include_in_menu: false hierarchical: false - display_labels: - - name__value + display_label: "name__value" attributes: - name: name kind: Text @@ -50,8 +49,7 @@ nodes: - name__value order_by: - name__value - display_labels: - - name__value + display_label: "name__value" attributes: - name: name kind: Text @@ -76,8 +74,7 @@ nodes: - name__value order_by: - name__value - display_labels: - - name__value + display_label: "name__value" attributes: - name: name kind: Text @@ -107,8 +104,7 @@ nodes: - name__value order_by: - name__value - display_labels: - - name__value + display_label: "name__value" attributes: - name: name kind: Text @@ -188,8 +184,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_labels: - - name__value + display_label: "name__value" attributes: - name: speed kind: Dropdown @@ -242,8 +237,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_labels: - - name__value + display_label: "name__value" - name: InterfaceVlan namespace: Infra @@ -257,8 +251,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_labels: - - name__value + display_label: "name__value" relationships: - name: vlan peer: InfraVLAN @@ -277,8 +270,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_labels: - - name__value + display_label: "name__value" attributes: - name: lacp_mode kind: Dropdown @@ -312,8 +304,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_labels: - - name__value + display_label: "name__value" attributes: - name: udp_port kind: Number @@ -336,8 +327,7 @@ nodes: - address__value order_by: - address__value - display_labels: - - address__value + display_label: "address__value" attributes: - name: address kind: IPNetwork -- 2.53.0 From bb76b9349942aa1d8b236cca68794bf540d4280f Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Sat, 7 Feb 2026 09:03:36 +0000 Subject: [PATCH 32/58] refactor(schema): replace deprecated display_labels with display_label --- schemas/bgp.yml | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/schemas/bgp.yml b/schemas/bgp.yml index 2e7b5e4..741bdeb 100644 --- a/schemas/bgp.yml +++ b/schemas/bgp.yml @@ -15,9 +15,7 @@ nodes: - asn__value order_by: - asn__value - display_labels: - - asn__value - - description__value + display_label: "asn__value" attributes: - name: asn kind: Number @@ -45,8 +43,7 @@ nodes: icon: mdi--router-wireless human_friendly_id: - device__name__value - display_labels: - - router_id__value + display_label: "router_id__value" attributes: - name: router_id kind: IPHost @@ -94,8 +91,7 @@ nodes: icon: mdi--account-group human_friendly_id: - name__value - display_labels: - - name__value + display_label: "name__value" attributes: - name: name kind: Text @@ -167,8 +163,7 @@ nodes: icon: mdi--connection human_friendly_id: - peer_address__value - display_labels: - - peer_address__value + display_label: "peer_address__value" attributes: - name: peer_address kind: IPHost @@ -208,9 +203,7 @@ nodes: description: BGP address family configuration label: BGP Address Family icon: mdi--format-list-bulleted - display_labels: - - afi__value - - safi__value + display_label: "afi__value" attributes: - name: afi kind: Dropdown -- 2.53.0 From 97080473f72e03aa2ce0e9596bc4539e6828c807 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Sat, 7 Feb 2026 09:16:40 +0000 Subject: [PATCH 33/58] fix: migrate display_labels to display_label Jinja2 format in base schema Replaces deprecated display_labels list format and bare display_label strings with the new Jinja2 template format as required by Infrahub. Refs #41 --- schemas/base.yml | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/schemas/base.yml b/schemas/base.yml index 9455494..3debdeb 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -9,7 +9,7 @@ generics: label: Interface include_in_menu: false hierarchical: false - display_label: "name__value" + display_label: "{{ name__value }}" attributes: - name: name kind: Text @@ -37,9 +37,9 @@ generics: kind: Generic nodes: - # ========================================================================== + # =================================================================== # Location - # ========================================================================== + # =================================================================== - name: Site namespace: Location description: Physical site or data center @@ -49,7 +49,7 @@ nodes: - name__value order_by: - name__value - display_label: "name__value" + display_label: "{{ name__value }}" attributes: - name: name kind: Text @@ -62,9 +62,9 @@ nodes: optional: true description: Facility identifier or code - # ========================================================================== + # =================================================================== # Platform - # ========================================================================== + # =================================================================== - name: Platform namespace: Infra description: Device platform/OS (e.g., Arista EOS, Cisco NX-OS) @@ -74,7 +74,7 @@ nodes: - name__value order_by: - name__value - display_label: "name__value" + display_label: "{{ name__value }}" attributes: - name: name kind: Text @@ -92,9 +92,9 @@ nodes: optional: true description: Netmiko device type - # ========================================================================== + # =================================================================== # Device - # ========================================================================== + # =================================================================== - name: Device namespace: Infra description: Network device (spine, leaf, etc.) @@ -104,7 +104,7 @@ nodes: - name__value order_by: - name__value - display_label: "name__value" + display_label: "{{ name__value }}" attributes: - name: name kind: Text @@ -169,9 +169,9 @@ nodes: cardinality: one optional: true - # ========================================================================== + # =================================================================== # Interface Types (inherit from InfraInterface generic) - # ========================================================================== + # =================================================================== - name: InterfaceEthernet namespace: Infra description: Physical Ethernet interface @@ -184,7 +184,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_label: "name__value" + display_label: "{{ name__value }}" attributes: - name: speed kind: Dropdown @@ -237,7 +237,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_label: "name__value" + display_label: "{{ name__value }}" - name: InterfaceVlan namespace: Infra @@ -251,7 +251,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_label: "name__value" + display_label: "{{ name__value }}" relationships: - name: vlan peer: InfraVLAN @@ -270,7 +270,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_label: "name__value" + display_label: "{{ name__value }}" attributes: - name: lacp_mode kind: Dropdown @@ -304,7 +304,7 @@ nodes: human_friendly_id: - device__name__value - name__value - display_label: "name__value" + display_label: "{{ name__value }}" attributes: - name: udp_port kind: Number @@ -315,9 +315,9 @@ nodes: cardinality: one description: VTEP source interface (typically Loopback1) - # ========================================================================== + # =================================================================== # IP Address - # ========================================================================== + # =================================================================== - name: IPAddress namespace: Infra description: IP Address assignment @@ -327,7 +327,7 @@ nodes: - address__value order_by: - address__value - display_label: "address__value" + display_label: "{{ address__value }}" attributes: - name: address kind: IPNetwork -- 2.53.0 From cda3804c2c5944573728a70623ef5631ea3be355 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Sat, 7 Feb 2026 09:17:07 +0000 Subject: [PATCH 34/58] fix: migrate display_labels to display_label Jinja2 format in BGP schema Refs #41 --- schemas/bgp.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/schemas/bgp.yml b/schemas/bgp.yml index 741bdeb..8946b84 100644 --- a/schemas/bgp.yml +++ b/schemas/bgp.yml @@ -3,9 +3,9 @@ --- version: "1.0" nodes: - # ========================================================================== + # =================================================================== # Autonomous System - # ========================================================================== + # =================================================================== - name: AutonomousSystem namespace: Infra description: BGP Autonomous System @@ -15,7 +15,7 @@ nodes: - asn__value order_by: - asn__value - display_label: "asn__value" + display_label: "{{ asn__value }}" attributes: - name: asn kind: Number @@ -33,9 +33,9 @@ nodes: - name: public label: Public - # ========================================================================== + # =================================================================== # BGP Router Configuration (per device) - # ========================================================================== + # =================================================================== - name: BGPRouterConfig namespace: Infra description: BGP router configuration on a device @@ -43,7 +43,7 @@ nodes: icon: mdi--router-wireless human_friendly_id: - device__name__value - display_label: "router_id__value" + display_label: "{{ router_id__value }}" attributes: - name: router_id kind: IPHost @@ -81,9 +81,9 @@ nodes: cardinality: many kind: Component - # ========================================================================== + # =================================================================== # BGP Peer Group - # ========================================================================== + # =================================================================== - name: BGPPeerGroup namespace: Infra description: BGP peer group template @@ -91,7 +91,7 @@ nodes: icon: mdi--account-group human_friendly_id: - name__value - display_label: "name__value" + display_label: "{{ name__value }}" attributes: - name: name kind: Text @@ -153,9 +153,9 @@ nodes: cardinality: one optional: true - # ========================================================================== + # =================================================================== # BGP Session (Neighbor) - # ========================================================================== + # =================================================================== - name: BGPSession namespace: Infra description: BGP neighbor session @@ -163,7 +163,7 @@ nodes: icon: mdi--connection human_friendly_id: - peer_address__value - display_label: "peer_address__value" + display_label: "{{ peer_address__value }}" attributes: - name: peer_address kind: IPHost @@ -195,15 +195,15 @@ nodes: optional: true description: Remote peer device (for documentation) - # ========================================================================== + # =================================================================== # BGP Address Family Configuration - # ========================================================================== + # =================================================================== - name: BGPAddressFamily namespace: Infra description: BGP address family configuration label: BGP Address Family icon: mdi--format-list-bulleted - display_label: "afi__value" + display_label: "{{ afi__value }}" attributes: - name: afi kind: Dropdown -- 2.53.0 From 498fa8505eda146172546c4ecdee9a323b063293 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Sat, 7 Feb 2026 09:17:26 +0000 Subject: [PATCH 35/58] fix: migrate display_labels to display_label Jinja2 format in extensions schema Refs #41 --- schemas/extensions.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/schemas/extensions.yml b/schemas/extensions.yml index ef67628..4120ee5 100644 --- a/schemas/extensions.yml +++ b/schemas/extensions.yml @@ -3,9 +3,9 @@ --- version: "1.0" nodes: - # ========================================================================== + # =================================================================== # Fabric (Top-level container for all fabric objects) - # ========================================================================== + # =================================================================== - name: Fabric namespace: Infra description: EVPN-VXLAN Fabric definition @@ -15,8 +15,7 @@ nodes: - name__value order_by: - name__value - display_labels: - - name__value + display_label: "{{ name__value }}" attributes: - name: name kind: Text @@ -58,16 +57,15 @@ nodes: cardinality: many optional: true - # ========================================================================== + # =================================================================== # Underlay P2P Link - # ========================================================================== + # =================================================================== - name: UnderlayLink namespace: Infra description: Point-to-point underlay link between devices label: Underlay Link icon: mdi--cable-data - display_labels: - - description__value + display_label: "{{ description__value }}" attributes: - name: description kind: Text @@ -108,9 +106,9 @@ nodes: cardinality: one direction: outbound - # ========================================================================== + # =================================================================== # Host Connection - # ========================================================================== + # =================================================================== - name: HostConnection namespace: Infra description: Host connection to fabric (single or dual-homed) @@ -118,8 +116,7 @@ nodes: icon: mdi--desktop-tower human_friendly_id: - hostname__value - display_labels: - - hostname__value + display_label: "{{ hostname__value }}" attributes: - name: hostname kind: Text -- 2.53.0 From d9b47461d38387f8e090f46453faea9204d6921f Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Sat, 7 Feb 2026 09:17:46 +0000 Subject: [PATCH 36/58] fix: migrate display_labels to display_label Jinja2 format in MLAG schema Refs #41 --- schemas/mlag.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/schemas/mlag.yml b/schemas/mlag.yml index c549b81..e42be15 100644 --- a/schemas/mlag.yml +++ b/schemas/mlag.yml @@ -3,9 +3,9 @@ --- version: "1.0" nodes: - # ========================================================================== + # =================================================================== # MLAG Domain - # ========================================================================== + # =================================================================== - name: MlagDomain namespace: Infra description: MLAG domain configuration for leaf pair @@ -13,8 +13,7 @@ nodes: icon: mdi--link-variant human_friendly_id: - domain_id__value - display_labels: - - domain_id__value + display_label: "{{ domain_id__value }}" attributes: - name: domain_id kind: Text @@ -65,9 +64,9 @@ nodes: optional: true description: VLAN for iBGP peering between MLAG peers - # ========================================================================== + # =================================================================== # MLAG Peer Configuration (per device) - # ========================================================================== + # =================================================================== - name: MlagPeerConfig namespace: Infra description: MLAG configuration on a specific device @@ -75,8 +74,7 @@ nodes: icon: mdi--server-network human_friendly_id: - device__name__value - display_labels: - - local_interface_ip__value + display_label: "{{ local_interface_ip__value }}" attributes: - name: local_interface_ip kind: IPNetwork @@ -105,16 +103,15 @@ nodes: cardinality: one description: Peer-link port-channel - # ========================================================================== + # =================================================================== # MLAG Interface (MLAG-enabled LAG) - # ========================================================================== + # =================================================================== - name: MlagInterface namespace: Infra description: MLAG interface configuration label: MLAG Interface icon: mdi--ethernet-cable - display_labels: - - mlag_id__value + display_label: "{{ mlag_id__value }}" attributes: - name: mlag_id kind: Number -- 2.53.0 From b9b15f3beb7436b9584380150efe5807aa666033 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Sat, 7 Feb 2026 09:18:11 +0000 Subject: [PATCH 37/58] fix: migrate display_labels to display_label Jinja2 format in VLAN/VXLAN schema Refs #41 --- schemas/vlan_vxlan.yml | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/schemas/vlan_vxlan.yml b/schemas/vlan_vxlan.yml index feef0c1..dc81548 100644 --- a/schemas/vlan_vxlan.yml +++ b/schemas/vlan_vxlan.yml @@ -3,9 +3,9 @@ --- version: "1.0" nodes: - # ========================================================================== + # =================================================================== # VLAN - # ========================================================================== + # =================================================================== - name: VLAN namespace: Infra description: Virtual LAN configuration @@ -15,9 +15,7 @@ nodes: - vlan_id__value order_by: - vlan_id__value - display_labels: - - vlan_id__value - - name__value + display_label: "{{ vlan_id__value }} ({{ name__value }})" attributes: - name: vlan_id kind: Number @@ -63,9 +61,9 @@ nodes: cardinality: one optional: true - # ========================================================================== + # =================================================================== # VNI (VXLAN Network Identifier) - # ========================================================================== + # =================================================================== - name: VNI namespace: Infra description: VXLAN Network Identifier @@ -75,8 +73,7 @@ nodes: - vni__value order_by: - vni__value - display_labels: - - vni__value + display_label: "{{ vni__value }}" attributes: - name: vni kind: Number @@ -108,9 +105,9 @@ nodes: optional: true description: Associated VRF for L3VNI - # ========================================================================== + # =================================================================== # VTEP (VXLAN Tunnel Endpoint) - # ========================================================================== + # =================================================================== - name: VTEP namespace: Infra description: VXLAN Tunnel Endpoint configuration @@ -118,8 +115,7 @@ nodes: icon: mdi--server-network-outline human_friendly_id: - device__name__value - display_labels: - - source_address__value + display_label: "{{ source_address__value }}" attributes: - name: source_address kind: IPHost @@ -151,16 +147,15 @@ nodes: cardinality: many kind: Component - # ========================================================================== + # =================================================================== # VLAN to VNI Mapping (per-device) - # ========================================================================== + # =================================================================== - name: VlanVniMapping namespace: Infra description: VLAN to VNI mapping on a VTEP label: VLAN-VNI Mapping icon: mdi--swap-horizontal - display_labels: - - description__value + display_label: "{{ description__value }}" attributes: - name: description kind: Text @@ -179,16 +174,15 @@ nodes: peer: InfraVNI cardinality: one - # ========================================================================== + # =================================================================== # EVPN Instance (per VLAN) - # ========================================================================== + # =================================================================== - name: EVPNInstance namespace: Infra description: EVPN instance configuration (route targets for L2 extension) label: EVPN Instance icon: mdi--cloud-sync - display_labels: - - route_distinguisher__value + display_label: "{{ route_distinguisher__value }}" attributes: - name: route_distinguisher kind: Text -- 2.53.0 From 25550bb3c42c426efbdcc8862e6d8b1aa3e54b1e Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Sat, 7 Feb 2026 09:18:38 +0000 Subject: [PATCH 38/58] fix: migrate display_labels to display_label Jinja2 format in VRF schema Also enriched VRFDeviceAssignment display_label to show device + VRF. Refs #41 --- schemas/vrf.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/schemas/vrf.yml b/schemas/vrf.yml index 1d83ac2..18f1483 100644 --- a/schemas/vrf.yml +++ b/schemas/vrf.yml @@ -3,9 +3,9 @@ --- version: "1.0" nodes: - # ========================================================================== + # =================================================================== # VRF (Virtual Routing and Forwarding) - # ========================================================================== + # =================================================================== - name: VRF namespace: Infra description: Virtual Routing and Forwarding instance @@ -15,8 +15,7 @@ nodes: - name__value order_by: - name__value - display_labels: - - name__value + display_label: "{{ name__value }}" attributes: - name: name kind: Text @@ -57,9 +56,9 @@ nodes: optional: true description: Interfaces assigned to this VRF - # ========================================================================== + # =================================================================== # Route Target - # ========================================================================== + # =================================================================== - name: RouteTarget namespace: Infra description: BGP Route Target for VPN import/export @@ -69,8 +68,7 @@ nodes: - target__value order_by: - target__value - display_labels: - - target__value + display_label: "{{ target__value }}" attributes: - name: target kind: Text @@ -80,9 +78,9 @@ nodes: kind: Text optional: true - # ========================================================================== + # =================================================================== # VRF Device Assignment - # ========================================================================== + # =================================================================== - name: VRFDeviceAssignment namespace: Infra description: VRF assignment to a specific device @@ -91,8 +89,7 @@ nodes: human_friendly_id: - device__name__value - vrf__name__value - display_labels: - - route_distinguisher__value + display_label: "{{ device__name__value }} - {{ vrf__name__value }}" attributes: - name: route_distinguisher kind: Text -- 2.53.0 From 78263e8bf530fe369e4f1a68a5f1832a08a13113 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Mon, 9 Feb 2026 12:02:18 +0000 Subject: [PATCH 39/58] feat(menu): add custom Infrahub menu for EVPN-VXLAN fabric #41 Organize 22+ schema nodes into logical categories: - Fabric Topology (Fabric, Site, Device, Platform, Underlay Links) - Interfaces (Ethernet, Loopback, VLAN SVI, LAG, VXLAN) - IP Addressing - Layer 2 / VXLAN (VLAN, VNI, VTEP, Mappings, EVPN) - Routing / BGP (AS, Router Config, Peer Groups, Sessions, AFI) - VRF (VRF, Route Targets, Assignments) - MLAG (Domain, Peer Config, Interface) - Host Connectivity --- menus/fabric-menu.yml | 247 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 menus/fabric-menu.yml diff --git a/menus/fabric-menu.yml b/menus/fabric-menu.yml new file mode 100644 index 0000000..a6cfc95 --- /dev/null +++ b/menus/fabric-menu.yml @@ -0,0 +1,247 @@ +# yaml-language-server: $schema=https://schema.infrahub.app/infrahub/menu/latest.json +# Custom menu for EVPN-VXLAN Fabric Orchestrator +# Organizes schema nodes into logical topology-aligned categories +--- +apiversion: infrahub.app/v1 +kind: Menu +spec: + data: + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + # Fabric Topology + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + - namespace: Topology + name: Mainmenu + label: Fabric Topology + icon: "mdi:lan" + children: + data: + - namespace: Topology + name: Fabric + label: Fabrics + kind: InfraFabric + icon: "mdi:vector-polygon" + + - namespace: Topology + name: Site + label: Sites + kind: LocationSite + icon: "mingcute:building-4-line" + + - namespace: Topology + name: Device + label: Devices + kind: InfraDevice + icon: "mdi:server-network" + + - namespace: Topology + name: Platform + label: Platforms + kind: InfraPlatform + icon: "mdi:chip" + + - namespace: Topology + name: UnderlayLink + label: Underlay Links + kind: InfraUnderlayLink + icon: "mdi:cable-data" + + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + # Interfaces + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + - namespace: Interfaces + name: Mainmenu + label: Interfaces + icon: "mdi:ethernet" + children: + data: + - namespace: Interfaces + name: Ethernet + label: Ethernet + kind: InfraInterfaceEthernet + icon: "mdi:ethernet" + + - namespace: Interfaces + name: Loopback + label: Loopback + kind: InfraInterfaceLoopback + icon: "mdi:reload" + + - namespace: Interfaces + name: VlanSvi + label: VLAN SVI + kind: InfraInterfaceVlan + icon: "mdi:lan" + + - namespace: Interfaces + name: Lag + label: LAG / Port-Channel + kind: InfraInterfaceLag + icon: "mdi:link-variant" + + - namespace: Interfaces + name: Vxlan + label: VXLAN Tunnel + kind: InfraInterfaceVxlan + icon: "mdi:tunnel" + + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + # IP Addressing + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + - namespace: Addressing + name: Mainmenu + label: IP Addressing + icon: "mdi:ip-network" + children: + data: + - namespace: Addressing + name: IPAddress + label: IP Addresses + kind: InfraIPAddress + icon: "mdi:ip-network" + + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + # Layer 2 / VXLAN + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + - namespace: Layer2 + name: Mainmenu + label: Layer 2 / VXLAN + icon: "mdi:switch" + children: + data: + - namespace: Layer2 + name: Vlan + label: VLANs + kind: InfraVLAN + icon: "mdi:lan-connect" + + - namespace: Layer2 + name: Vni + label: VNIs + kind: InfraVNI + icon: "mdi:tunnel-outline" + + - namespace: Layer2 + name: Vtep + label: VTEPs + kind: InfraVTEP + icon: "mdi:server-network-outline" + + - namespace: Layer2 + name: VlanVniMapping + label: VLAN-VNI Mappings + kind: InfraVlanVniMapping + icon: "mdi:swap-horizontal" + + - namespace: Layer2 + name: EvpnInstance + label: EVPN Instances + kind: InfraEVPNInstance + icon: "mdi:cloud-sync" + + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + # Routing / BGP + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + - namespace: Routing + name: Mainmenu + label: Routing / BGP + icon: "mdi:routes" + children: + data: + - namespace: Routing + name: AutonomousSystem + label: Autonomous Systems + kind: InfraAutonomousSystem + icon: "mdi:cloud-outline" + + - namespace: Routing + name: BGPRouterConfig + label: BGP Router Config + kind: InfraBGPRouterConfig + icon: "mdi:router-wireless" + + - namespace: Routing + name: BGPPeerGroup + label: BGP Peer Groups + kind: InfraBGPPeerGroup + icon: "mdi:account-group" + + - namespace: Routing + name: BGPSession + label: BGP Sessions + kind: InfraBGPSession + icon: "mdi:connection" + + - namespace: Routing + name: BGPAddressFamily + label: BGP Address Families + kind: InfraBGPAddressFamily + icon: "mdi:format-list-bulleted" + + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + # VRF + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + - namespace: VRF + name: Mainmenu + label: VRF + icon: "mdi:router" + children: + data: + - namespace: VRF + name: Vrf + label: VRFs + kind: InfraVRF + icon: "mdi:router" + + - namespace: VRF + name: RouteTarget + label: Route Targets + kind: InfraRouteTarget + icon: "mdi:target" + + - namespace: VRF + name: VrfAssignment + label: VRF Assignments + kind: InfraVRFDeviceAssignment + icon: "mdi:router-network" + + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + # MLAG + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + - namespace: MLAG + name: Mainmenu + label: MLAG + icon: "mdi:link-variant" + children: + data: + - namespace: MLAG + name: MlagDomain + label: MLAG Domains + kind: InfraMlagDomain + icon: "mdi:link-variant" + + - namespace: MLAG + name: MlagPeerConfig + label: MLAG Peer Config + kind: InfraMlagPeerConfig + icon: "mdi:server-network" + + - namespace: MLAG + name: MlagInterface + label: MLAG Interfaces + kind: InfraMlagInterface + icon: "mdi:ethernet-cable" + + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + # Host Connectivity + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + - namespace: Connectivity + name: Mainmenu + label: Host Connectivity + icon: "mdi:desktop-tower" + children: + data: + - namespace: Connectivity + name: HostConnection + label: Host Connections + kind: InfraHostConnection + icon: "mdi:desktop-tower" -- 2.53.0 From 40fdf504c93b83cedcbc9ad0ba3c940c5bd7f065 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Mon, 9 Feb 2026 12:02:29 +0000 Subject: [PATCH 40/58] feat(config): add menu reference to .infrahub.yml #41 --- .infrahub.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.infrahub.yml b/.infrahub.yml index 38dd224..60b2cb5 100644 --- a/.infrahub.yml +++ b/.infrahub.yml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=https://schema.infrahub.app/python-sdk/repository-config/latest.json --- schemas: - - schemas \ No newline at end of file + - schemas/ + +menus: + - menus/fabric-menu.yml -- 2.53.0 From 69f003b7983de1a2ac1f5806f39fca053fff4c58 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Mon, 9 Feb 2026 12:03:09 +0000 Subject: [PATCH 41/58] feat(schema): add include_in_menu: false to all base nodes #41 Menu is now controlled by custom menus/fabric-menu.yml --- schemas/base.yml | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/schemas/base.yml b/schemas/base.yml index 3debdeb..b1a286c 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -37,14 +37,15 @@ generics: kind: Generic nodes: - # =================================================================== + # ================================================================ # Location - # =================================================================== + # ================================================================ - name: Site namespace: Location description: Physical site or data center label: Site icon: mingcute--building-4-line + include_in_menu: false human_friendly_id: - name__value order_by: @@ -62,14 +63,15 @@ nodes: optional: true description: Facility identifier or code - # =================================================================== + # ================================================================ # Platform - # =================================================================== + # ================================================================ - name: Platform namespace: Infra description: Device platform/OS (e.g., Arista EOS, Cisco NX-OS) label: Platform icon: mdi--chip + include_in_menu: false human_friendly_id: - name__value order_by: @@ -92,14 +94,15 @@ nodes: optional: true description: Netmiko device type - # =================================================================== + # ================================================================ # Device - # =================================================================== + # ================================================================ - name: Device namespace: Infra description: Network device (spine, leaf, etc.) label: Device icon: mdi--server-network + include_in_menu: false human_friendly_id: - name__value order_by: @@ -169,14 +172,15 @@ nodes: cardinality: one optional: true - # =================================================================== + # ================================================================ # Interface Types (inherit from InfraInterface generic) - # =================================================================== + # ================================================================ - name: InterfaceEthernet namespace: Infra description: Physical Ethernet interface label: Ethernet Interface icon: mdi--ethernet + include_in_menu: false inherit_from: - InfraInterface uniqueness_constraints: @@ -230,6 +234,7 @@ nodes: description: Loopback interface label: Loopback Interface icon: mdi--reload + include_in_menu: false inherit_from: - InfraInterface uniqueness_constraints: @@ -244,6 +249,7 @@ nodes: description: VLAN SVI interface label: VLAN Interface icon: mdi--lan + include_in_menu: false inherit_from: - InfraInterface uniqueness_constraints: @@ -263,6 +269,7 @@ nodes: description: Link Aggregation (Port-Channel) interface label: LAG Interface icon: mdi--link-variant + include_in_menu: false inherit_from: - InfraInterface uniqueness_constraints: @@ -297,6 +304,7 @@ nodes: description: VXLAN tunnel interface label: VXLAN Interface icon: mdi--tunnel + include_in_menu: false inherit_from: - InfraInterface uniqueness_constraints: @@ -315,14 +323,15 @@ nodes: cardinality: one description: VTEP source interface (typically Loopback1) - # =================================================================== + # ================================================================ # IP Address - # =================================================================== + # ================================================================ - name: IPAddress namespace: Infra description: IP Address assignment label: IP Address icon: mdi--ip-network + include_in_menu: false human_friendly_id: - address__value order_by: -- 2.53.0 From ffa1eff19adce317c63e39a080c6592f4063a3f3 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Mon, 9 Feb 2026 12:03:38 +0000 Subject: [PATCH 42/58] feat(schema): add include_in_menu: false to all BGP nodes #41 --- schemas/bgp.yml | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/schemas/bgp.yml b/schemas/bgp.yml index 8946b84..351738a 100644 --- a/schemas/bgp.yml +++ b/schemas/bgp.yml @@ -3,14 +3,15 @@ --- version: "1.0" nodes: - # =================================================================== + # ================================================================ # Autonomous System - # =================================================================== + # ================================================================ - name: AutonomousSystem namespace: Infra description: BGP Autonomous System label: Autonomous System icon: mdi--cloud-outline + include_in_menu: false human_friendly_id: - asn__value order_by: @@ -33,14 +34,15 @@ nodes: - name: public label: Public - # =================================================================== + # ================================================================ # BGP Router Configuration (per device) - # =================================================================== + # ================================================================ - name: BGPRouterConfig namespace: Infra description: BGP router configuration on a device label: BGP Router Config icon: mdi--router-wireless + include_in_menu: false human_friendly_id: - device__name__value display_label: "{{ router_id__value }}" @@ -81,14 +83,15 @@ nodes: cardinality: many kind: Component - # =================================================================== + # ================================================================ # BGP Peer Group - # =================================================================== + # ================================================================ - name: BGPPeerGroup namespace: Infra description: BGP peer group template label: BGP Peer Group icon: mdi--account-group + include_in_menu: false human_friendly_id: - name__value display_label: "{{ name__value }}" @@ -153,14 +156,15 @@ nodes: cardinality: one optional: true - # =================================================================== + # ================================================================ # BGP Session (Neighbor) - # =================================================================== + # ================================================================ - name: BGPSession namespace: Infra description: BGP neighbor session label: BGP Session icon: mdi--connection + include_in_menu: false human_friendly_id: - peer_address__value display_label: "{{ peer_address__value }}" @@ -195,14 +199,15 @@ nodes: optional: true description: Remote peer device (for documentation) - # =================================================================== + # ================================================================ # BGP Address Family Configuration - # =================================================================== + # ================================================================ - name: BGPAddressFamily namespace: Infra description: BGP address family configuration label: BGP Address Family icon: mdi--format-list-bulleted + include_in_menu: false display_label: "{{ afi__value }}" attributes: - name: afi -- 2.53.0 From a05e9977422d8bddaa3b8806f59a7ab68e1d94e5 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Mon, 9 Feb 2026 12:04:04 +0000 Subject: [PATCH 43/58] feat(schema): add include_in_menu: false to all VLAN/VXLAN nodes #41 --- schemas/vlan_vxlan.yml | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/schemas/vlan_vxlan.yml b/schemas/vlan_vxlan.yml index dc81548..c55ae1a 100644 --- a/schemas/vlan_vxlan.yml +++ b/schemas/vlan_vxlan.yml @@ -3,14 +3,15 @@ --- version: "1.0" nodes: - # =================================================================== + # ================================================================ # VLAN - # =================================================================== + # ================================================================ - name: VLAN namespace: Infra description: Virtual LAN configuration label: VLAN icon: mdi--lan-connect + include_in_menu: false human_friendly_id: - vlan_id__value order_by: @@ -61,14 +62,15 @@ nodes: cardinality: one optional: true - # =================================================================== + # ================================================================ # VNI (VXLAN Network Identifier) - # =================================================================== + # ================================================================ - name: VNI namespace: Infra description: VXLAN Network Identifier label: VNI icon: mdi--tunnel-outline + include_in_menu: false human_friendly_id: - vni__value order_by: @@ -105,14 +107,15 @@ nodes: optional: true description: Associated VRF for L3VNI - # =================================================================== + # ================================================================ # VTEP (VXLAN Tunnel Endpoint) - # =================================================================== + # ================================================================ - name: VTEP namespace: Infra description: VXLAN Tunnel Endpoint configuration label: VTEP icon: mdi--server-network-outline + include_in_menu: false human_friendly_id: - device__name__value display_label: "{{ source_address__value }}" @@ -147,14 +150,15 @@ nodes: cardinality: many kind: Component - # =================================================================== + # ================================================================ # VLAN to VNI Mapping (per-device) - # =================================================================== + # ================================================================ - name: VlanVniMapping namespace: Infra description: VLAN to VNI mapping on a VTEP label: VLAN-VNI Mapping icon: mdi--swap-horizontal + include_in_menu: false display_label: "{{ description__value }}" attributes: - name: description @@ -174,14 +178,15 @@ nodes: peer: InfraVNI cardinality: one - # =================================================================== + # ================================================================ # EVPN Instance (per VLAN) - # =================================================================== + # ================================================================ - name: EVPNInstance namespace: Infra description: EVPN instance configuration (route targets for L2 extension) label: EVPN Instance icon: mdi--cloud-sync + include_in_menu: false display_label: "{{ route_distinguisher__value }}" attributes: - name: route_distinguisher -- 2.53.0 From 741132a1761bd6be4f5bb955f3c1f75cae831ada Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Mon, 9 Feb 2026 12:04:21 +0000 Subject: [PATCH 44/58] feat(schema): add include_in_menu: false to all VRF nodes #41 --- schemas/vrf.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/schemas/vrf.yml b/schemas/vrf.yml index 18f1483..68e1569 100644 --- a/schemas/vrf.yml +++ b/schemas/vrf.yml @@ -3,14 +3,15 @@ --- version: "1.0" nodes: - # =================================================================== + # ================================================================ # VRF (Virtual Routing and Forwarding) - # =================================================================== + # ================================================================ - name: VRF namespace: Infra description: Virtual Routing and Forwarding instance label: VRF icon: mdi--router + include_in_menu: false human_friendly_id: - name__value order_by: @@ -56,14 +57,15 @@ nodes: optional: true description: Interfaces assigned to this VRF - # =================================================================== + # ================================================================ # Route Target - # =================================================================== + # ================================================================ - name: RouteTarget namespace: Infra description: BGP Route Target for VPN import/export label: Route Target icon: mdi--target + include_in_menu: false human_friendly_id: - target__value order_by: @@ -78,14 +80,15 @@ nodes: kind: Text optional: true - # =================================================================== + # ================================================================ # VRF Device Assignment - # =================================================================== + # ================================================================ - name: VRFDeviceAssignment namespace: Infra description: VRF assignment to a specific device label: VRF Assignment icon: mdi--router-network + include_in_menu: false human_friendly_id: - device__name__value - vrf__name__value -- 2.53.0 From e31846b0573a7b4a559eed292bfae4a80c4f289b Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Mon, 9 Feb 2026 12:04:46 +0000 Subject: [PATCH 45/58] feat(schema): add include_in_menu: false to all MLAG nodes #41 --- schemas/mlag.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/schemas/mlag.yml b/schemas/mlag.yml index e42be15..7a6c220 100644 --- a/schemas/mlag.yml +++ b/schemas/mlag.yml @@ -3,14 +3,15 @@ --- version: "1.0" nodes: - # =================================================================== + # ================================================================ # MLAG Domain - # =================================================================== + # ================================================================ - name: MlagDomain namespace: Infra description: MLAG domain configuration for leaf pair label: MLAG Domain icon: mdi--link-variant + include_in_menu: false human_friendly_id: - domain_id__value display_label: "{{ domain_id__value }}" @@ -64,14 +65,15 @@ nodes: optional: true description: VLAN for iBGP peering between MLAG peers - # =================================================================== + # ================================================================ # MLAG Peer Configuration (per device) - # =================================================================== + # ================================================================ - name: MlagPeerConfig namespace: Infra description: MLAG configuration on a specific device label: MLAG Peer Config icon: mdi--server-network + include_in_menu: false human_friendly_id: - device__name__value display_label: "{{ local_interface_ip__value }}" @@ -103,14 +105,15 @@ nodes: cardinality: one description: Peer-link port-channel - # =================================================================== + # ================================================================ # MLAG Interface (MLAG-enabled LAG) - # =================================================================== + # ================================================================ - name: MlagInterface namespace: Infra description: MLAG interface configuration label: MLAG Interface icon: mdi--ethernet-cable + include_in_menu: false display_label: "{{ mlag_id__value }}" attributes: - name: mlag_id -- 2.53.0 From d05c96915f98f59a5dd7966245c9abf071b6059f Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Mon, 9 Feb 2026 12:05:11 +0000 Subject: [PATCH 46/58] feat(schema): add include_in_menu: false to all extension nodes #41 --- schemas/extensions.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/schemas/extensions.yml b/schemas/extensions.yml index 4120ee5..4f9e8c7 100644 --- a/schemas/extensions.yml +++ b/schemas/extensions.yml @@ -3,14 +3,15 @@ --- version: "1.0" nodes: - # =================================================================== + # ================================================================ # Fabric (Top-level container for all fabric objects) - # =================================================================== + # ================================================================ - name: Fabric namespace: Infra description: EVPN-VXLAN Fabric definition label: Fabric icon: mdi--vector-polygon + include_in_menu: false human_friendly_id: - name__value order_by: @@ -57,14 +58,15 @@ nodes: cardinality: many optional: true - # =================================================================== + # ================================================================ # Underlay P2P Link - # =================================================================== + # ================================================================ - name: UnderlayLink namespace: Infra description: Point-to-point underlay link between devices label: Underlay Link icon: mdi--cable-data + include_in_menu: false display_label: "{{ description__value }}" attributes: - name: description @@ -106,14 +108,15 @@ nodes: cardinality: one direction: outbound - # =================================================================== + # ================================================================ # Host Connection - # =================================================================== + # ================================================================ - name: HostConnection namespace: Infra description: Host connection to fabric (single or dual-homed) label: Host Connection icon: mdi--desktop-tower + include_in_menu: false human_friendly_id: - hostname__value display_label: "{{ hostname__value }}" -- 2.53.0 From aa9d0093fe449be49a938c6d12de3b31a7e5a959 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Mon, 9 Feb 2026 13:29:11 +0000 Subject: [PATCH 47/58] fix(menu): rename VRF/MLAG namespaces to match Infrahub regex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Infrahub namespaces must match ^[A-Z][a-z0-9]+$ - VRF → Vrf - MLAG → Mlag --- menus/fabric-menu.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/menus/fabric-menu.yml b/menus/fabric-menu.yml index a6cfc95..49b5bc6 100644 --- a/menus/fabric-menu.yml +++ b/menus/fabric-menu.yml @@ -180,25 +180,25 @@ spec: # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # VRF # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - namespace: VRF + - namespace: Vrf name: Mainmenu label: VRF icon: "mdi:router" children: data: - - namespace: VRF + - namespace: Vrf name: Vrf label: VRFs kind: InfraVRF icon: "mdi:router" - - namespace: VRF + - namespace: Vrf name: RouteTarget label: Route Targets kind: InfraRouteTarget icon: "mdi:target" - - namespace: VRF + - namespace: Vrf name: VrfAssignment label: VRF Assignments kind: InfraVRFDeviceAssignment @@ -207,25 +207,25 @@ spec: # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # MLAG # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - namespace: MLAG + - namespace: Mlag name: Mainmenu label: MLAG icon: "mdi:link-variant" children: data: - - namespace: MLAG + - namespace: Mlag name: MlagDomain label: MLAG Domains kind: InfraMlagDomain icon: "mdi:link-variant" - - namespace: MLAG + - namespace: Mlag name: MlagPeerConfig label: MLAG Peer Config kind: InfraMlagPeerConfig icon: "mdi:server-network" - - namespace: MLAG + - namespace: Mlag name: MlagInterface label: MLAG Interfaces kind: InfraMlagInterface -- 2.53.0 From f69bba2bf165d505e1365564dc2d4cc1b79f6c64 Mon Sep 17 00:00:00 2001 From: Damien Date: Thu, 12 Feb 2026 11:19:23 +0100 Subject: [PATCH 48/58] Create CLAUDE.md --- CLAUDE.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f974c3a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,35 @@ +# Claude Code Instructions — Schema Refinement + +## Project Context +This is a fabric-orchestrator project managing Arista EVPN-VXLAN fabrics. +Branch: `feature/41-infrahub-schema` +Schema files are in `schemas/` directory (Infrahub YAML format). + +## Reference Topology (from overlaid.net) +- 2 spines (AS 65000), 8 leafs in 4 MLAG pairs (AS 65001-65004) +- Loopback0: BGP router-id, Loopback1: shared VTEP IP per MLAG pair +- VLANs 4090/4091: MLAG peering with trunk groups +- EVPN overlay via eBGP multihop on loopbacks +- L2VXLAN (Type-2) and L3VXLAN (Type-5) with VRFs + +## Infrahub Schema Rules +1. `human_friendly_id` attributes MUST have `unique: true` +2. If human_friendly_id needs to be scoped per-device, traverse Parent + relationships: `parent_rel__parent_attr__value` +3. Parent relationships need `optional: false` explicitly +4. Self-referencing relationships need `direction: outbound` +5. Multiple relationships to same peer type need unique `identifier` +6. Validate with: `infrahubctl schema check schemas/` + +## Commit Convention +- Reference issue: `fix(schema): description — refs #41` +- One logical change per commit +- Run schema validation before committing + +## Files +- `schemas/base.yml` — Device, Interfaces, IPAddress +- `schemas/bgp.yml` — AS, BGPRouterConfig, PeerGroup, Session, AF +- `schemas/vlan_vxlan.yml` — VLAN, VNI, VTEP, VlanVniMapping, EVPN +- `schemas/vrf.yml` — VRF, RouteTarget, VRFDeviceAssignment +- `schemas/mlag.yml` — MlagDomain, MlagPeerConfig, MlagInterface +- `schemas/extensions.yml` — UnderlayLink, HostConnection, FabricSettings -- 2.53.0 From 3654c2de9dfa70d003e454286f69ec76685d2f72 Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 13 Feb 2026 11:21:51 +0100 Subject: [PATCH 49/58] =?UTF-8?q?fix(schema):=20scope=20BGPPeerGroup=20and?= =?UTF-8?q?=20BGPSession=20human=5Ffriendly=5Fid=20per=20device=20?= =?UTF-8?q?=E2=80=94=20refs=20#43?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schemas/bgp.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/schemas/bgp.yml b/schemas/bgp.yml index 351738a..1cc509f 100644 --- a/schemas/bgp.yml +++ b/schemas/bgp.yml @@ -49,6 +49,7 @@ nodes: attributes: - name: router_id kind: IPHost + unique: true description: BGP Router ID - name: default_ipv4_unicast kind: Boolean @@ -92,7 +93,10 @@ nodes: label: BGP Peer Group icon: mdi--account-group include_in_menu: false + uniqueness_constraints: + - ["bgp_config", "name__value"] human_friendly_id: + - bgp_config__router_id__value - name__value display_label: "{{ name__value }}" attributes: @@ -165,7 +169,10 @@ nodes: label: BGP Session icon: mdi--connection include_in_menu: false + uniqueness_constraints: + - ["bgp_config", "peer_address__value"] human_friendly_id: + - bgp_config__router_id__value - peer_address__value display_label: "{{ peer_address__value }}" attributes: -- 2.53.0 From 719ecfafaaddfc29be66d336de3edcb9d8efce01 Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 13 Feb 2026 11:22:43 +0100 Subject: [PATCH 50/58] =?UTF-8?q?fix(schema):=20remove=20duplicate=20Inter?= =?UTF-8?q?faceVxlan,=20keep=20VTEP=20only=20=E2=80=94=20refs=20#44?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schemas/README.md | 3 +-- schemas/base.yml | 24 ------------------------ 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/schemas/README.md b/schemas/README.md index 58f9ab2..f753c89 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -50,7 +50,6 @@ This directory contains the Infrahub schema definitions for modeling an EVPN-VXL │ - Loopback │ │ (underlay, │ │ (neighbors) │ │ - Vlan │ │ evpn) │ └──────────────┘ │ - Lag │ └──────────────┘ -│ - Vxlan │ └──────┬───────┘ │ ▼ @@ -81,7 +80,7 @@ The schema models this topology from `arista-evpn-vxlan-clab`: | Port-Channel1 | InfraMlagInterface (host-facing) | | Ethernet1-8 | InfraInterfaceEthernet | | Loopback0, Loopback1 | InfraInterfaceLoopback | -| Vxlan1 | InfraInterfaceVxlan | +| Vxlan1 | InfraVTEP | | peer groups | InfraBGPPeerGroup | ## Usage diff --git a/schemas/base.yml b/schemas/base.yml index b1a286c..be0460b 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -299,30 +299,6 @@ nodes: cardinality: many kind: Component - - name: InterfaceVxlan - namespace: Infra - description: VXLAN tunnel interface - label: VXLAN Interface - icon: mdi--tunnel - include_in_menu: false - inherit_from: - - InfraInterface - uniqueness_constraints: - - ["device", "name__value"] - human_friendly_id: - - device__name__value - - name__value - display_label: "{{ name__value }}" - attributes: - - name: udp_port - kind: Number - default_value: 4789 - relationships: - - name: source_interface - peer: InfraInterfaceLoopback - cardinality: one - description: VTEP source interface (typically Loopback1) - # ================================================================ # IP Address # ================================================================ -- 2.53.0 From 82af2daafc66cfa847ba44998d1243a4ec237add Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 13 Feb 2026 11:23:02 +0100 Subject: [PATCH 51/58] =?UTF-8?q?fix(schema):=20add=20unique=20constraint?= =?UTF-8?q?=20on=20InfraVLAN.vlan=5Fid=20for=20human=5Ffriendly=5Fid=20?= =?UTF-8?q?=E2=80=94=20refs=20#45?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schemas/vlan_vxlan.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/schemas/vlan_vxlan.yml b/schemas/vlan_vxlan.yml index c55ae1a..026327e 100644 --- a/schemas/vlan_vxlan.yml +++ b/schemas/vlan_vxlan.yml @@ -20,6 +20,7 @@ nodes: attributes: - name: vlan_id kind: Number + unique: true description: VLAN ID (1-4094) - name: name kind: Text -- 2.53.0 From ed820f3380899fe6350ce325323de3dc7754d94f Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 13 Feb 2026 11:23:29 +0100 Subject: [PATCH 52/58] =?UTF-8?q?fix(schema):=20add=20virtual=5Frouter=5Fa?= =?UTF-8?q?ddress=20and=20autostate=20on=20InterfaceVlan=20=E2=80=94=20ref?= =?UTF-8?q?s=20#46?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schemas/base.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/schemas/base.yml b/schemas/base.yml index be0460b..ca6685b 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -258,6 +258,15 @@ nodes: - device__name__value - name__value display_label: "{{ name__value }}" + attributes: + - name: virtual_router_address + kind: IPHost + optional: true + description: Anycast gateway IP (ip virtual-router address) + - name: autostate + kind: Boolean + default_value: true + description: "Enable autostate (set false for MLAG peer SVIs)" relationships: - name: vlan peer: InfraVLAN -- 2.53.0 From e527534820696942abb39ef005277ef42c8b6c55 Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 13 Feb 2026 11:24:17 +0100 Subject: [PATCH 53/58] =?UTF-8?q?fix(schema):=20refactor=20UnderlayLink=20?= =?UTF-8?q?IPs=20from=20attributes=20to=20InfraIPAddress=20relations=20?= =?UTF-8?q?=E2=80=94=20refs=20#47?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schemas/extensions.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/schemas/extensions.yml b/schemas/extensions.yml index 4f9e8c7..d2d8c9e 100644 --- a/schemas/extensions.yml +++ b/schemas/extensions.yml @@ -72,12 +72,6 @@ nodes: - name: description kind: Text description: Link description (e.g., spine1:eth1 <-> leaf1:eth11) - - name: local_ip - kind: IPNetwork - description: Local interface IP with mask - - name: remote_ip - kind: IPNetwork - description: Remote interface IP with mask - name: mtu kind: Number default_value: 9214 @@ -97,6 +91,11 @@ nodes: identifier: underlay_link_local_interface cardinality: one direction: outbound + - name: local_ip_address + peer: InfraIPAddress + identifier: underlay_link_local_ip + cardinality: one + direction: outbound - name: remote_device peer: InfraDevice identifier: underlay_link_remote_device @@ -107,6 +106,11 @@ nodes: identifier: underlay_link_remote_interface cardinality: one direction: outbound + - name: remote_ip_address + peer: InfraIPAddress + identifier: underlay_link_remote_ip + cardinality: one + direction: outbound # ================================================================ # Host Connection -- 2.53.0 From f623d12b8c85e8f3d7ad9b37f1faa973019fd47a Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 13 Feb 2026 11:24:49 +0100 Subject: [PATCH 54/58] =?UTF-8?q?fix(schema):=20remove=20redundant=20Devic?= =?UTF-8?q?e.router=5Fid,=20add=20BGP=20distance=20attributes=20=E2=80=94?= =?UTF-8?q?=20refs=20#48?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schemas/base.yml | 4 ---- schemas/bgp.yml | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/schemas/base.yml b/schemas/base.yml index ca6685b..7e33dc4 100644 --- a/schemas/base.yml +++ b/schemas/base.yml @@ -129,10 +129,6 @@ nodes: label: Border Leaf color: "#f59e0b" description: Fabric role - - name: router_id - kind: IPHost - optional: true - description: BGP Router ID (typically Loopback0) - name: status kind: Dropdown default_value: active diff --git a/schemas/bgp.yml b/schemas/bgp.yml index 1cc509f..060b277 100644 --- a/schemas/bgp.yml +++ b/schemas/bgp.yml @@ -66,6 +66,18 @@ nodes: kind: Number default_value: 64 description: Maximum ECMP routes + - name: ebgp_distance + kind: Number + default_value: 20 + description: eBGP administrative distance + - name: ibgp_distance + kind: Number + default_value: 200 + description: iBGP administrative distance + - name: local_distance + kind: Number + default_value: 200 + description: Local route administrative distance relationships: - name: device peer: InfraDevice -- 2.53.0 From cf05a5d477643a069dfbb6f58fbd566c7a850bb7 Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 13 Feb 2026 11:25:29 +0100 Subject: [PATCH 55/58] =?UTF-8?q?fix(schema):=20add=20trunk=5Fgroups=20and?= =?UTF-8?q?=20stp=5Fenabled=20on=20InfraVLAN=20=E2=80=94=20refs=20#49?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schemas/vlan_vxlan.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/schemas/vlan_vxlan.yml b/schemas/vlan_vxlan.yml index 026327e..b17cf82 100644 --- a/schemas/vlan_vxlan.yml +++ b/schemas/vlan_vxlan.yml @@ -52,6 +52,14 @@ nodes: - name: mlag_ibgp label: MLAG iBGP description: VLAN purpose + - name: trunk_groups + kind: List + optional: true + description: "Trunk groups restricting VLAN propagation (e.g., mlag-peer)" + - name: stp_enabled + kind: Boolean + default_value: true + description: "Enable spanning-tree on this VLAN (set false for MLAG peer VLANs)" relationships: - name: vni peer: InfraVNI -- 2.53.0 From 4e2f5b5b0c16ee55fb683ec84dd7cad7931cf7e9 Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 13 Feb 2026 15:02:55 +0100 Subject: [PATCH 56/58] Update CLAUDE.md --- CLAUDE.md | 99 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f974c3a..4c28566 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,35 +1,82 @@ -# Claude Code Instructions — Schema Refinement +# Claude Code Instructions — fabric-orchestrator ## Project Context -This is a fabric-orchestrator project managing Arista EVPN-VXLAN fabrics. -Branch: `feature/41-infrahub-schema` -Schema files are in `schemas/` directory (Infrahub YAML format). -## Reference Topology (from overlaid.net) -- 2 spines (AS 65000), 8 leafs in 4 MLAG pairs (AS 65001-65004) -- Loopback0: BGP router-id, Loopback1: shared VTEP IP per MLAG pair -- VLANs 4090/4091: MLAG peering with trunk groups -- EVPN overlay via eBGP multihop on loopbacks -- L2VXLAN (Type-2) and L3VXLAN (Type-5) with VRFs +Fabric-orchestrator manages Arista EVPN-VXLAN fabrics using Infrahub as the source of truth. +Gitea: https://gitea.arnodo.fr/Damien/fabric-orchestrator +Branch: `feature/41-infrahub-schema` + +## Reference Topology (overlaid.net) + +- 2 spines (AS 65000), 8 leafs in 4 MLAG pairs (AS 65001–65004) +- Loopback0: BGP router-id per device, Loopback1: shared VTEP IP per MLAG pair +- VLANs 4090 (MLAG peer) / 4091 (MLAG iBGP) with trunk groups +- Underlay: eBGP point-to-point (spine↔leaf) + iBGP (leaf↔leaf peer) +- Overlay: EVPN eBGP multihop on loopbacks, spines as route-reflectors with next-hop-unchanged +- L2VXLAN (EVPN Type-2): VLAN→VNI mapping, redistribute learned +- L3VXLAN (EVPN Type-5): VRF→VNI mapping, redistribute connected +- Border peering: BGP sessions inside VRF (leaf7/8 → AS 64999 in VRF gold) + +## Schema Files (Infrahub YAML format, in `schemas/`) + +| File | Content | +| ---------------- | ----------------------------------------------------------------------------- | +| `base.yml` | Device, Interfaces (Ethernet, Loopback, Vlan, Lag, Vxlan), IPAddress | +| `bgp.yml` | AutonomousSystem, BGPRouterConfig, BGPPeerGroup, BGPSession, BGPAddressFamily | +| `vlan_vxlan.yml` | VLAN, VNI, VTEP, VlanVniMapping, EVPNInstance | +| `vrf.yml` | VRFConfig, RouteTarget, VRFDeviceAssignment | +| `mlag.yml` | MlagDomain, MlagPeerConfig, MlagInterface | +| `extensions.yml` | UnderlayLink, HostConnection, FabricSettings | ## Infrahub Schema Rules -1. `human_friendly_id` attributes MUST have `unique: true` -2. If human_friendly_id needs to be scoped per-device, traverse Parent - relationships: `parent_rel__parent_attr__value` -3. Parent relationships need `optional: false` explicitly + +1. `human_friendly_id` fields MUST have `unique: true` — globally unique across all instances +2. To scope human_friendly_id per-device, traverse Parent relationships: + `parent_rel__parent_attr__value` (e.g. `device__name__value`) +3. Parent relationships (`kind: Parent`) need `optional: false` explicitly 4. Self-referencing relationships need `direction: outbound` -5. Multiple relationships to same peer type need unique `identifier` -6. Validate with: `infrahubctl schema check schemas/` +5. Multiple relationships to the same peer type need distinct `identifier` values +6. Don't model the same concept twice (e.g. VTEP source_address vs InterfaceVxlan source_interface) +7. `kind: Attribute` for association, `kind: Component` for ownership (lifecycle-coupled) +8. `kind: Parent` implies the child cannot exist without the parent + +## Validation + +```bash +infrahubctl schema check schemas/ +``` + +Always run before committing. Fix any errors before pushing. ## Commit Convention -- Reference issue: `fix(schema): description — refs #41` -- One logical change per commit -- Run schema validation before committing -## Files -- `schemas/base.yml` — Device, Interfaces, IPAddress -- `schemas/bgp.yml` — AS, BGPRouterConfig, PeerGroup, Session, AF -- `schemas/vlan_vxlan.yml` — VLAN, VNI, VTEP, VlanVniMapping, EVPN -- `schemas/vrf.yml` — VRF, RouteTarget, VRFDeviceAssignment -- `schemas/mlag.yml` — MlagDomain, MlagPeerConfig, MlagInterface -- `schemas/extensions.yml` — UnderlayLink, HostConnection, FabricSettings +``` +fix(schema): short description — refs # +feat(schema): short description — refs # +``` + +- One logical change per commit +- Reference the Gitea issue number +- Comment on the issue after implementation with changes summary + +## Open Issues (prioritized) + +Check https://gitea.arnodo.fr/Damien/fabric-orchestrator/issues for current backlog. +Critical issues (blocking data load) take priority over functional improvements. +Dependency chain: resolve critical → significant → minor sequentially. + +## Workflow + +1. Read the issue description fully before starting +2. Read relevant schema files to understand current state +3. Make minimal, targeted changes +4. Validate with `infrahubctl schema check schemas/` +5. Commit with proper message referencing the issue +6. Comment on the Gitea issue with what was changed + +## Don'ts + +- Don't add fields not needed by the reference topology +- Don't change `human_friendly_id` without checking uniqueness implications +- Don't remove existing relationships without checking reverse dependencies +- Don't create new schema files without discussing first -- 2.53.0 From e32da46bd7b44ccda5194b91c6bbf89bc54aafc2 Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 13 Feb 2026 15:03:55 +0100 Subject: [PATCH 57/58] =?UTF-8?q?fix(schema):=20add=20optional=20VRF=20rel?= =?UTF-8?q?ation=20on=20BGPSession=20=E2=80=94=20refs=20#50?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schemas/bgp.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/schemas/bgp.yml b/schemas/bgp.yml index 060b277..2b48d01 100644 --- a/schemas/bgp.yml +++ b/schemas/bgp.yml @@ -217,6 +217,12 @@ nodes: cardinality: one optional: true description: Remote peer device (for documentation) + - name: vrf + peer: InfraVRF + cardinality: one + kind: Attribute + optional: true + description: VRF context for this session (null = global BGP process) # ================================================================ # BGP Address Family Configuration -- 2.53.0 From f484af442a03bf6a58c412edb2ed7c9ceffa5497 Mon Sep 17 00:00:00 2001 From: Damien Arnodo Date: Fri, 13 Feb 2026 14:20:02 +0000 Subject: [PATCH 58/58] =?UTF-8?q?docs(schema):=20update=20README=20with=20?= =?UTF-8?q?complete=20relationships=20and=20topology=20mapping=20=E2=80=94?= =?UTF-8?q?=20refs=20#41?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schemas/README.md | 235 +++++++++++++++++++++++++++++++++------------- 1 file changed, 170 insertions(+), 65 deletions(-) diff --git a/schemas/README.md b/schemas/README.md index f753c89..ce54fc2 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -1,71 +1,162 @@ # Infrahub Schema for EVPN-VXLAN Fabric -This directory contains the Infrahub schema definitions for modeling an EVPN-VXLAN fabric. The schema is designed to represent the [arista-evpn-vxlan-clab](https://gitea.arnodo.fr/Damien/arista-evpn-vxlan-clab) topology. +This directory contains the Infrahub schema definitions for modeling an EVPN-VXLAN fabric. The schema is designed to represent the [overlaid.net reference topology](https://overlaid.net/2019/01/27/arista-bgp-evpn-configuration-example/) (2 spines, 8 leafs in 4 MLAG pairs). ## Schema Files -| File | Description | -|------|-------------| -| `base.yml` | Core infrastructure: Device, Interface types, IP Address, Platform, Site | -| `vlan_vxlan.yml` | VLAN, VNI, VTEP, EVPN Instance | -| `vrf.yml` | VRF, Route Target, VRF assignments | -| `bgp.yml` | Autonomous System, BGP Config, Peer Groups, Sessions | -| `mlag.yml` | MLAG Domain, Peer Config, MLAG Interfaces | -| `extensions.yml` | Fabric, Underlay Links, Host Connections | +| File | Nodes | Description | +|------|-------|-------------| +| `base.yml` | Device, InterfaceEthernet, InterfaceLoopback, InterfaceVlan, InterfaceLag, IPAddress, Site, Platform | Core infrastructure and generic Interface | +| `bgp.yml` | AutonomousSystem, BGPRouterConfig, BGPPeerGroup, BGPSession, BGPAddressFamily | BGP routing configuration | +| `vlan_vxlan.yml` | VLAN, VNI, VTEP, VlanVniMapping, EVPNInstance | Layer 2 overlay and VXLAN tunneling | +| `vrf.yml` | VRF, RouteTarget, VRFDeviceAssignment | VRF and L3VNI configuration | +| `mlag.yml` | MlagDomain, MlagPeerConfig, MlagInterface | MLAG domain and peer configuration | +| `extensions.yml` | Fabric, UnderlayLink, HostConnection | Fabric topology and connectivity | ## Entity Relationship Diagram ``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ FABRIC TOPOLOGY │ -└─────────────────────────────────────────────────────────────────────────────┘ + ┌──────────────┐ + │ InfraFabric │ + └──────┬───────┘ + ┌───────────┼───────────┐ + ▼ ▼ ▼ + ┌────────────┐ ┌──────────┐ ┌──────────────────┐ + │LocationSite│ │InfraAS │ │InfraUnderlayLink │ + └────────────┘ └────┬─────┘ │ local/remote: │ + │ │ Device,Interface,│ + │ │ IPAddress │ + ┌────────────┘ └──────────────────┘ + ▼ + ┌──────────────┐ ┌────────────────┐ + │ InfraDevice │◄────────│ InfraPlatform │ + └──────┬───────┘ └────────────────┘ + │ + ┌─────────────┼──────────────┬────────────────┐ + ▼ ▼ ▼ ▼ +┌─────────────┐ ┌──────────┐ ┌───────────┐ ┌──────────────┐ +│InfraInterface│ │InfraBGP- │ │InfraVTEP │ │InfraMlagDomain│ +│ (generic) │ │RouterCfg │ │ │ │ (2 devices) │ +└──────┬──────┘ └────┬─────┘ └─────┬─────┘ └──────┬───────┘ + │ │ │ │ + ▼ ▼ ▼ ▼ + Subtypes: ┌──────────┐ ┌──────────┐ ┌───────────────┐ + - Ethernet │BGPPeer- │ │VlanVni- │ │MlagPeerConfig │ + - Loopback │ Group │ │ Mapping │ │ (per device) │ + - Vlan └──────────┘ └──────────┘ └───────────────┘ + - Lag ┌──────────┐ ┌───────────────┐ + │ │BGPSession│ │MlagInterface │ + ▼ └────┬─────┘ └───────────────┘ +┌──────────────┐ │ +│InfraIPAddress│ │ optional vrf +└──────────────┘ ▼ + ┌─────────┐ ┌──────────────┐ + │InfraVRF │◄────│InfraRoute- │ + └────┬────┘ │ Target │ + │ └──────────────┘ + ▼ + ┌────────────────┐ + │VRFDevice- │ + │ Assignment │ + │ (per device RD)│ + └────────────────┘ - ┌──────────────┐ - │ InfraFabric │ - └──────┬───────┘ - │ - ┌──────────────────────┼──────────────────────┐ - │ │ │ - ▼ ▼ ▼ - ┌────────────┐ ┌─────────────┐ ┌────────────┐ - │ LocationSite│ │ InfraDevice │ │InfraAutono-│ - └────────────┘ │ (spine/ │ │mousSystem │ - │ leaf) │ └─────┬──────┘ - └──────┬──────┘ │ - │ │ - ┌────────────────────────────┼─────────────────────┤ - │ │ │ - ▼ ▼ ▼ -┌──────────────┐ ┌──────────────┐ ┌──────────────┐ -│InfraInterface│ │InfraMlagDomain│ │InfraBGPRouter│ -│ (generic) │ │ (leaf pair) │ │ Config │ -└──────┬───────┘ └──────────────┘ └──────┬───────┘ - │ │ - │ ┌─────────────────────────┬───────────────────┤ - │ │ │ │ - ▼ ▼ ▼ ▼ -┌──────────────┐ ┌──────────────┐ ┌──────────────┐ -│InterfaceTypes│ │InfraBGPPeer- │ │ InfraBGP- │ -│ - Ethernet │ │ Group │ │ Session │ -│ - Loopback │ │ (underlay, │ │ (neighbors) │ -│ - Vlan │ │ evpn) │ └──────────────┘ -│ - Lag │ └──────────────┘ -└──────┬───────┘ - │ - ▼ -┌──────────────┐ ┌──────────────┐ ┌──────────────┐ -│InfraIPAddress│◄────►│ InfraVLAN │◄────►│ InfraVNI │ -└──────────────┘ └──────────────┘ └──────────────┘ - │ - ▼ - ┌──────────────┐ - │ InfraVTEP │ - └──────────────┘ +Layer 2 / EVPN: +┌──────────┐ ┌──────────┐ ┌──────────────┐ +│InfraVLAN │◄──►│ InfraVNI │ │EVPNInstance │ +│ │ │(L2/L3) │ │(per device │ +│ │ └──────────┘ │ RD/RT) │ +└──────────┘ └──────────────┘ ``` -## Reference Topology Mapping +### Relationship Legend -The schema models this topology from `arista-evpn-vxlan-clab`: +| Symbol | Meaning | +|--------|---------| +| `Parent` → child | Child lifecycle depends on parent (e.g., Device → Interface) | +| `Component` → child | Owned collection (e.g., VTEP → VlanVniMapping) | +| `Attribute` | Association without ownership (e.g., BGPSession → VRF) | +| `Generic` | Polymorphic (e.g., IPAddress → any Interface subtype) | + +### All Relationships + +| Source | Relationship | Target | Kind | Cardinality | +|--------|-------------|--------|------|-------------| +| **base.yml** | | | | | +| InfraInterface | `device` | InfraDevice | Parent | one | +| InfraInterface | `ip_addresses` | InfraIPAddress | Generic | many | +| InfraDevice | `site` | LocationSite | Attribute | one (opt) | +| InfraDevice | `platform` | InfraPlatform | Attribute | one (opt) | +| InfraDevice | `asn` | InfraAutonomousSystem | Attribute | one (opt) | +| InfraDevice | `interfaces` | InfraInterface | Component | many | +| InfraDevice | `mlag_domain` | InfraMlagDomain | Attribute | one (opt) | +| InterfaceEthernet | `lag` | InterfaceLag | Attribute | one (opt) | +| InterfaceEthernet | `connected_interface` | InterfaceEthernet | outbound | one (opt) | +| InterfaceVlan | `vlan` | InfraVLAN | Attribute | one (opt) | +| InterfaceLag | `members` | InterfaceEthernet | Component | many | +| InfraIPAddress | `interface` | InfraInterface | Attribute | one (opt) | +| **bgp.yml** | | | | | +| BGPRouterConfig | `device` | InfraDevice | Parent | one | +| BGPRouterConfig | `local_asn` | InfraAutonomousSystem | Attribute | one | +| BGPRouterConfig | `peer_groups` | BGPPeerGroup | Component | many | +| BGPRouterConfig | `sessions` | BGPSession | Component | many | +| BGPPeerGroup | `bgp_config` | BGPRouterConfig | Parent | one | +| BGPPeerGroup | `remote_asn` | InfraAutonomousSystem | Attribute | one (opt) | +| BGPSession | `bgp_config` | BGPRouterConfig | Parent | one | +| BGPSession | `peer_group` | BGPPeerGroup | Attribute | one (opt) | +| BGPSession | `remote_asn` | InfraAutonomousSystem | Attribute | one (opt) | +| BGPSession | `peer_device` | InfraDevice | Attribute | one (opt) | +| BGPSession | `vrf` | InfraVRF | Attribute | one (opt) | +| BGPAddressFamily | `bgp_config` | BGPRouterConfig | Parent | one | +| BGPAddressFamily | `active_peer_groups` | BGPPeerGroup | Attribute | many | +| BGPAddressFamily | `networks` | InfraIPAddress | Attribute | many (opt) | +| **vlan_vxlan.yml** | | | | | +| InfraVLAN | `vni` | InfraVNI | Attribute | one (opt) | +| InfraVLAN | `site` | LocationSite | Attribute | one (opt) | +| InfraVNI | `vlan` | InfraVLAN | Attribute | one (opt) | +| InfraVNI | `vrf` | InfraVRF | Attribute | one (opt) | +| InfraVTEP | `device` | InfraDevice | Parent | one | +| InfraVTEP | `source_interface` | InterfaceLoopback | Attribute | one | +| InfraVTEP | `vlan_vni_mappings` | VlanVniMapping | Component | many | +| VlanVniMapping | `vtep` | InfraVTEP | Parent | one | +| VlanVniMapping | `vlan` | InfraVLAN | Attribute | one | +| VlanVniMapping | `vni` | InfraVNI | Attribute | one | +| EVPNInstance | `device` | InfraDevice | Parent | one | +| EVPNInstance | `vlan` | InfraVLAN | Attribute | one | +| **vrf.yml** | | | | | +| InfraVRF | `l3vni` | InfraVNI | Attribute | one (opt) | +| InfraVRF | `import_targets` | InfraRouteTarget | outbound | many (opt) | +| InfraVRF | `export_targets` | InfraRouteTarget | outbound | many (opt) | +| InfraVRF | `interfaces` | InfraInterface | Attribute | many (opt) | +| VRFDeviceAssignment | `vrf` | InfraVRF | Attribute | one | +| VRFDeviceAssignment | `device` | InfraDevice | Parent | one | +| VRFDeviceAssignment | `import_targets` | InfraRouteTarget | outbound | many (opt) | +| VRFDeviceAssignment | `export_targets` | InfraRouteTarget | outbound | many (opt) | +| **mlag.yml** | | | | | +| MlagDomain | `devices` | InfraDevice | Attribute | many (2) | +| MlagDomain | `peer_vlan` | InfraVLAN | outbound | one | +| MlagDomain | `ibgp_vlan` | InfraVLAN | outbound | one (opt) | +| MlagPeerConfig | `device` | InfraDevice | Parent | one | +| MlagPeerConfig | `mlag_domain` | MlagDomain | Attribute | one | +| MlagPeerConfig | `local_interface` | InterfaceVlan | Attribute | one | +| MlagPeerConfig | `peer_link` | InterfaceLag | Attribute | one | +| MlagInterface | `mlag_domain` | MlagDomain | Attribute | one | +| MlagInterface | `lag_interfaces` | InterfaceLag | Attribute | many (1-2) | +| **extensions.yml** | | | | | +| InfraFabric | `spine_asn` | InfraAutonomousSystem | Attribute | one (opt) | +| InfraFabric | `sites` | LocationSite | Attribute | many (opt) | +| UnderlayLink | `fabric` | InfraFabric | Parent | one | +| UnderlayLink | `local_device` | InfraDevice | outbound | one | +| UnderlayLink | `local_interface` | InterfaceEthernet | outbound | one | +| UnderlayLink | `local_ip_address` | InfraIPAddress | outbound | one | +| UnderlayLink | `remote_device` | InfraDevice | outbound | one | +| UnderlayLink | `remote_interface` | InterfaceEthernet | outbound | one | +| UnderlayLink | `remote_ip_address` | InfraIPAddress | outbound | one | +| HostConnection | `vlans` | InfraVLAN | Attribute | many | +| HostConnection | `mlag_interface` | MlagInterface | Attribute | one (opt) | +| HostConnection | `lag_interface` | InterfaceLag | Attribute | one (opt) | + +## Reference Topology Mapping | Physical | Infrahub Model | |----------|----------------| @@ -73,22 +164,30 @@ The schema models this topology from `arista-evpn-vxlan-clab`: | leaf1-8 | InfraDevice (role: leaf) | | AS 65000 | InfraAutonomousSystem (spines) | | AS 65001-65004 | InfraAutonomousSystem (leaf pairs) | -| VLAN 40, 34, 78 | InfraVLAN + InfraVNI | -| VLAN 4090, 4091 | InfraVLAN (vlan_type: mlag_peer/mlag_ibgp) | +| AS 64999 | InfraAutonomousSystem (border router) | +| VLAN 40, 34, 78, 900 | InfraVLAN + InfraVNI | +| VLAN 4090, 4091 | InfraVLAN (vlan_type: mlag_peer/mlag_ibgp, trunk_groups, stp_enabled: false) | +| VRF gold | InfraVRF + VRFDeviceAssignment (per-device RD) | +| Route targets 1:100001 | InfraRouteTarget | | leaf1+leaf2 pair | InfraMlagDomain | | Port-Channel999 | InfraInterfaceLag (peer-link) | | Port-Channel1 | InfraMlagInterface (host-facing) | -| Ethernet1-8 | InfraInterfaceEthernet | -| Loopback0, Loopback1 | InfraInterfaceLoopback | +| Ethernet1-12 | InfraInterfaceEthernet | +| Loopback0 | InfraInterfaceLoopback (BGP router-id) | +| Loopback1 | InfraInterfaceLoopback (shared VTEP IP per MLAG pair) | | Vxlan1 | InfraVTEP | -| peer groups | InfraBGPPeerGroup | +| Vlan34/78 SVIs | InfraInterfaceVlan (virtual_router_address for anycast gateway) | +| peer groups (underlay, evpn, underlay_ibgp) | InfraBGPPeerGroup | +| BGP sessions (global) | InfraBGPSession (vrf: null) | +| BGP sessions in VRF gold (leaf7/8 → AS 64999) | InfraBGPSession (vrf: gold) | +| spine1/2 p2p links | InfraUnderlayLink (IPAddress relations, not attributes) | +| distance bgp 20 200 200 | BGPRouterConfig (ebgp_distance, ibgp_distance, local_distance) | ## Usage ### Loading the Schema ```bash -# From the fabric-orchestrator root directory infrahubctl schema load schemas/ ``` @@ -101,12 +200,18 @@ infrahubctl schema check schemas/ ## Key Design Decisions 1. **Generic Interface**: All interface types inherit from `InfraInterface` generic for polymorphic queries -2. **MLAG as Domain**: MLAG is modeled as a domain containing exactly 2 devices, with per-device config +2. **MLAG as Domain**: MLAG is modeled as a domain containing exactly 2 devices, with per-device config via MlagPeerConfig 3. **BGP Hierarchy**: BGPRouterConfig → PeerGroups → Sessions allows template-based configuration -4. **VTEP Independence**: VTEP is separate from Device to support shared VTEP scenarios -5. **EVPN Instance per VLAN**: Allows device-specific RD/RT while referencing common VLAN/VNI +4. **BGP VRF Sessions**: BGPSession has an optional `vrf` relation (kind: Attribute) to support peering inside a VRF context (#50) +5. **VTEP as single model**: VTEP is the unique VXLAN model (InterfaceVxlan was removed to avoid duplication — #44) +6. **EVPN Instance per VLAN**: Allows device-specific RD/RT while referencing common VLAN/VNI +7. **Per-device scoped IDs**: BGPPeerGroup and BGPSession use `bgp_config__router_id__value` prefix in human_friendly_id for global uniqueness (#43) +8. **UnderlayLink IPs as relations**: local/remote IPs reference InfraIPAddress objects instead of inline attributes to avoid dual source of truth (#47) +9. **VRFDeviceAssignment**: Separates VRF definition (global) from per-device assignment (with device-specific RD/RT overrides) +10. **Anycast gateway**: InterfaceVlan has `virtual_router_address` for `ip virtual-router address` and `autostate` for MLAG SVIs (#46) ## Related Issues -- Parent issue: [#41 - Define Infrahub Schema for EVPN-VXLAN Fabric](https://gitea.arnodo.fr/Damien/fabric-orchestrator/issues/41) +- Parent issue: [#41 — Define Infrahub Schema for EVPN-VXLAN Fabric](https://gitea.arnodo.fr/Damien/fabric-orchestrator/issues/41) +- Schema fixes: #43 (unique IDs), #44 (remove duplicate VTEP), #45 (VLAN unique), #46 (anycast gateway), #47 (underlay IPs), #48 (BGP distance), #49 (trunk groups), #50 (VRF BGP sessions) - Depends on: Schema being loaded before transforms (#30, #31, #32, #33) -- 2.53.0