feat: Add Infrahub Jinja2 transform for BGP configuration (#23) #27

Merged
Damien merged 2 commits from feat/infrahub-transforms-bgp into main 2026-03-01 13:22:52 +00:00
Owner

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]}]
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

🤖 Generated with Claude Code

## 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 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Damien added 1 commit 2026-03-01 11:44:46 +00:00
Single unified bgp_yang_transform covering the full BGP router stanza
(process config, peer groups, neighbors, address families) for all
10 fabric devices in a single query+template pass.

- Add GraphQL query bgp_intent.gql: queries InfraBGPRouterConfig by
  device name, traversing local_asn, peer_groups (with remote_asn),
  and sessions (with peer_group, remote_asn, vrf, peer_device);
  separately queries InfraBGPAddressFamily for the same device,
  including active_peer_groups, active_sessions, networks, and optional
  vrf relationship
- Add Jinja2 template bgp_yang.j2: renders a JSON object with bgp.global
  (ASN, router-id, distances, ECMP), bgp.peer_groups, bgp.neighbors,
  bgp.address_families for global sessions, plus bgp.vrf_neighbors and
  bgp.vrf_address_families for VRF-scoped entries (e.g. leaf7 VRF gold
  border peering); returns [] for devices with no BGP config; all
  optional relationships guarded with 'is defined and is not none' checks;
  send_community "none" normalised to null in output
- Update .infrahub.yml: register bgp_intent query and bgp_yang_transform
- Add unit test fixtures for three representative devices:
    leaf1  — 3 peer-groups, 5 global neighbors, 2 global AFs
    spine1 — 1 peer-group (evpn/next-hop-unchanged), 16 neighbors
             (8 direct underlay with remote_asn, 8 EVPN via peer-group),
             IPv4 AF activates individual sessions
    leaf7  — leaf1 pattern + VRF gold border session (AS 64999) and
             VRF-scoped IPv4 unicast AF

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Damien added 1 commit 2026-03-01 12:05:49 +00:00
InfraHub does not support multi-hop relationship traversal in GraphQL
filters, so `bgp_config__device__name__value` fails at query time.
Fix follows the same pattern used for InfraMlagPeerConfig (#22):
add a denormalized direct device relationship to the schema node and
use it in the query filter.

Changes:
- infrahub/schemas/bgp.yml: add `device` relationship (kind: Attribute,
  cardinality: one, optional: false) to BGPAddressFamily as the first
  relationship, before bgp_config
- infrahub/objects/11-bgp-sessions.yml: add `device: ["<device>"]` to
  all 22 InfraBGPAddressFamily entries (spine1×2, spine2×2, leaf1–8×2
  each, plus leaf7 and leaf8 VRF gold AF)
- infrahub/transforms/queries/bgp_intent.gql: change filter from
  `bgp_config__device__name__value` to `device__name__value`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Damien merged commit 1b918a4cbc into main 2026-03-01 13:22:52 +00:00
Damien deleted branch feat/infrahub-transforms-bgp 2026-03-01 13:22:56 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Damien/arista-evpn-vxlan-clab#27