feature/52-object-files #53

Merged
Damien merged 29 commits from feature/52-object-files into main 2026-02-20 15:14:03 +00:00
Showing only changes of commit 5a335b37e6 - Show all commits

171
CLAUDE.md
View File

@@ -4,7 +4,34 @@
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`
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)
@@ -12,71 +39,123 @@ Branch: `feature/41-infrahub-schema`
- 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
- 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)
## Schema Files (Infrahub YAML format, in `schemas/`)
### IP Addressing Quick Reference
| 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 |
| 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 |
## Infrahub Schema Rules
### P2P Addressing Pattern
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 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
- 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
infrahubctl schema check schemas/
# 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 run before committing. Fix any errors before pushing.
Always validate before committing. Fix any errors before pushing.
## Commit Convention
```
fix(schema): short description — refs #<issue>
feat(schema): short description — refs #<issue>
feat(objects): short description — refs #52
```
- 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.
- One logical file per commit (or group of closely related files)
- Reference issue #52
## 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
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 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
- 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