Damien
37b3261416
fix: add human_friendly_id to 4 schemas for idempotent Repository sync
...
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 <noreply@anthropic.com >
2026-03-03 17:19:30 +01:00
68b9e88483
docs: Add README for Infrahub transforms ( #28 )
...
Adds a concise README in `infrahub/transforms/` documenting the 6 available Jinja2 transforms, usage commands, directory structure, and how to add new transforms.
Reviewed-on: #28
2026-03-01 16:29:40 +00:00
1b918a4cbc
feat: Add Infrahub Jinja2 transform for BGP configuration ( #23 ) ( #27 )
...
## Summary
Closes #23 . Implements a single unified `bgp_yang_transform` covering the complete BGP router stanza for all 10 fabric devices.
**Design decision:** One transform (one query + one template) rather than 4 separate transforms, because all BGP components (process config, peer groups, neighbors, AFs) live under a single `router bgp <ASN>` stanza and must be consistent. This avoids multiple API calls per device and keeps the data model coherent.
| File | Description |
|------|-------------|
| `infrahub/transforms/queries/bgp_intent.gql` | Unified GraphQL query — `InfraBGPRouterConfig` (with peer_groups, sessions) + `InfraBGPAddressFamily` (with active_peer_groups, active_sessions, networks, optional vrf) |
| `infrahub/transforms/templates/bgp_yang.j2` | Jinja2 template — renders `bgp.global`, `bgp.peer_groups`, `bgp.neighbors`, `bgp.address_families`, `bgp.vrf_neighbors`, `bgp.vrf_address_families`; returns `[]` for devices with no BGP config |
| `infrahub/transforms/tests/bgp_yang/test.yml` | Smoke check + unit render tests for leaf1, spine1, leaf7 |
| `infrahub/transforms/tests/bgp_yang/leaf1/` | 3 peer-groups, 5 global neighbors, 2 global AFs |
| `infrahub/transforms/tests/bgp_yang/spine1/` | 1 peer-group (evpn/next-hop-unchanged), 16 neighbors (8 direct underlay + 8 EVPN), IPv4 AF activates individual sessions |
| `infrahub/transforms/tests/bgp_yang/leaf7/` | leaf1 pattern + VRF gold border session (AS 64999) + VRF-scoped IPv4 unicast AF |
| `.infrahub.yml` | Registers `bgp_intent` query and `bgp_yang_transform` |
## Validation
| Device | Expected output |
|--------|----------------|
| `leaf1` | 3 peer-groups, 5 global neighbors (underlay×2, iBGP×1, EVPN×2), 2 AFs, empty VRF sections |
| `spine1` | 1 peer-group (evpn, next-hop-unchanged), 16 neighbors (8 direct with `remote_asn`, 8 EVPN via peer-group), IPv4 AF activates individual sessions |
| `leaf7` | Same as leaf1 (AS 65004) + `vrf_neighbors: [{10.90.90.1, AS 64999, VRF gold}]` + `vrf_address_families: [{ipv4, VRF gold, active_sessions: [10.90.90.1]}]` |
```bash
infrahubctl render bgp_yang_transform device_name=leaf1
infrahubctl render bgp_yang_transform device_name=spine1
infrahubctl render bgp_yang_transform device_name=leaf7
```
## Design notes
- Follows identical conventions to existing transforms (#20–#22)
- All optional relationships (`remote_asn`, `peer_group`, `vrf`, `peer_device`, `update_source`, etc.) wrapped in `is defined and is not none` guards
- `send_community` value `"none"` (schema default) is normalised to `null` in the output — keeps the rendered JSON clean for downstream consumers
- VRF-scoped sessions and AFs are separated into `vrf_neighbors` / `vrf_address_families` arrays, each entry carrying a `"vrf"` key, so the template consumer can trivially iterate per-VRF without filtering
2026-03-01 13:22:51 +00:00
cf7da535ed
feat: Add Infrahub Jinja2 transforms for MLAG configuration ( #22 ) ( #26 )
...
## Summary
Closes #22 . Implements Infrahub Jinja2 transforms for MLAG configuration, generating Arista-native YANG-compatible JSON payloads from Infrahub intent data.
| File | Description |
|------|-------------|
| `infrahub/transforms/queries/mlag_intent.gql` | GraphQL query — fetches `InfraMlagPeerConfig` by `$device_name`, including MLAG domain attributes, peer/iBGP VLANs, local interface SVI, and peer-link LAG |
| `infrahub/transforms/templates/mlag_yang.j2` | Jinja2 template — renders a JSON object targeting `/arista-mlag-augments:mlag/config`; returns `[]` for devices with no MLAG (spines) |
| `infrahub/transforms/tests/mlag_yang/test.yml` | Test spec: smoke check + unit render tests for `leaf1` and `spine1` |
| `infrahub/transforms/tests/mlag_yang/leaf1/` | Mock input + expected output for leaf1 (full MLAG config, domain `leafs-1-2`) |
| `infrahub/transforms/tests/mlag_yang/spine1/` | Mock input (empty edges) + expected output `[]` for spine1 |
| `.infrahub.yml` | Registers `mlag_intent` query and `mlag_yang_transform` jinja2 transform |
## Output shape (leaf1)
```json
{
"mlag": {
"config": {
"domain-id": "leafs-1-2",
"peer-link": "Port-Channel999",
"local-interface": "Vlan4090",
"peer-address": "10.0.199.255",
"shutdown": false
},
"dual_primary_detection": {
"enabled": true,
"delay": 10,
"action": "errdisable",
"heartbeat_peer_ip": "172.16.0.50",
"heartbeat_vrf": "mgmt"
},
"virtual_mac": "c001.cafe.babe",
"peer_vlan_id": 4090,
"ibgp_vlan_id": 4091,
"local_interface_ip": "10.0.199.254/31"
}
}
```
## Validation
```bash
infrahubctl render mlag_yang_transform device_name=leaf1 # → MLAG config JSON
infrahubctl render mlag_yang_transform device_name=spine1 # → []
```
## Design notes
- Follows identical conventions to existing transforms (#20 VLAN/interface/VXLAN, #21 VRF/L3VNI)
- All optional relationship accesses wrapped in `is defined and is not none` guards
- Spine/non-MLAG devices return `[]` (empty array) — consistent with the "no data → empty collection" pattern used in vxlan_yang for devices without VTEP
2026-03-01 11:06:55 +00:00
a105e44bbd
feat: Add Infrahub Jinja2 transform for VRF/L3VNI configuration ( #21 ) ( #25 )
...
## Summary
Implements Infrahub Jinja2 Transform for VRF/L3VNI configuration, generating structured JSON payloads from Infrahub intent data. Closes #21 .
## What's included
- **GraphQL query** (`transforms/queries/vrf_intent.gql`): Queries `InfraVRFDeviceAssignment` by device name, fetching VRF details, L3VNI, route targets, and device-specific route distinguisher
- **Jinja2 transform** (`transforms/templates/vrf_yang.j2`): Renders VRF config payloads with defensive null handling (lessons learned from #20 )
- **`.infrahub.yml`** updated with the new query and transform definitions
- **Tests** (`transforms/tests/vrf_yang/`) using correct Infrahub pytest format (`jinja2-transform-smoke` + `jinja2-transform-unit-render`)
## Validation
All transforms render correctly:
| Device | Expected | Result |
|--------|----------|--------|
| `leaf3` | VRF gold, RD `10.0.250.13:1`, L3VNI 100001 | ✅ |
| `leaf7` | VRF gold, RD `10.0.250.17:1`, L3VNI 100001 | ✅ |
| `leaf1` | Empty array (no VRF assignment) | ✅ |
| `spine1` | Empty array (no VRF assignment) | ✅ |
## Usage
```bash
# Local debugging
infrahubctl render vrf_yang_transform device_name=leaf3
# API endpoint
GET /api/transform/jinja2/vrf_yang_transform?device_name=leaf3
```
## Related
- Depends on: #20 (base transforms infrastructure, already merged)
- Reference: Arista EVPN Type-5 / L3VXLAN configuration from lab topology
2026-03-01 10:45:01 +00:00
668e9cbada
feat: Add Infrahub Jinja2 transforms for VLANs, interfaces, and VXLAN ( #20 ) ( #24 )
...
## Summary
Closes #20
Adds Infrahub Jinja2 transforms that query device intent from Infrahub via GraphQL and produce structured JSON payloads (YANG-style) suitable for gNMI Set operations on Arista EOS devices.
- **3 GraphQL queries** — `vlan_intent`, `interface_intent`, `vxlan_intent` — each parameterized by `$device_name`
- **3 Jinja2 templates** — `vlan_yang.j2`, `interface_yang.j2`, `vxlan_yang.j2` — producing JSON arrays/objects from the GraphQL response
- **Integration test fixtures** — one directory per transform with `input.json`, `output.json`, and `test.yml`, using leaf1 from the lab topology as sample device
- **`.infrahub.yml` updated** with `queries` and `jinja2_transforms` sections
## Files added
```
transforms/
├── queries/
│ ├── vlan_intent.gql # VLANs via VTEP mappings + SVI interfaces
│ ├── interface_intent.gql # All interface types with IPs
│ └── vxlan_intent.gql # VTEP config + VLAN/VNI/VRF mappings
├── templates/
│ ├── vlan_yang.j2 # JSON array of VLANs (merged, deduplicated, sorted)
│ ├── interface_yang.j2 # JSON array of interfaces with type discriminator
│ └── vxlan_yang.j2 # JSON object: vtep + vlan_vni + vrf_vni mappings
└── tests/
├── vlan_yang/{input,output,test}.{json,yml}
├── interface_yang/{input,output,test}.{json,yml}
└── vxlan_yang/{input,output,test}.{json,yml}
```
## Transform usage
```bash
# Render locally
infrahubctl render vlan_yang_transform device_name=leaf1
infrahubctl render interface_yang_transform device_name=leaf1
infrahubctl render vxlan_yang_transform device_name=leaf1
# Via API
GET /api/transform/jinja2/vlan_yang_transform?device_name=leaf1
GET /api/transform/jinja2/interface_yang_transform?device_name=leaf1
GET /api/transform/jinja2/vxlan_yang_transform?device_name=leaf1
```
## Test plan
- [x] Load branch into Infrahub (`infrahubctl schema load` + `infrahubctl object load`)
- [x] Run `infrahubctl render vlan_yang_transform device_name=leaf1` and verify JSON output matches expected VLANs (40, 4090, 4091)
- [x] Run `infrahubctl render interface_yang_transform device_name=leaf1` and verify all interface types are present with correct attributes
- [x] Run `infrahubctl render vxlan_yang_transform device_name=leaf1` and verify VTEP source address, UDP port, and VLAN-VNI mapping for VLAN 40 / VNI 110040
- [x] Run `infrahubctl render vxlan_yang_transform device_name=leaf3` and verify VRF gold / L3VNI 100001 appears in `vrf_vni_mappings`
- ~~[ ] Verify `infrahubctl test` passes for all three test fixtures~~
Reviewed-on: #24
2026-02-28 17:42:08 +00:00
Damien
ac1634b561
Add device roles to fabric links
2026-02-22 10:07:27 +01:00
Damien
9a0b6dd1e6
feat(schema): add bidirectional relationship identifiers and fabric-device links
...
- LocationSite: add devices (device__site) and fabrics (fabric__sites) reverse relationships
- InfraDevice.site: add identifier device__site
- InfraDevice: add fabric relationship (fabric__devices)
- InfraFabric.sites: add identifier fabric__sites; add devices reverse relationship (fabric__devices)
- InfraInterfaceVlan.vlan: add identifier vlan__svi
- InfraVLAN: add svi_interfaces reverse relationship (vlan__svi)
- Add 14-fabric-links.yml to assign all 10 devices to the evpn-lab fabric
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-21 20:59:10 +01:00
Damien
2c1fccee5b
Remove IP addresses from interfaces and add new IPAM links file
2026-02-21 18:08:53 +01:00
Damien
e778fedf71
Add IP addresses to loopback and VLAN interfaces
2026-02-21 18:03:19 +01:00
Damien
4aecc544da
Refactor interface references to use structured format
...
Refactored all interface references in IPAM configuration to use the
structured format with kind and data fields instead of simple lists.
This improves consistency and makes the configuration more maintainable.
2026-02-21 17:41:11 +01:00
Damien
807f3ce8a1
refactor(ipam): simplify interface references to compact array format
...
Replace verbose interface definitions using node/kind objects with
concise [device, interface] array notation across all IPAM address
entries. This reduces verbosity and improves readability of the
IP address assignments for loopbacks and P2P underlay links.
2026-02-21 16:13:31 +01:00
Damien
e9dad132ea
feat(ipam): add interface associations to IP addresses
...
Add interface node and kind to all IP address entries in the IPAM configuration file. This change enhances the IPAM configuration by explicitly associating each IP address with its corresponding interface, improving clarity and maintainability of the network configuration.
The changes include:
- Adding interface node and kind for all Router-ID Loopback0 addresses
- Adding interface node and kind for all VTEP Loopback1 addresses
- Adding interface node and kind for all spine and leaf P2P underlay addresses
- Maintaining consistent format across all IP address entries
2026-02-21 16:02:54 +01:00
Damien
e353ef0a90
Update MLAG schema to use IPHost instead of IPNetwork for local
...
interface IP
2026-02-21 11:48:13 +01:00
Damien
6dd4cc96ef
fix(InfraBGPSessionUpsert): changeing load order of objects
2026-02-21 10:02:17 +01:00
Damien
1b25c92965
build(infrahub): update file paths to match new directory structure
...
Refactor the .infrahub.yml configuration file to prefix all schema, menu, and object paths with the 'infrahub/' directory. This change aligns the configuration with the reorganized project structure where Infrahub resources have been moved into a dedicated subfolder.
2026-02-20 18:33:37 +01:00