## 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
206 lines
8.0 KiB
JSON
206 lines
8.0 KiB
JSON
{
|
|
"data": {
|
|
"InfraBGPRouterConfig": {
|
|
"edges": [
|
|
{
|
|
"node": {
|
|
"router_id": { "value": "10.0.250.17" },
|
|
"default_ipv4_unicast": { "value": false },
|
|
"log_neighbor_changes": { "value": true },
|
|
"ecmp_max_paths": { "value": 4 },
|
|
"ecmp_max_ecmp": { "value": 64 },
|
|
"ebgp_distance": { "value": 20 },
|
|
"ibgp_distance": { "value": 200 },
|
|
"local_distance": { "value": 200 },
|
|
"local_asn": {
|
|
"node": {
|
|
"asn": { "value": 65004 }
|
|
}
|
|
},
|
|
"peer_groups": {
|
|
"edges": [
|
|
{
|
|
"node": {
|
|
"name": { "value": "underlay" },
|
|
"peer_group_type": { "value": "underlay" },
|
|
"update_source": { "value": null },
|
|
"ebgp_multihop": { "value": null },
|
|
"send_community": { "value": "none" },
|
|
"next_hop_self": { "value": false },
|
|
"next_hop_unchanged": { "value": false },
|
|
"maximum_routes": { "value": 12000 },
|
|
"maximum_routes_warning_only": { "value": true },
|
|
"remote_asn": {
|
|
"node": {
|
|
"asn": { "value": 65000 }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"node": {
|
|
"name": { "value": "underlay_ibgp" },
|
|
"peer_group_type": { "value": "underlay_ibgp" },
|
|
"update_source": { "value": null },
|
|
"ebgp_multihop": { "value": null },
|
|
"send_community": { "value": "none" },
|
|
"next_hop_self": { "value": true },
|
|
"next_hop_unchanged": { "value": false },
|
|
"maximum_routes": { "value": 12000 },
|
|
"maximum_routes_warning_only": { "value": true },
|
|
"remote_asn": {
|
|
"node": {
|
|
"asn": { "value": 65004 }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"node": {
|
|
"name": { "value": "evpn" },
|
|
"peer_group_type": { "value": "evpn" },
|
|
"update_source": { "value": "Loopback0" },
|
|
"ebgp_multihop": { "value": 3 },
|
|
"send_community": { "value": "extended" },
|
|
"next_hop_self": { "value": false },
|
|
"next_hop_unchanged": { "value": false },
|
|
"maximum_routes": { "value": 12000 },
|
|
"maximum_routes_warning_only": { "value": true },
|
|
"remote_asn": {
|
|
"node": {
|
|
"asn": { "value": 65000 }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"sessions": {
|
|
"edges": [
|
|
{
|
|
"node": {
|
|
"peer_address": { "value": "10.0.1.12" },
|
|
"description": { "value": "underlay to spine1" },
|
|
"enabled": { "value": true },
|
|
"peer_group": { "node": { "name": { "value": "underlay" }, "local_identifier": { "value": "leaf7__underlay" } } },
|
|
"remote_asn": { "node": null },
|
|
"vrf": { "node": null },
|
|
"peer_device": { "node": { "name": { "value": "spine1" } } }
|
|
}
|
|
},
|
|
{
|
|
"node": {
|
|
"peer_address": { "value": "10.0.2.12" },
|
|
"description": { "value": "underlay to spine2" },
|
|
"enabled": { "value": true },
|
|
"peer_group": { "node": { "name": { "value": "underlay" }, "local_identifier": { "value": "leaf7__underlay" } } },
|
|
"remote_asn": { "node": null },
|
|
"vrf": { "node": null },
|
|
"peer_device": { "node": { "name": { "value": "spine2" } } }
|
|
}
|
|
},
|
|
{
|
|
"node": {
|
|
"peer_address": { "value": "10.0.3.7" },
|
|
"description": { "value": "iBGP to leaf8" },
|
|
"enabled": { "value": true },
|
|
"peer_group": { "node": { "name": { "value": "underlay_ibgp" }, "local_identifier": { "value": "leaf7__underlay_ibgp" } } },
|
|
"remote_asn": { "node": null },
|
|
"vrf": { "node": null },
|
|
"peer_device": { "node": { "name": { "value": "leaf8" } } }
|
|
}
|
|
},
|
|
{
|
|
"node": {
|
|
"peer_address": { "value": "10.0.250.1" },
|
|
"description": { "value": "EVPN to spine1" },
|
|
"enabled": { "value": true },
|
|
"peer_group": { "node": { "name": { "value": "evpn" }, "local_identifier": { "value": "leaf7__evpn" } } },
|
|
"remote_asn": { "node": null },
|
|
"vrf": { "node": null },
|
|
"peer_device": { "node": { "name": { "value": "spine1" } } }
|
|
}
|
|
},
|
|
{
|
|
"node": {
|
|
"peer_address": { "value": "10.0.250.2" },
|
|
"description": { "value": "EVPN to spine2" },
|
|
"enabled": { "value": true },
|
|
"peer_group": { "node": { "name": { "value": "evpn" }, "local_identifier": { "value": "leaf7__evpn" } } },
|
|
"remote_asn": { "node": null },
|
|
"vrf": { "node": null },
|
|
"peer_device": { "node": { "name": { "value": "spine2" } } }
|
|
}
|
|
},
|
|
{
|
|
"node": {
|
|
"peer_address": { "value": "10.90.90.1" },
|
|
"description": { "value": "border peering to AS 64999 in VRF gold" },
|
|
"enabled": { "value": true },
|
|
"peer_group": { "node": null },
|
|
"remote_asn": { "node": { "asn": { "value": 64999 } } },
|
|
"vrf": { "node": { "name": { "value": "gold" } } },
|
|
"peer_device": { "node": null }
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"InfraBGPAddressFamily": {
|
|
"edges": [
|
|
{
|
|
"node": {
|
|
"afi": { "value": "ipv4" },
|
|
"safi": { "value": "unicast" },
|
|
"vrf": { "node": null },
|
|
"active_peer_groups": {
|
|
"edges": [
|
|
{ "node": { "name": { "value": "underlay" } } },
|
|
{ "node": { "name": { "value": "underlay_ibgp" } } }
|
|
]
|
|
},
|
|
"active_sessions": { "edges": [] },
|
|
"networks": {
|
|
"edges": [
|
|
{ "node": { "address": { "value": "10.0.250.17/32" } } },
|
|
{ "node": { "address": { "value": "10.0.255.14/32" } } }
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"node": {
|
|
"afi": { "value": "evpn" },
|
|
"safi": { "value": "unicast" },
|
|
"vrf": { "node": null },
|
|
"active_peer_groups": {
|
|
"edges": [
|
|
{ "node": { "name": { "value": "evpn" } } }
|
|
]
|
|
},
|
|
"active_sessions": { "edges": [] },
|
|
"networks": { "edges": [] }
|
|
}
|
|
},
|
|
{
|
|
"node": {
|
|
"afi": { "value": "ipv4" },
|
|
"safi": { "value": "unicast" },
|
|
"vrf": { "node": { "name": { "value": "gold" } } },
|
|
"active_peer_groups": { "edges": [] },
|
|
"active_sessions": {
|
|
"edges": [
|
|
{ "node": { "peer_address": { "value": "10.90.90.1" } } }
|
|
]
|
|
},
|
|
"networks": { "edges": [] }
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|