Create Infrahub Transforms - VLANs, Interfaces, VXLAN #20

Closed
opened 2026-02-27 12:18:16 +00:00 by Damien · 1 comment
Owner

Description

Create Infrahub Transforms that generate YANG-structured payloads suitable for gNMI Set operations from Infrahub intent data, starting with VLANs and basic interfaces.

Context

With Infrahub as Source of Truth, we leverage its native Transform system (Jinja2 or Python) instead of custom Python mappers. Transforms query data via GraphQL and output structured YANG payloads ready for gNMI operations.

Architecture Decision

  • Declarative templates for YANG structure
  • Easy to test and debug with infrahubctl render
  • Version-controlled in Git repository
  • Native Infrahub integration

Option B: Python Transforms (For complex logic)

  • Full Python flexibility when needed
  • Access to Infrahub SDK objects
  • Better for conditional logic or computed values

Tasks

  • Define GraphQL queries for intent data extraction
    • vlan_intent.gql - Fetch VLANs with VNI mappings
    • interface_intent.gql - Fetch interfaces with IP addresses
    • vxlan_intent.gql - Fetch L2VPN/VNI configurations
  • Create Jinja2 transforms for YANG generation
    • vlan_yang.j2 - VLAN → YANG config
    • interface_yang.j2 - Interface → YANG config
    • vxlan_yang.j2 - VXLAN → YANG config
  • Configure .infrahub.yml with transform definitions
  • Handle both OpenConfig and Arista-native YANG paths
  • Add transform unit tests with infrahub-tests
  • Document transform usage and API endpoints

Example Implementation

GraphQL Query (vlan_intent.gql)

query VlanIntent($device: String!) {
  InfraVLAN(device__name__value: $device) {
    edges {
      node {
        vlan_id { value }
        name { value }
        vni { value }
        status { value }
      }
    }
  }
}

Jinja2 Transform (vlan_yang.j2)

{% for vlan in data.InfraVLAN.edges %}
{% set v = vlan.node %}
{
  "path": "/network-instances/network-instance[name=default]/vlans/vlan[vlan-id={{ v.vlan_id.value }}]",
  "value": {
    "config": {
      "vlan-id": {{ v.vlan_id.value }},
      "name": "{{ v.name.value }}",
      "status": "{{ v.status.value | upper }}"
    }
  }
}{% if not loop.last %},{% endif %}
{% endfor %}

.infrahub.yml Configuration

jinja2_transforms:
  - name: vlan_yang_transform
    description: "Generate YANG payload for VLANs"
    query: vlan_intent
    template_path: transforms/vlan_yang.j2

  - name: interface_yang_transform
    description: "Generate YANG payload for interfaces"
    query: interface_intent
    template_path: transforms/interface_yang.j2

  - name: vxlan_yang_transform
    description: "Generate YANG payload for VXLAN"
    query: vxlan_intent
    template_path: transforms/vxlan_yang.j2

queries:
  - name: vlan_intent
    file_path: queries/vlan_intent.gql
  - name: interface_intent
    file_path: queries/interface_intent.gql
  - name: vxlan_intent
    file_path: queries/vxlan_intent.gql

API Usage

# Render VLAN YANG config for a device
curl "https://infrahub/api/transform/jinja2/vlan_yang_transform?device=leaf1"

# Local debugging
infrahubctl render vlan_yang_transform device=leaf1

Output Files

transforms/
├── vlan_yang.j2
├── interface_yang.j2
└── vxlan_yang.j2
queries/
├── vlan_intent.gql
├── interface_intent.gql
└── vxlan_intent.gql
tests/
├── vlan_transform_test.yml
├── interface_transform_test.yml
└── vxlan_transform_test.yml
.infrahub.yml

Acceptance Criteria

  • Transforms produce valid YANG JSON structures
  • All transforms accessible via REST API
  • Unit tests validate transformations with sample data
  • Supports both OpenConfig and Arista-native paths (configurable)
  • Documentation includes usage examples

Migration Notes (from NetBox)

Before (NetBox) After (Infrahub)
Python YangMapper class Jinja2/Python Transform
Custom NetBox client GraphQL queries
to_yang() method Transform template
from_yang() reverse mapping Not needed (Infrahub manages state)
  • Depends on: #41 (Infrahub Schema definition)
  • Uses: src/yang/paths.py (documented YANG paths)
  • Enables: #29 (Plan/Apply needs YANG payloads from transforms)
## Description Create Infrahub Transforms that generate YANG-structured payloads suitable for gNMI Set operations from Infrahub intent data, starting with VLANs and basic interfaces. ## Context With Infrahub as Source of Truth, we leverage its native **Transform** system (Jinja2 or Python) instead of custom Python mappers. Transforms query data via GraphQL and output structured YANG payloads ready for gNMI operations. ## Architecture Decision ### Option A: Jinja2 Transforms (Recommended for config generation) - Declarative templates for YANG structure - Easy to test and debug with `infrahubctl render` - Version-controlled in Git repository - Native Infrahub integration ### Option B: Python Transforms (For complex logic) - Full Python flexibility when needed - Access to Infrahub SDK objects - Better for conditional logic or computed values ## Tasks - [x] Define GraphQL queries for intent data extraction - `vlan_intent.gql` - Fetch VLANs with VNI mappings - `interface_intent.gql` - Fetch interfaces with IP addresses - `vxlan_intent.gql` - Fetch L2VPN/VNI configurations - [x] Create Jinja2 transforms for YANG generation - `vlan_yang.j2` - VLAN → YANG config - `interface_yang.j2` - Interface → YANG config - `vxlan_yang.j2` - VXLAN → YANG config - [x] Configure `.infrahub.yml` with transform definitions - [x] Handle both OpenConfig and Arista-native YANG paths - [x] Add transform unit tests with `infrahub-tests` - [x] Document transform usage and API endpoints ## Example Implementation ### GraphQL Query (`vlan_intent.gql`) ```graphql query VlanIntent($device: String!) { InfraVLAN(device__name__value: $device) { edges { node { vlan_id { value } name { value } vni { value } status { value } } } } } ``` ### Jinja2 Transform (`vlan_yang.j2`) ```jinja2 {% for vlan in data.InfraVLAN.edges %} {% set v = vlan.node %} { "path": "/network-instances/network-instance[name=default]/vlans/vlan[vlan-id={{ v.vlan_id.value }}]", "value": { "config": { "vlan-id": {{ v.vlan_id.value }}, "name": "{{ v.name.value }}", "status": "{{ v.status.value | upper }}" } } }{% if not loop.last %},{% endif %} {% endfor %} ``` ### `.infrahub.yml` Configuration ```yaml jinja2_transforms: - name: vlan_yang_transform description: "Generate YANG payload for VLANs" query: vlan_intent template_path: transforms/vlan_yang.j2 - name: interface_yang_transform description: "Generate YANG payload for interfaces" query: interface_intent template_path: transforms/interface_yang.j2 - name: vxlan_yang_transform description: "Generate YANG payload for VXLAN" query: vxlan_intent template_path: transforms/vxlan_yang.j2 queries: - name: vlan_intent file_path: queries/vlan_intent.gql - name: interface_intent file_path: queries/interface_intent.gql - name: vxlan_intent file_path: queries/vxlan_intent.gql ``` ## API Usage ```bash # Render VLAN YANG config for a device curl "https://infrahub/api/transform/jinja2/vlan_yang_transform?device=leaf1" # Local debugging infrahubctl render vlan_yang_transform device=leaf1 ``` ## Output Files ``` transforms/ ├── vlan_yang.j2 ├── interface_yang.j2 └── vxlan_yang.j2 queries/ ├── vlan_intent.gql ├── interface_intent.gql └── vxlan_intent.gql tests/ ├── vlan_transform_test.yml ├── interface_transform_test.yml └── vxlan_transform_test.yml .infrahub.yml ``` ## Acceptance Criteria - [x] Transforms produce valid YANG JSON structures - [x] All transforms accessible via REST API - [x] Unit tests validate transformations with sample data - [x] Supports both OpenConfig and Arista-native paths (configurable) - [x] Documentation includes usage examples ## Migration Notes (from NetBox) | Before (NetBox) | After (Infrahub) | |-----------------|------------------| | Python `YangMapper` class | Jinja2/Python Transform | | Custom NetBox client | GraphQL queries | | `to_yang()` method | Transform template | | `from_yang()` reverse mapping | Not needed (Infrahub manages state) | ## Related - **Depends on: #41** (Infrahub Schema definition) - Uses: `src/yang/paths.py` (documented YANG paths) - Enables: #29 (Plan/Apply needs YANG payloads from transforms)
Author
Owner

Branch feat/infrahub-transforms-vlan-interfaces-vxlan created from main for this issue.

Branch `feat/infrahub-transforms-vlan-interfaces-vxlan` created from `main` for this issue.
Damien added reference feat/infrahub-transforms-vlan-interfaces-vxlan 2026-02-28 08:49:28 +00:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

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