# Claude Code Instructions — fabric-orchestrator ## Project Context Fabric-orchestrator manages Arista EVPN-VXLAN fabrics using Infrahub as the source of truth. Gitea: https://gitea.arnodo.fr/Damien/fabric-orchestrator Branch: `feature/52-object-files` ## Current Task: Issue #52 — Create Infrahub Object Files Create YAML object files to load the reference topology data into Infrahub. Object files use the `apiVersion: infrahub.app/v1` format and are loaded via `infrahubctl object load`. ### Data Sources (read-only references) - **Arista configs**: https://gitea.arnodo.fr/Damien/arista-evpn-vxlan-clab (`configs/*.cfg`) - **Reference article**: overlaid.net EVPN Configuration Example (document `arista-bgp-evpn-configuration-example-overlaid.md` if available locally) - **These configs are the source of truth** — extract all IPs, ASNs, peer groups, VLANs, VNIs from them ### Target Structure ``` objects/ ├── 01-foundation.yml # InfraFabric, InfraAutonomousSystem ├── 02-devices.yml # InfraDevice (10 devices) ├── 03-interfaces.yml # InterfaceLoopback, InterfaceEthernet, InterfaceLag, InterfaceVlan ├── 04-ipam.yml # InfraIPAddress (all /31, /32, /24 assignments) ├── 05-vlans-vxlan.yml # InfraVLAN, InfraVNI, InfraVTEP, InfraVlanVniMapping, InfraEVPNInstance ├── 06-bgp.yml # InfraBGPRouterConfig, InfraBGPPeerGroup, InfraBGPSession, InfraBGPAddressFamily ├── 07-vrfs.yml # InfraVRF, InfraRouteTarget └── 08-mlag.yml # InfraMlagDomain, InfraMlagPeerConfig ``` **Order matters**: files are loaded sequentially, dependencies must be satisfied (devices before interfaces, interfaces before IPs, etc.). ## 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 with next-hop-unchanged - L2VXLAN: VLAN 40 → VNI 110040, redistribute learned - L3VXLAN: VRF gold → VNI 100001, redistribute connected (leaf3-4, leaf7-8) - Border peering: BGP sessions inside VRF (leaf7/8 → AS 64999 in VRF gold) ### IP Addressing Quick Reference | Device | Lo0 (router-id) | Lo1 (VTEP) | AS | |---------|------------------|--------------|-------| | spine1 | 10.0.250.1 | — | 65000 | | spine2 | 10.0.250.2 | — | 65000 | | leaf1 | 10.0.250.11 | 10.0.255.11 | 65001 | | leaf2 | 10.0.250.12 | 10.0.255.11 | 65001 | | leaf3 | 10.0.250.13 | 10.0.255.12 | 65002 | | leaf4 | 10.0.250.14 | 10.0.255.12 | 65002 | | leaf5 | 10.0.250.15 | 10.0.255.13 | 65003 | | leaf6 | 10.0.250.16 | 10.0.255.13 | 65003 | | leaf7 | 10.0.250.17 | 10.0.255.14 | 65004 | | leaf8 | 10.0.250.18 | 10.0.255.14 | 65004 | ### P2P Addressing Pattern - spine1→leaf{N}: `10.0.1.{(N-1)*2}/31` (spine side) / `10.0.1.{(N-1)*2+1}/31` (leaf side) - spine2→leaf{N}: `10.0.2.{(N-1)*2}/31` (spine side) / `10.0.2.{(N-1)*2+1}/31` (leaf side) - MLAG iBGP: leaf pairs on `10.0.3.{pair_offset}/31` - MLAG peer: leaf pairs on `10.0.199.254/31` and `10.0.199.255/31` ## Infrahub Object File Format ```yaml --- apiVersion: infrahub.app/v1 kind: Object spec: kind: InfraDevice data: - name: spine1 role: spine platform: arista_eos # References InfraPlatform by HFID ``` ### Key Rules 1. **Reference existing objects by their `human_friendly_id` (HFID)** — not by ID 2. For relationships with cardinality one, use the HFID value directly: `site: "dc1"` 3. For relationships with cardinality many, use a list: `vlans: ["40", "4090"]` 4. For nested objects (Component kind), use inline `data:` blocks 5. For multi-field HFIDs, use list format: `device: ["spine1", "Loopback0"]` → references `device__name + interface__name` ### Schema human_friendly_id Reference (critical for references) | Node | HFID fields | |-----------------------|------------------------------------------------| | InfraDevice | `name__value` | | InfraAutonomousSystem | `asn__value` | | InfraInterfaceEthernet| `device__name__value` + `name__value` | | InfraInterfaceLoopback| `device__name__value` + `name__value` | | InfraInterfaceVlan | `device__name__value` + `name__value` | | InfraInterfaceLag | `device__name__value` + `name__value` | | InfraIPAddress | `address__value` | | InfraVLAN | `vlan_id__value` | | InfraVNI | `vni__value` | | InfraVTEP | `device__name__value` | | InfraBGPRouterConfig | `device__name__value` | | InfraBGPPeerGroup | `bgp_config__router_id__value` + `name__value` | | InfraBGPSession | `bgp_config__router_id__value` + `peer_address__value` | | InfraVLAN | `vlan_id__value` | | InfraFabric | `name__value` | | LocationSite | `name__value` | | InfraPlatform | `name__value` | ## Schema Files (in `schemas/`) | File | Content | |-------------------|-----------------------------------------------------------------------| | `base.yml` | Device, Interfaces (Ethernet, Loopback, Vlan, Lag), IPAddress, Site, Platform | | `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` | Fabric, UnderlayLink, HostConnection | ## Validation ```bash # Validate object file format infrahubctl object validate objects/01-foundation.yml # Load objects sequentially infrahubctl object load objects/01-foundation.yml infrahubctl object load objects/02-devices.yml # ... etc. ``` Always validate before committing. Fix any errors before pushing. ## Commit Convention ``` feat(objects): short description — refs #52 ``` - One logical file per commit (or group of closely related files) - Reference issue #52 ## Workflow 1. Read the relevant schema file to understand required fields and relationships 2. Extract data from the clab configs (configs/*.cfg) or the reference topology doc 3. Create the object file respecting the Infrahub Object File format 4. Validate with `infrahubctl object validate` 5. Commit with proper message ## Don'ts - Don't invent data not present in the reference topology configs - Don't create schema modifications — the schema is frozen for this task - Don't skip optional fields that have data in the configs (description, mtu, etc.) - Don't forget the dependency order: foundation → devices → interfaces → IPs → rest - Don't use `id` references — always use human_friendly_id (HFID) strings