feature/52-object-files #53
171
CLAUDE.md
171
CLAUDE.md
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user