Files
arista-evpn-vxlan-clab/infrahub/transforms/tests/bgp_yang/leaf7/output.json
Damien Arnodo 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

141 lines
3.2 KiB
JSON

{
"bgp": {
"global": {
"asn": 65004,
"router_id": "10.0.250.17",
"default_ipv4_unicast": false,
"log_neighbor_changes": true,
"distance": {
"ebgp": 20,
"ibgp": 200,
"local": 200
},
"ecmp": {
"max_paths": 4,
"max_ecmp": 64
}
},
"peer_groups": [
{
"name": "underlay",
"type": "underlay",
"remote_asn": 65000,
"update_source": null,
"ebgp_multihop": null,
"send_community": null,
"next_hop_self": false,
"next_hop_unchanged": false,
"maximum_routes": 12000,
"maximum_routes_warning_only": true
},
{
"name": "underlay_ibgp",
"type": "underlay_ibgp",
"remote_asn": 65004,
"update_source": null,
"ebgp_multihop": null,
"send_community": null,
"next_hop_self": true,
"next_hop_unchanged": false,
"maximum_routes": 12000,
"maximum_routes_warning_only": true
},
{
"name": "evpn",
"type": "evpn",
"remote_asn": 65000,
"update_source": "Loopback0",
"ebgp_multihop": 3,
"send_community": "extended",
"next_hop_self": false,
"next_hop_unchanged": false,
"maximum_routes": 12000,
"maximum_routes_warning_only": true
}
],
"neighbors": [
{
"peer_address": "10.0.1.12",
"description": "underlay to spine1",
"enabled": true,
"peer_group": "underlay",
"remote_asn": null
},
{
"peer_address": "10.0.2.12",
"description": "underlay to spine2",
"enabled": true,
"peer_group": "underlay",
"remote_asn": null
},
{
"peer_address": "10.0.3.7",
"description": "iBGP to leaf8",
"enabled": true,
"peer_group": "underlay_ibgp",
"remote_asn": null
},
{
"peer_address": "10.0.250.1",
"description": "EVPN to spine1",
"enabled": true,
"peer_group": "evpn",
"remote_asn": null
},
{
"peer_address": "10.0.250.2",
"description": "EVPN to spine2",
"enabled": true,
"peer_group": "evpn",
"remote_asn": null
}
],
"address_families": [
{
"afi": "ipv4",
"safi": "unicast",
"active_peer_groups": [
"underlay",
"underlay_ibgp"
],
"active_sessions": [],
"networks": [
"10.0.250.17/32",
"10.0.255.14/32"
]
},
{
"afi": "evpn",
"safi": "unicast",
"active_peer_groups": [
"evpn"
],
"active_sessions": [],
"networks": []
}
],
"vrf_neighbors": [
{
"peer_address": "10.90.90.1",
"description": "border peering to AS 64999 in VRF gold",
"enabled": true,
"peer_group": null,
"remote_asn": 64999,
"vrf": "gold"
}
],
"vrf_address_families": [
{
"afi": "ipv4",
"safi": "unicast",
"vrf": "gold",
"active_peer_groups": [],
"active_sessions": [
"10.90.90.1"
],
"networks": []
}
]
}
}