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
# 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
Add three GraphQL queries, Jinja2 templates, and integration tests for
generating YANG-style JSON configuration payloads from Infrahub intent data,
suitable for gNMI Set operations on Arista EOS devices.
Queries (transforms/queries/):
- vlan_intent.gql: Fetches VLANs for a device via VTEP mappings and SVI
interfaces, including VNI associations.
- interface_intent.gql: Fetches all interface types (loopback, ethernet, vlan,
lag) with IP addresses and type-specific attributes.
- vxlan_intent.gql: Fetches VTEP config, VLAN-to-VNI mappings, and VRF-to-VNI
mappings (L3VNI) via VRF device assignments.
Templates (transforms/templates/):
- vlan_yang.j2: Merges VLANs from both VTEP and SVI sources, deduplicates by
vlan_id, and emits a sorted JSON array.
- interface_yang.j2: Emits a JSON array of interfaces sorted by name, with a
"type" discriminator field for each interface kind.
- vxlan_yang.j2: Emits a JSON object with vtep config, vlan_vni_mappings, and
vrf_vni_mappings sections.
Integration tests (transforms/tests/):
- One test directory per transform with input.json (sample GraphQL response for
leaf1), output.json (expected result), and test.yml config.
- Test data reflects the lab topology: leaf1 VTEP 10.0.255.11, VLAN 40 / VNI
110040, MLAG VLANs 4090/4091, underlay Ethernet11/12.
.infrahub.yml updated with queries and jinja2_transforms sections.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all `null` literals with `none` (valid Jinja2/Python) in all three
templates. Add explicit `is defined and is not none and .node is not none`
guards before accessing nested nodes on optional GraphQL relationships, to
avoid `Undefined is not JSON serializable` errors at render time.
Also add `| default(none)` on optional scalar attributes (speed, mode,
lacp_mode, mlag_id, mtu, description, virtual_router_address,
route_distinguisher, learn_restrict, vlan_type, trunk_groups) so that
Infrahub `Undefined` values from unset optional fields are safely coerced
to JSON null rather than crashing tojson serialization.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rewrite all three test.yml files to use the Infrahub SDK pytest format
(version: "1.0" / infrahub_tests) instead of the previous invalid
apiVersion/kind schema. Each test file now declares a smoke_check test
(jinja2-transform-smoke) and a unit render test (jinja2-transform-unit-render)
pointing to the local input/output JSON fixtures.
Update output.json files with the actual render output from the fixed templates:
- vlan_yang: trunk_groups is null (not []) for VLANs with no trunk groups set;
key order reflects Python dict / tojson serialization order.
- interface_yang: corrected MLAG peer-link SVI IP (10.0.199.254/31), added
iBGP SVI IP (10.0.3.0/31), removed stale Loopback1 IP address.
- vxlan_yang: source_address now includes /32 prefix as stored in Infrahub
IPHost fields; key order matches tojson output.
Update input.json files to be consistent with the expected output:
- vlan_yang/input.json: trunk_groups.value set to null for VLAN 40.
- interface_yang/input.json: Loopback1 ip_addresses cleared; Vlan4090 IP
updated to 10.0.199.254/31; Vlan4091 IP added as 10.0.3.0/31.
- vxlan_yang/input.json: source_address updated to 10.0.255.11/32.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move transforms/{queries,templates,tests} under infrahub/transforms/ so all
Infrahub-managed content lives under the dedicated infrahub/ directory,
consistent with schemas/, objects/, and menus/.
Updated paths:
- .infrahub.yml: file_path and template_path entries now prefixed with
infrahub/transforms/
- infrahub/transforms/tests/*/test.yml: directory references updated from
transforms/tests/* to infrahub/transforms/tests/*
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Damien
merged commit 668e9cbada into main2026-02-28 17:42:09 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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.
vlan_intent,interface_intent,vxlan_intent— each parameterized by$device_namevlan_yang.j2,interface_yang.j2,vxlan_yang.j2— producing JSON arrays/objects from the GraphQL responseinput.json,output.json, andtest.yml, using leaf1 from the lab topology as sample device.infrahub.ymlupdated withqueriesandjinja2_transformssectionsFiles added
Transform usage
Test plan
infrahubctl schema load+infrahubctl object load)infrahubctl render vlan_yang_transform device_name=leaf1and verify JSON output matches expected VLANs (40, 4090, 4091)infrahubctl render interface_yang_transform device_name=leaf1and verify all interface types are present with correct attributesinfrahubctl render vxlan_yang_transform device_name=leaf1and verify VTEP source address, UDP port, and VLAN-VNI mapping for VLAN 40 / VNI 110040infrahubctl render vxlan_yang_transform device_name=leaf3and verify VRF gold / L3VNI 100001 appears invrf_vni_mappings[ ] Verifyinfrahubctl testpasses for all three test fixtures🤖 Generated with Claude Code
Move transforms/{queries,templates,tests} under infrahub/transforms/ so all Infrahub-managed content lives under the dedicated infrahub/ directory, consistent with schemas/, objects/, and menus/. Updated paths: - .infrahub.yml: file_path and template_path entries now prefixed with infrahub/transforms/ - infrahub/transforms/tests/*/test.yml: directory references updated from transforms/tests/* to infrahub/transforms/tests/* Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>