From 37b32614162247f8aab0b0b97f592138f4f48ead Mon Sep 17 00:00:00 2001 From: Damien Date: Tue, 3 Mar 2026 17:19:30 +0100 Subject: [PATCH] fix: add human_friendly_id to 4 schemas for idempotent Repository sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add local_identifier attribute (kind: Text) + uniqueness_constraints + human_friendly_id to InfraVlanVniMapping, InfraEVPNInstance, InfraMlagInterface and InfraUnderlayLink so Infrahub can perform upserts during Repository backend sync instead of duplicating objects on every import. Schema changes (following the InfraBGPPeerGroup/BGPSession pattern): - infrahub/schemas/vlan_vxlan.yml: VlanVniMapping + EVPNInstance - infrahub/schemas/mlag.yml: MlagInterface - infrahub/schemas/extensions.yml: UnderlayLink Object file updates: - 06-vlans-vxlan.yml: local_identifier added to all VlanVniMapping and EVPNInstance entries (format: leaf1__vlan40__vni110040 / leaf1__vlan40) - 12-mlag.yml: InfraMlagInterface section added for all 4 MLAG pairs (format: mlag1__leaf1-leaf2) - 14-fabric-links.yml: InfraUnderlayLink section added for all 16 spine↔leaf P2P links (format: spine1-eth1__leaf1-eth11) Co-Authored-By: Claude Sonnet 4.6 --- infrahub/objects/06-vlans-vxlan.yml | 24 ++-- infrahub/objects/12-mlag.yml | 46 +++++++ infrahub/objects/14-fabric-links.yml | 172 +++++++++++++++++++++++++++ infrahub/schemas/extensions.yml | 7 ++ infrahub/schemas/mlag.yml | 7 ++ infrahub/schemas/vlan_vxlan.yml | 14 +++ 6 files changed, 262 insertions(+), 8 deletions(-) diff --git a/infrahub/objects/06-vlans-vxlan.yml b/infrahub/objects/06-vlans-vxlan.yml index 96a4ff8..b516a79 100644 --- a/infrahub/objects/06-vlans-vxlan.yml +++ b/infrahub/objects/06-vlans-vxlan.yml @@ -116,19 +116,23 @@ spec: kind: InfraVlanVniMapping data: # VLAN 40 <-> VNI 110040 on leaf1/2/5/6 (L2 VXLAN leafs) - - vtep: ["leaf1"] + - local_identifier: leaf1__vlan40__vni110040 + vtep: ["leaf1"] vlan: ["40"] vni: ["110040"] description: "VLAN 40 <-> VNI 110040" - - vtep: ["leaf2"] + - local_identifier: leaf2__vlan40__vni110040 + vtep: ["leaf2"] vlan: ["40"] vni: ["110040"] description: "VLAN 40 <-> VNI 110040" - - vtep: ["leaf5"] + - local_identifier: leaf5__vlan40__vni110040 + vtep: ["leaf5"] vlan: ["40"] vni: ["110040"] description: "VLAN 40 <-> VNI 110040" - - vtep: ["leaf6"] + - local_identifier: leaf6__vlan40__vni110040 + vtep: ["leaf6"] vlan: ["40"] vni: ["110040"] description: "VLAN 40 <-> VNI 110040" @@ -140,26 +144,30 @@ spec: data: # EVPN instance for VLAN 40 on L2 VXLAN leafs # leaf1: rd 65001:110040, rt both 40:110040 - - device: ["leaf1"] + - local_identifier: leaf1__vlan40 + device: ["leaf1"] vlan: ["40"] route_distinguisher: "65001:110040" route_target_import: "40:110040" route_target_export: "40:110040" redistribute_learned: true - - device: ["leaf2"] + - local_identifier: leaf2__vlan40 + device: ["leaf2"] vlan: ["40"] route_distinguisher: "65001:110040" route_target_import: "40:110040" route_target_export: "40:110040" redistribute_learned: true # leaf5/6: rd 65003:110040, rt both 40:110040 - - device: ["leaf5"] + - local_identifier: leaf5__vlan40 + device: ["leaf5"] vlan: ["40"] route_distinguisher: "65003:110040" route_target_import: "40:110040" route_target_export: "40:110040" redistribute_learned: true - - device: ["leaf6"] + - local_identifier: leaf6__vlan40 + device: ["leaf6"] vlan: ["40"] route_distinguisher: "65003:110040" route_target_import: "40:110040" diff --git a/infrahub/objects/12-mlag.yml b/infrahub/objects/12-mlag.yml index 29b8e56..e1f460e 100644 --- a/infrahub/objects/12-mlag.yml +++ b/infrahub/objects/12-mlag.yml @@ -132,3 +132,49 @@ spec: heartbeat_peer_ip: "172.16.0.31" local_interface: ["leaf8", "Vlan4090"] peer_link: ["leaf8", "Port-Channel999"] +--- +apiVersion: infrahub.app/v1 +kind: Object +spec: + kind: InfraMlagInterface + data: + # MLAG interface 1 on leaf1/leaf2 pair (Port-Channel1 → host1) + - local_identifier: mlag1__leaf1-leaf2 + mlag_id: 1 + description: "MLAG interface 1 for leaf1/leaf2 pair (host1)" + lacp_fallback_timeout: 5 + lacp_fallback_individual: true + mlag_domain: ["leafs-1-2"] + lag_interfaces: + - ["leaf1", "Port-Channel1"] + - ["leaf2", "Port-Channel1"] + # MLAG interface 1 on leaf3/leaf4 pair (Port-Channel1 → host2) + - local_identifier: mlag1__leaf3-leaf4 + mlag_id: 1 + description: "MLAG interface 1 for leaf3/leaf4 pair (host2)" + lacp_fallback_timeout: 5 + lacp_fallback_individual: true + mlag_domain: ["leafs-3-4"] + lag_interfaces: + - ["leaf3", "Port-Channel1"] + - ["leaf4", "Port-Channel1"] + # MLAG interface 1 on leaf5/leaf6 pair (Port-Channel1 → host3) + - local_identifier: mlag1__leaf5-leaf6 + mlag_id: 1 + description: "MLAG interface 1 for leaf5/leaf6 pair (host3)" + lacp_fallback_timeout: 5 + lacp_fallback_individual: true + mlag_domain: ["leafs-5-6"] + lag_interfaces: + - ["leaf5", "Port-Channel1"] + - ["leaf6", "Port-Channel1"] + # MLAG interface 1 on leaf7/leaf8 pair (Port-Channel1 → host4) + - local_identifier: mlag1__leaf7-leaf8 + mlag_id: 1 + description: "MLAG interface 1 for leaf7/leaf8 pair (host4)" + lacp_fallback_timeout: 5 + lacp_fallback_individual: true + mlag_domain: ["leafs-7-8"] + lag_interfaces: + - ["leaf7", "Port-Channel1"] + - ["leaf8", "Port-Channel1"] diff --git a/infrahub/objects/14-fabric-links.yml b/infrahub/objects/14-fabric-links.yml index 175bb7c..ecec617 100644 --- a/infrahub/objects/14-fabric-links.yml +++ b/infrahub/objects/14-fabric-links.yml @@ -36,3 +36,175 @@ spec: - name: leaf8 role: leaf fabric: "evpn-lab" +--- +apiVersion: infrahub.app/v1 +kind: Object +spec: + kind: InfraUnderlayLink + data: + # ============================================================ + # Spine1 P2P underlay links (Ethernet1-8 → leaf1-8:Ethernet11) + # ============================================================ + - local_identifier: spine1-eth1__leaf1-eth11 + description: "spine1:Ethernet1 <-> leaf1:Ethernet11" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine1"] + local_interface: ["spine1", "Ethernet1"] + local_ip_address: ["10.0.1.0/31"] + remote_device: ["leaf1"] + remote_interface: ["leaf1", "Ethernet11"] + remote_ip_address: ["10.0.1.1/31"] + - local_identifier: spine1-eth2__leaf2-eth11 + description: "spine1:Ethernet2 <-> leaf2:Ethernet11" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine1"] + local_interface: ["spine1", "Ethernet2"] + local_ip_address: ["10.0.1.2/31"] + remote_device: ["leaf2"] + remote_interface: ["leaf2", "Ethernet11"] + remote_ip_address: ["10.0.1.3/31"] + - local_identifier: spine1-eth3__leaf3-eth11 + description: "spine1:Ethernet3 <-> leaf3:Ethernet11" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine1"] + local_interface: ["spine1", "Ethernet3"] + local_ip_address: ["10.0.1.4/31"] + remote_device: ["leaf3"] + remote_interface: ["leaf3", "Ethernet11"] + remote_ip_address: ["10.0.1.5/31"] + - local_identifier: spine1-eth4__leaf4-eth11 + description: "spine1:Ethernet4 <-> leaf4:Ethernet11" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine1"] + local_interface: ["spine1", "Ethernet4"] + local_ip_address: ["10.0.1.6/31"] + remote_device: ["leaf4"] + remote_interface: ["leaf4", "Ethernet11"] + remote_ip_address: ["10.0.1.7/31"] + - local_identifier: spine1-eth5__leaf5-eth11 + description: "spine1:Ethernet5 <-> leaf5:Ethernet11" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine1"] + local_interface: ["spine1", "Ethernet5"] + local_ip_address: ["10.0.1.8/31"] + remote_device: ["leaf5"] + remote_interface: ["leaf5", "Ethernet11"] + remote_ip_address: ["10.0.1.9/31"] + - local_identifier: spine1-eth6__leaf6-eth11 + description: "spine1:Ethernet6 <-> leaf6:Ethernet11" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine1"] + local_interface: ["spine1", "Ethernet6"] + local_ip_address: ["10.0.1.10/31"] + remote_device: ["leaf6"] + remote_interface: ["leaf6", "Ethernet11"] + remote_ip_address: ["10.0.1.11/31"] + - local_identifier: spine1-eth7__leaf7-eth11 + description: "spine1:Ethernet7 <-> leaf7:Ethernet11" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine1"] + local_interface: ["spine1", "Ethernet7"] + local_ip_address: ["10.0.1.12/31"] + remote_device: ["leaf7"] + remote_interface: ["leaf7", "Ethernet11"] + remote_ip_address: ["10.0.1.13/31"] + - local_identifier: spine1-eth8__leaf8-eth11 + description: "spine1:Ethernet8 <-> leaf8:Ethernet11" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine1"] + local_interface: ["spine1", "Ethernet8"] + local_ip_address: ["10.0.1.14/31"] + remote_device: ["leaf8"] + remote_interface: ["leaf8", "Ethernet11"] + remote_ip_address: ["10.0.1.15/31"] + # ============================================================ + # Spine2 P2P underlay links (Ethernet1-8 → leaf1-8:Ethernet12) + # ============================================================ + - local_identifier: spine2-eth1__leaf1-eth12 + description: "spine2:Ethernet1 <-> leaf1:Ethernet12" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine2"] + local_interface: ["spine2", "Ethernet1"] + local_ip_address: ["10.0.2.0/31"] + remote_device: ["leaf1"] + remote_interface: ["leaf1", "Ethernet12"] + remote_ip_address: ["10.0.2.1/31"] + - local_identifier: spine2-eth2__leaf2-eth12 + description: "spine2:Ethernet2 <-> leaf2:Ethernet12" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine2"] + local_interface: ["spine2", "Ethernet2"] + local_ip_address: ["10.0.2.2/31"] + remote_device: ["leaf2"] + remote_interface: ["leaf2", "Ethernet12"] + remote_ip_address: ["10.0.2.3/31"] + - local_identifier: spine2-eth3__leaf3-eth12 + description: "spine2:Ethernet3 <-> leaf3:Ethernet12" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine2"] + local_interface: ["spine2", "Ethernet3"] + local_ip_address: ["10.0.2.4/31"] + remote_device: ["leaf3"] + remote_interface: ["leaf3", "Ethernet12"] + remote_ip_address: ["10.0.2.5/31"] + - local_identifier: spine2-eth4__leaf4-eth12 + description: "spine2:Ethernet4 <-> leaf4:Ethernet12" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine2"] + local_interface: ["spine2", "Ethernet4"] + local_ip_address: ["10.0.2.6/31"] + remote_device: ["leaf4"] + remote_interface: ["leaf4", "Ethernet12"] + remote_ip_address: ["10.0.2.7/31"] + - local_identifier: spine2-eth5__leaf5-eth12 + description: "spine2:Ethernet5 <-> leaf5:Ethernet12" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine2"] + local_interface: ["spine2", "Ethernet5"] + local_ip_address: ["10.0.2.8/31"] + remote_device: ["leaf5"] + remote_interface: ["leaf5", "Ethernet12"] + remote_ip_address: ["10.0.2.9/31"] + - local_identifier: spine2-eth6__leaf6-eth12 + description: "spine2:Ethernet6 <-> leaf6:Ethernet12" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine2"] + local_interface: ["spine2", "Ethernet6"] + local_ip_address: ["10.0.2.10/31"] + remote_device: ["leaf6"] + remote_interface: ["leaf6", "Ethernet12"] + remote_ip_address: ["10.0.2.11/31"] + - local_identifier: spine2-eth7__leaf7-eth12 + description: "spine2:Ethernet7 <-> leaf7:Ethernet12" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine2"] + local_interface: ["spine2", "Ethernet7"] + local_ip_address: ["10.0.2.12/31"] + remote_device: ["leaf7"] + remote_interface: ["leaf7", "Ethernet12"] + remote_ip_address: ["10.0.2.13/31"] + - local_identifier: spine2-eth8__leaf8-eth12 + description: "spine2:Ethernet8 <-> leaf8:Ethernet12" + mtu: 9214 + fabric: ["evpn-lab"] + local_device: ["spine2"] + local_interface: ["spine2", "Ethernet8"] + local_ip_address: ["10.0.2.14/31"] + remote_device: ["leaf8"] + remote_interface: ["leaf8", "Ethernet12"] + remote_ip_address: ["10.0.2.15/31"] diff --git a/infrahub/schemas/extensions.yml b/infrahub/schemas/extensions.yml index fb5517d..ebe647d 100644 --- a/infrahub/schemas/extensions.yml +++ b/infrahub/schemas/extensions.yml @@ -74,8 +74,15 @@ nodes: label: Underlay Link icon: mdi--cable-data include_in_menu: false + uniqueness_constraints: + - ["local_identifier__value"] + human_friendly_id: + - local_identifier__value display_label: "{{ description__value }}" attributes: + - name: local_identifier + kind: Text + description: "Unique identifier combining local and remote device/interface (e.g. spine1-eth1__leaf1-eth11)" - name: description kind: Text description: Link description (e.g., spine1:eth1 <-> leaf1:eth11) diff --git a/infrahub/schemas/mlag.yml b/infrahub/schemas/mlag.yml index 832395d..a245115 100644 --- a/infrahub/schemas/mlag.yml +++ b/infrahub/schemas/mlag.yml @@ -114,8 +114,15 @@ nodes: label: MLAG Interface icon: mdi--ethernet-cable include_in_menu: false + uniqueness_constraints: + - ["local_identifier__value"] + human_friendly_id: + - local_identifier__value display_label: "{{ mlag_id__value }}" attributes: + - name: local_identifier + kind: Text + description: "Unique identifier combining mlag_id and peer devices (e.g. mlag1__leaf1-leaf2)" - name: mlag_id kind: Number description: MLAG interface ID diff --git a/infrahub/schemas/vlan_vxlan.yml b/infrahub/schemas/vlan_vxlan.yml index a8d28a0..33cc0aa 100644 --- a/infrahub/schemas/vlan_vxlan.yml +++ b/infrahub/schemas/vlan_vxlan.yml @@ -174,8 +174,15 @@ nodes: label: VLAN-VNI Mapping icon: mdi--swap-horizontal include_in_menu: false + uniqueness_constraints: + - ["local_identifier__value"] + human_friendly_id: + - local_identifier__value display_label: "{{ description__value }}" attributes: + - name: local_identifier + kind: Text + description: "Unique identifier combining device name, VLAN ID and VNI (e.g. leaf1__vlan40__vni110040)" - name: description kind: Text optional: true @@ -202,8 +209,15 @@ nodes: label: EVPN Instance icon: mdi--cloud-sync include_in_menu: false + uniqueness_constraints: + - ["local_identifier__value"] + human_friendly_id: + - local_identifier__value display_label: "{{ route_distinguisher__value }}" attributes: + - name: local_identifier + kind: Text + description: "Unique identifier combining device name and VLAN ID (e.g. leaf1__vlan40)" - name: route_distinguisher kind: Text description: "Route Distinguisher (format: ASN:VNI or IP:VNI)"