## 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. - **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 ```bash # 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 ``` ## Test plan - [x] Load branch into Infrahub (`infrahubctl schema load` + `infrahubctl object load`) - [x] Run `infrahubctl render vlan_yang_transform device_name=leaf1` and verify JSON output matches expected VLANs (40, 4090, 4091) - [x] Run `infrahubctl render interface_yang_transform device_name=leaf1` and verify all interface types are present with correct attributes - [x] Run `infrahubctl render vxlan_yang_transform device_name=leaf1` and verify VTEP source address, UDP port, and VLAN-VNI mapping for VLAN 40 / VNI 110040 - [x] Run `infrahubctl render vxlan_yang_transform device_name=leaf3` and verify VRF gold / L3VNI 100001 appears in `vrf_vni_mappings` - ~~[ ] Verify `infrahubctl test` passes for all three test fixtures~~ Reviewed-on: #24
This commit was merged in pull request #24.
This commit is contained in:
@@ -16,3 +16,25 @@ objects:
|
||||
- infrahub/objects/10-bgp-sessions.yml
|
||||
- infrahub/objects/11-vrfs.yml
|
||||
- infrahub/objects/12-mlag.yml
|
||||
|
||||
queries:
|
||||
- name: vlan_intent
|
||||
file_path: infrahub/transforms/queries/vlan_intent.gql
|
||||
- name: interface_intent
|
||||
file_path: infrahub/transforms/queries/interface_intent.gql
|
||||
- name: vxlan_intent
|
||||
file_path: infrahub/transforms/queries/vxlan_intent.gql
|
||||
|
||||
jinja2_transforms:
|
||||
- name: vlan_yang_transform
|
||||
description: "Generate VLAN configuration payload from Infrahub intent"
|
||||
query: vlan_intent
|
||||
template_path: infrahub/transforms/templates/vlan_yang.j2
|
||||
- name: interface_yang_transform
|
||||
description: "Generate interface configuration payload from Infrahub intent"
|
||||
query: interface_intent
|
||||
template_path: infrahub/transforms/templates/interface_yang.j2
|
||||
- name: vxlan_yang_transform
|
||||
description: "Generate VXLAN/VTEP configuration payload from Infrahub intent"
|
||||
query: vxlan_intent
|
||||
template_path: infrahub/transforms/templates/vxlan_yang.j2
|
||||
|
||||
155
infrahub/transforms/queries/interface_intent.gql
Normal file
155
infrahub/transforms/queries/interface_intent.gql
Normal file
@@ -0,0 +1,155 @@
|
||||
query InterfaceIntent($device_name: String!) {
|
||||
# Loopback interfaces
|
||||
InfraInterfaceLoopback(device__name__value: $device_name) {
|
||||
edges {
|
||||
node {
|
||||
name {
|
||||
value
|
||||
}
|
||||
description {
|
||||
value
|
||||
}
|
||||
enabled {
|
||||
value
|
||||
}
|
||||
mtu {
|
||||
value
|
||||
}
|
||||
ip_addresses {
|
||||
edges {
|
||||
node {
|
||||
address {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# Ethernet interfaces
|
||||
InfraInterfaceEthernet(device__name__value: $device_name) {
|
||||
edges {
|
||||
node {
|
||||
name {
|
||||
value
|
||||
}
|
||||
description {
|
||||
value
|
||||
}
|
||||
enabled {
|
||||
value
|
||||
}
|
||||
mtu {
|
||||
value
|
||||
}
|
||||
speed {
|
||||
value
|
||||
}
|
||||
mode {
|
||||
value
|
||||
}
|
||||
lag {
|
||||
node {
|
||||
name {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
ip_addresses {
|
||||
edges {
|
||||
node {
|
||||
address {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# VLAN SVI interfaces
|
||||
InfraInterfaceVlan(device__name__value: $device_name) {
|
||||
edges {
|
||||
node {
|
||||
name {
|
||||
value
|
||||
}
|
||||
description {
|
||||
value
|
||||
}
|
||||
enabled {
|
||||
value
|
||||
}
|
||||
mtu {
|
||||
value
|
||||
}
|
||||
virtual_router_address {
|
||||
value
|
||||
}
|
||||
autostate {
|
||||
value
|
||||
}
|
||||
vlan {
|
||||
node {
|
||||
vlan_id {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
ip_addresses {
|
||||
edges {
|
||||
node {
|
||||
address {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# LAG / Port-Channel interfaces
|
||||
InfraInterfaceLag(device__name__value: $device_name) {
|
||||
edges {
|
||||
node {
|
||||
name {
|
||||
value
|
||||
}
|
||||
description {
|
||||
value
|
||||
}
|
||||
enabled {
|
||||
value
|
||||
}
|
||||
mtu {
|
||||
value
|
||||
}
|
||||
lacp_mode {
|
||||
value
|
||||
}
|
||||
mlag_id {
|
||||
value
|
||||
}
|
||||
members {
|
||||
edges {
|
||||
node {
|
||||
name {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ip_addresses {
|
||||
edges {
|
||||
node {
|
||||
address {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
92
infrahub/transforms/queries/vlan_intent.gql
Normal file
92
infrahub/transforms/queries/vlan_intent.gql
Normal file
@@ -0,0 +1,92 @@
|
||||
query VlanIntent($device_name: String!) {
|
||||
# VLANs reachable via VTEP VLAN-VNI mappings (L2/VXLAN VLANs)
|
||||
InfraVTEP(device__name__value: $device_name) {
|
||||
edges {
|
||||
node {
|
||||
source_address {
|
||||
value
|
||||
}
|
||||
udp_port {
|
||||
value
|
||||
}
|
||||
vlan_vni_mappings {
|
||||
edges {
|
||||
node {
|
||||
vlan {
|
||||
node {
|
||||
vlan_id {
|
||||
value
|
||||
}
|
||||
name {
|
||||
value
|
||||
}
|
||||
status {
|
||||
value
|
||||
}
|
||||
vlan_type {
|
||||
value
|
||||
}
|
||||
trunk_groups {
|
||||
value
|
||||
}
|
||||
stp_enabled {
|
||||
value
|
||||
}
|
||||
vni {
|
||||
node {
|
||||
vni {
|
||||
value
|
||||
}
|
||||
vni_type {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# VLANs reachable via SVI interfaces (MLAG, routing, and other local VLANs)
|
||||
InfraInterfaceVlan(device__name__value: $device_name) {
|
||||
edges {
|
||||
node {
|
||||
vlan {
|
||||
node {
|
||||
vlan_id {
|
||||
value
|
||||
}
|
||||
name {
|
||||
value
|
||||
}
|
||||
status {
|
||||
value
|
||||
}
|
||||
vlan_type {
|
||||
value
|
||||
}
|
||||
trunk_groups {
|
||||
value
|
||||
}
|
||||
stp_enabled {
|
||||
value
|
||||
}
|
||||
vni {
|
||||
node {
|
||||
vni {
|
||||
value
|
||||
}
|
||||
vni_type {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
100
infrahub/transforms/queries/vxlan_intent.gql
Normal file
100
infrahub/transforms/queries/vxlan_intent.gql
Normal file
@@ -0,0 +1,100 @@
|
||||
query VxlanIntent($device_name: String!) {
|
||||
# VTEP configuration for the device
|
||||
InfraVTEP(device__name__value: $device_name) {
|
||||
edges {
|
||||
node {
|
||||
source_address {
|
||||
value
|
||||
}
|
||||
udp_port {
|
||||
value
|
||||
}
|
||||
learn_restrict {
|
||||
value
|
||||
}
|
||||
source_interface {
|
||||
node {
|
||||
name {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
# VLAN-to-VNI mappings (L2 VXLAN)
|
||||
vlan_vni_mappings {
|
||||
edges {
|
||||
node {
|
||||
description {
|
||||
value
|
||||
}
|
||||
vlan {
|
||||
node {
|
||||
vlan_id {
|
||||
value
|
||||
}
|
||||
name {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
vni {
|
||||
node {
|
||||
vni {
|
||||
value
|
||||
}
|
||||
vni_type {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# VRF-to-VNI mappings (L3 VXLAN) via VRF device assignments
|
||||
InfraVRFDeviceAssignment(device__name__value: $device_name) {
|
||||
edges {
|
||||
node {
|
||||
route_distinguisher {
|
||||
value
|
||||
}
|
||||
vrf {
|
||||
node {
|
||||
name {
|
||||
value
|
||||
}
|
||||
l3vni {
|
||||
node {
|
||||
vni {
|
||||
value
|
||||
}
|
||||
vni_type {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
import_targets {
|
||||
edges {
|
||||
node {
|
||||
target {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export_targets {
|
||||
edges {
|
||||
node {
|
||||
target {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
101
infrahub/transforms/templates/interface_yang.j2
Normal file
101
infrahub/transforms/templates/interface_yang.j2
Normal file
@@ -0,0 +1,101 @@
|
||||
{#
|
||||
interface_yang.j2 — Produce a JSON array of interface configuration objects.
|
||||
|
||||
Input: GraphQL response from interface_intent query.
|
||||
Returns all interface types (loopback, ethernet, vlan, lag) for the device,
|
||||
each with a "type" discriminator and type-specific attributes.
|
||||
#}
|
||||
{%- set interfaces = [] -%}
|
||||
|
||||
{#— Loopback interfaces —#}
|
||||
{%- for edge in data.InfraInterfaceLoopback.edges -%}
|
||||
{%- set iface = edge.node -%}
|
||||
{%- set ip_list = [] -%}
|
||||
{%- for ip_edge in iface.ip_addresses.edges -%}
|
||||
{%- set _ = ip_list.append(ip_edge.node.address.value) -%}
|
||||
{%- endfor -%}
|
||||
{%- set _ = interfaces.append({
|
||||
"type": "loopback",
|
||||
"name": iface.name.value,
|
||||
"description": iface.description.value | default(none),
|
||||
"enabled": iface.enabled.value,
|
||||
"mtu": iface.mtu.value | default(none),
|
||||
"ip_addresses": ip_list
|
||||
}) -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{#— Ethernet interfaces —#}
|
||||
{%- for edge in data.InfraInterfaceEthernet.edges -%}
|
||||
{%- set iface = edge.node -%}
|
||||
{%- set ip_list = [] -%}
|
||||
{%- for ip_edge in iface.ip_addresses.edges -%}
|
||||
{%- set _ = ip_list.append(ip_edge.node.address.value) -%}
|
||||
{%- endfor -%}
|
||||
{%- set lag_name = none -%}
|
||||
{%- if iface.lag is defined and iface.lag is not none and iface.lag.node is not none -%}
|
||||
{%- set lag_name = iface.lag.node.name.value -%}
|
||||
{%- endif -%}
|
||||
{%- set _ = interfaces.append({
|
||||
"type": "ethernet",
|
||||
"name": iface.name.value,
|
||||
"description": iface.description.value | default(none),
|
||||
"enabled": iface.enabled.value,
|
||||
"mtu": iface.mtu.value | default(none),
|
||||
"speed": iface.speed.value | default(none),
|
||||
"mode": iface.mode.value | default(none),
|
||||
"lag": lag_name,
|
||||
"ip_addresses": ip_list
|
||||
}) -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{#— VLAN SVI interfaces —#}
|
||||
{%- for edge in data.InfraInterfaceVlan.edges -%}
|
||||
{%- set iface = edge.node -%}
|
||||
{%- set ip_list = [] -%}
|
||||
{%- for ip_edge in iface.ip_addresses.edges -%}
|
||||
{%- set _ = ip_list.append(ip_edge.node.address.value) -%}
|
||||
{%- endfor -%}
|
||||
{%- set vlan_id = none -%}
|
||||
{%- if iface.vlan is defined and iface.vlan is not none and iface.vlan.node is not none -%}
|
||||
{%- set vlan_id = iface.vlan.node.vlan_id.value -%}
|
||||
{%- endif -%}
|
||||
{%- set _ = interfaces.append({
|
||||
"type": "vlan",
|
||||
"name": iface.name.value,
|
||||
"description": iface.description.value | default(none),
|
||||
"enabled": iface.enabled.value,
|
||||
"mtu": iface.mtu.value | default(none),
|
||||
"vlan_id": vlan_id,
|
||||
"virtual_router_address": iface.virtual_router_address.value | default(none),
|
||||
"autostate": iface.autostate.value,
|
||||
"ip_addresses": ip_list
|
||||
}) -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{#— LAG / Port-Channel interfaces —#}
|
||||
{%- for edge in data.InfraInterfaceLag.edges -%}
|
||||
{%- set iface = edge.node -%}
|
||||
{%- set ip_list = [] -%}
|
||||
{%- for ip_edge in iface.ip_addresses.edges -%}
|
||||
{%- set _ = ip_list.append(ip_edge.node.address.value) -%}
|
||||
{%- endfor -%}
|
||||
{%- set member_list = [] -%}
|
||||
{%- for member_edge in iface.members.edges -%}
|
||||
{%- set _ = member_list.append(member_edge.node.name.value) -%}
|
||||
{%- endfor -%}
|
||||
{%- set _ = interfaces.append({
|
||||
"type": "lag",
|
||||
"name": iface.name.value,
|
||||
"description": iface.description.value | default(none),
|
||||
"enabled": iface.enabled.value,
|
||||
"mtu": iface.mtu.value | default(none),
|
||||
"lacp_mode": iface.lacp_mode.value | default(none),
|
||||
"mlag_id": iface.mlag_id.value | default(none),
|
||||
"members": member_list,
|
||||
"ip_addresses": ip_list
|
||||
}) -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{#— Sort by name and emit JSON array —#}
|
||||
{%- set sorted_ifaces = interfaces | sort(attribute='name') -%}
|
||||
{{ sorted_ifaces | tojson(indent=2) }}
|
||||
67
infrahub/transforms/templates/vlan_yang.j2
Normal file
67
infrahub/transforms/templates/vlan_yang.j2
Normal file
@@ -0,0 +1,67 @@
|
||||
{#
|
||||
vlan_yang.j2 — Produce a JSON array of VLAN configuration objects.
|
||||
|
||||
Input: GraphQL response from vlan_intent query.
|
||||
The query returns VLANs from two sources:
|
||||
1. data.InfraVTEP[].vlan_vni_mappings[].vlan (L2/VXLAN VLANs)
|
||||
2. data.InfraInterfaceVlan[].vlan (SVI/routing/MLAG VLANs)
|
||||
|
||||
We merge both sources, deduplicate by vlan_id, and emit one object per VLAN.
|
||||
#}
|
||||
{%- set vlans = {} -%}
|
||||
|
||||
{#— Collect VLANs from VTEP VLAN-VNI mappings —#}
|
||||
{%- for vtep_edge in data.InfraVTEP.edges -%}
|
||||
{%- for mapping_edge in vtep_edge.node.vlan_vni_mappings.edges -%}
|
||||
{%- set vlan_node = mapping_edge.node.vlan.node -%}
|
||||
{%- set vid = vlan_node.vlan_id.value | string -%}
|
||||
{%- if vid not in vlans -%}
|
||||
{%- set vni_val = none -%}
|
||||
{%- set vni_type_val = none -%}
|
||||
{%- if vlan_node.vni is defined and vlan_node.vni is not none and vlan_node.vni.node is not none -%}
|
||||
{%- set vni_val = vlan_node.vni.node.vni.value -%}
|
||||
{%- set vni_type_val = vlan_node.vni.node.vni_type.value -%}
|
||||
{%- endif -%}
|
||||
{%- set _ = vlans.update({vid: {
|
||||
"vlan_id": vlan_node.vlan_id.value,
|
||||
"name": vlan_node.name.value,
|
||||
"status": vlan_node.status.value | default('') | upper,
|
||||
"vlan_type": vlan_node.vlan_type.value | default(none),
|
||||
"trunk_groups": vlan_node.trunk_groups.value | default([]),
|
||||
"stp_enabled": vlan_node.stp_enabled.value,
|
||||
"vni": vni_val,
|
||||
"vni_type": vni_type_val
|
||||
}}) -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{#— Collect VLANs from SVI interfaces —#}
|
||||
{%- for svi_edge in data.InfraInterfaceVlan.edges -%}
|
||||
{%- if svi_edge.node.vlan is defined and svi_edge.node.vlan is not none and svi_edge.node.vlan.node is not none -%}
|
||||
{%- set vlan_node = svi_edge.node.vlan.node -%}
|
||||
{%- set vid = vlan_node.vlan_id.value | string -%}
|
||||
{%- if vid not in vlans -%}
|
||||
{%- set vni_val = none -%}
|
||||
{%- set vni_type_val = none -%}
|
||||
{%- if vlan_node.vni is defined and vlan_node.vni is not none and vlan_node.vni.node is not none -%}
|
||||
{%- set vni_val = vlan_node.vni.node.vni.value -%}
|
||||
{%- set vni_type_val = vlan_node.vni.node.vni_type.value -%}
|
||||
{%- endif -%}
|
||||
{%- set _ = vlans.update({vid: {
|
||||
"vlan_id": vlan_node.vlan_id.value,
|
||||
"name": vlan_node.name.value,
|
||||
"status": vlan_node.status.value | default('') | upper,
|
||||
"vlan_type": vlan_node.vlan_type.value | default(none),
|
||||
"trunk_groups": vlan_node.trunk_groups.value | default([]),
|
||||
"stp_enabled": vlan_node.stp_enabled.value,
|
||||
"vni": vni_val,
|
||||
"vni_type": vni_type_val
|
||||
}}) -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{#— Sort by vlan_id and emit JSON array —#}
|
||||
{%- set sorted_vlans = vlans.values() | sort(attribute='vlan_id') -%}
|
||||
{{ sorted_vlans | tojson(indent=2) }}
|
||||
88
infrahub/transforms/templates/vxlan_yang.j2
Normal file
88
infrahub/transforms/templates/vxlan_yang.j2
Normal file
@@ -0,0 +1,88 @@
|
||||
{#
|
||||
vxlan_yang.j2 — Produce a JSON object representing the VXLAN/VTEP configuration
|
||||
for the device, including VLAN-to-VNI mappings and VRF-to-VNI mappings.
|
||||
|
||||
Input: GraphQL response from vxlan_intent query.
|
||||
#}
|
||||
{%- set vtep_edges = data.InfraVTEP.edges -%}
|
||||
{%- set vrf_edges = data.InfraVRFDeviceAssignment.edges -%}
|
||||
|
||||
{#— Build VTEP section (there is one VTEP per device) —#}
|
||||
{%- if vtep_edges | length > 0 -%}
|
||||
{%- set vtep = vtep_edges[0].node -%}
|
||||
{%- set source_iface = none -%}
|
||||
{%- if vtep.source_interface is defined and vtep.source_interface is not none and vtep.source_interface.node is not none -%}
|
||||
{%- set source_iface = vtep.source_interface.node.name.value -%}
|
||||
{%- endif -%}
|
||||
|
||||
{#— Build VLAN-to-VNI mapping list —#}
|
||||
{%- set vlan_vni_list = [] -%}
|
||||
{%- for mapping_edge in vtep.vlan_vni_mappings.edges -%}
|
||||
{%- set m = mapping_edge.node -%}
|
||||
{%- set vlan_id = none -%}
|
||||
{%- set vlan_name = none -%}
|
||||
{%- if m.vlan is defined and m.vlan is not none and m.vlan.node is not none -%}
|
||||
{%- set vlan_id = m.vlan.node.vlan_id.value -%}
|
||||
{%- set vlan_name = m.vlan.node.name.value -%}
|
||||
{%- endif -%}
|
||||
{%- set vni_val = none -%}
|
||||
{%- set vni_type_val = none -%}
|
||||
{%- if m.vni is defined and m.vni is not none and m.vni.node is not none -%}
|
||||
{%- set vni_val = m.vni.node.vni.value -%}
|
||||
{%- set vni_type_val = m.vni.node.vni_type.value -%}
|
||||
{%- endif -%}
|
||||
{%- set _ = vlan_vni_list.append({
|
||||
"vlan_id": vlan_id,
|
||||
"vlan_name": vlan_name,
|
||||
"vni": vni_val,
|
||||
"vni_type": vni_type_val
|
||||
}) -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{#— Build VRF-to-VNI mapping list —#}
|
||||
{%- set vrf_vni_list = [] -%}
|
||||
{%- for vrf_edge in vrf_edges -%}
|
||||
{%- set assignment = vrf_edge.node -%}
|
||||
{%- set vrf_name = none -%}
|
||||
{%- set l3vni = none -%}
|
||||
{%- set import_rts = [] -%}
|
||||
{%- set export_rts = [] -%}
|
||||
{%- if assignment.vrf is defined and assignment.vrf is not none and assignment.vrf.node is not none -%}
|
||||
{%- set vrf_node = assignment.vrf.node -%}
|
||||
{%- set vrf_name = vrf_node.name.value -%}
|
||||
{%- if vrf_node.l3vni is defined and vrf_node.l3vni is not none and vrf_node.l3vni.node is not none -%}
|
||||
{%- set l3vni = vrf_node.l3vni.node.vni.value -%}
|
||||
{%- endif -%}
|
||||
{%- for rt_edge in vrf_node.import_targets.edges -%}
|
||||
{%- set _ = import_rts.append(rt_edge.node.target.value) -%}
|
||||
{%- endfor -%}
|
||||
{%- for rt_edge in vrf_node.export_targets.edges -%}
|
||||
{%- set _ = export_rts.append(rt_edge.node.target.value) -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
{%- set _ = vrf_vni_list.append({
|
||||
"vrf": vrf_name,
|
||||
"l3vni": l3vni,
|
||||
"route_distinguisher": assignment.route_distinguisher.value | default(none),
|
||||
"import_targets": import_rts,
|
||||
"export_targets": export_rts
|
||||
}) -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{%- set result = {
|
||||
"vtep": {
|
||||
"source_address": vtep.source_address.value,
|
||||
"source_interface": source_iface,
|
||||
"udp_port": vtep.udp_port.value,
|
||||
"learn_restrict": vtep.learn_restrict.value | default(none),
|
||||
"vlan_vni_mappings": vlan_vni_list | sort(attribute='vlan_id'),
|
||||
"vrf_vni_mappings": vrf_vni_list
|
||||
}
|
||||
} -%}
|
||||
{%- else -%}
|
||||
{%- set result = {
|
||||
"vtep": none,
|
||||
"vrf_vni_mappings": []
|
||||
} -%}
|
||||
{%- endif -%}
|
||||
{{ result | tojson(indent=2) }}
|
||||
350
infrahub/transforms/tests/interface_yang/input.json
Normal file
350
infrahub/transforms/tests/interface_yang/input.json
Normal file
@@ -0,0 +1,350 @@
|
||||
{
|
||||
"data": {
|
||||
"InfraInterfaceLoopback": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Loopback0"
|
||||
},
|
||||
"description": {
|
||||
"value": "Router-ID"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": null
|
||||
},
|
||||
"ip_addresses": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"address": {
|
||||
"value": "10.0.250.11/32"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Loopback1"
|
||||
},
|
||||
"description": {
|
||||
"value": "VTEP"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": null
|
||||
},
|
||||
"ip_addresses": {
|
||||
"edges": []
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"InfraInterfaceEthernet": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Ethernet1"
|
||||
},
|
||||
"description": {
|
||||
"value": "host1"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": null
|
||||
},
|
||||
"speed": {
|
||||
"value": null
|
||||
},
|
||||
"mode": {
|
||||
"value": "trunk"
|
||||
},
|
||||
"lag": {
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Port-Channel1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ip_addresses": {
|
||||
"edges": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Ethernet10"
|
||||
},
|
||||
"description": {
|
||||
"value": "mlag peer link"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": null
|
||||
},
|
||||
"speed": {
|
||||
"value": null
|
||||
},
|
||||
"mode": {
|
||||
"value": "trunk"
|
||||
},
|
||||
"lag": {
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Port-Channel999"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ip_addresses": {
|
||||
"edges": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Ethernet11"
|
||||
},
|
||||
"description": {
|
||||
"value": "spine1"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": 9214
|
||||
},
|
||||
"speed": {
|
||||
"value": null
|
||||
},
|
||||
"mode": {
|
||||
"value": "routed"
|
||||
},
|
||||
"lag": null,
|
||||
"ip_addresses": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"address": {
|
||||
"value": "10.0.1.1/31"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Ethernet12"
|
||||
},
|
||||
"description": {
|
||||
"value": "spine2"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": 9214
|
||||
},
|
||||
"speed": {
|
||||
"value": null
|
||||
},
|
||||
"mode": {
|
||||
"value": "routed"
|
||||
},
|
||||
"lag": null,
|
||||
"ip_addresses": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"address": {
|
||||
"value": "10.0.2.1/31"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"InfraInterfaceVlan": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Vlan4090"
|
||||
},
|
||||
"description": {
|
||||
"value": "MLAG Peer-Link"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": null
|
||||
},
|
||||
"virtual_router_address": {
|
||||
"value": null
|
||||
},
|
||||
"autostate": {
|
||||
"value": false
|
||||
},
|
||||
"vlan": {
|
||||
"node": {
|
||||
"vlan_id": {
|
||||
"value": 4090
|
||||
}
|
||||
}
|
||||
},
|
||||
"ip_addresses": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"address": {
|
||||
"value": "10.0.199.254/31"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Vlan4091"
|
||||
},
|
||||
"description": {
|
||||
"value": "MLAG iBGP Peering"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": 9214
|
||||
},
|
||||
"virtual_router_address": {
|
||||
"value": null
|
||||
},
|
||||
"autostate": {
|
||||
"value": true
|
||||
},
|
||||
"vlan": {
|
||||
"node": {
|
||||
"vlan_id": {
|
||||
"value": 4091
|
||||
}
|
||||
}
|
||||
},
|
||||
"ip_addresses": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"address": {
|
||||
"value": "10.0.3.0/31"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"InfraInterfaceLag": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Port-Channel1"
|
||||
},
|
||||
"description": {
|
||||
"value": "host1"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": null
|
||||
},
|
||||
"lacp_mode": {
|
||||
"value": "active"
|
||||
},
|
||||
"mlag_id": {
|
||||
"value": 1
|
||||
},
|
||||
"members": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Ethernet1"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ip_addresses": {
|
||||
"edges": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Port-Channel999"
|
||||
},
|
||||
"description": {
|
||||
"value": "MLAG Peer"
|
||||
},
|
||||
"enabled": {
|
||||
"value": true
|
||||
},
|
||||
"mtu": {
|
||||
"value": null
|
||||
},
|
||||
"lacp_mode": {
|
||||
"value": "active"
|
||||
},
|
||||
"mlag_id": {
|
||||
"value": null
|
||||
},
|
||||
"members": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Ethernet10"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ip_addresses": {
|
||||
"edges": []
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
12
infrahub/transforms/tests/interface_yang/output.json
Normal file
12
infrahub/transforms/tests/interface_yang/output.json
Normal file
@@ -0,0 +1,12 @@
|
||||
[
|
||||
{"description":"host1","enabled":true,"ip_addresses":[],"lag":"Port-Channel1","mode":"trunk","mtu":null,"name":"Ethernet1","speed":null,"type":"ethernet"},
|
||||
{"description":"mlag peer link","enabled":true,"ip_addresses":[],"lag":"Port-Channel999","mode":"trunk","mtu":null,"name":"Ethernet10","speed":null,"type":"ethernet"},
|
||||
{"description":"spine1","enabled":true,"ip_addresses":["10.0.1.1/31"],"lag":null,"mode":"routed","mtu":9214,"name":"Ethernet11","speed":null,"type":"ethernet"},
|
||||
{"description":"spine2","enabled":true,"ip_addresses":["10.0.2.1/31"],"lag":null,"mode":"routed","mtu":9214,"name":"Ethernet12","speed":null,"type":"ethernet"},
|
||||
{"description":"Router-ID","enabled":true,"ip_addresses":["10.0.250.11/32"],"mtu":null,"name":"Loopback0","type":"loopback"},
|
||||
{"description":"VTEP","enabled":true,"ip_addresses":[],"mtu":null,"name":"Loopback1","type":"loopback"},
|
||||
{"description":"host1","enabled":true,"ip_addresses":[],"lacp_mode":"active","members":["Ethernet1"],"mlag_id":1,"mtu":null,"name":"Port-Channel1","type":"lag"},
|
||||
{"description":"MLAG Peer","enabled":true,"ip_addresses":[],"lacp_mode":"active","members":["Ethernet10"],"mlag_id":null,"mtu":null,"name":"Port-Channel999","type":"lag"},
|
||||
{"autostate":false,"description":"MLAG Peer-Link","enabled":true,"ip_addresses":["10.0.199.254/31"],"mtu":null,"name":"Vlan4090","type":"vlan","virtual_router_address":null,"vlan_id":4090},
|
||||
{"autostate":true,"description":"MLAG iBGP Peering","enabled":true,"ip_addresses":["10.0.3.0/31"],"mtu":9214,"name":"Vlan4091","type":"vlan","virtual_router_address":null,"vlan_id":4091}
|
||||
]
|
||||
15
infrahub/transforms/tests/interface_yang/test.yml
Normal file
15
infrahub/transforms/tests/interface_yang/test.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
version: "1.0"
|
||||
infrahub_tests:
|
||||
- resource: Jinja2Transform
|
||||
resource_name: interface_yang_transform
|
||||
tests:
|
||||
- name: smoke_check
|
||||
spec:
|
||||
kind: jinja2-transform-smoke
|
||||
- name: render_leaf1
|
||||
spec:
|
||||
kind: jinja2-transform-unit-render
|
||||
directory: infrahub/transforms/tests/interface_yang
|
||||
input: input.json
|
||||
output: output.json
|
||||
116
infrahub/transforms/tests/vlan_yang/input.json
Normal file
116
infrahub/transforms/tests/vlan_yang/input.json
Normal file
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"data": {
|
||||
"InfraVTEP": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"source_address": {
|
||||
"value": "10.0.255.11"
|
||||
},
|
||||
"udp_port": {
|
||||
"value": 4789
|
||||
},
|
||||
"vlan_vni_mappings": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"vlan": {
|
||||
"node": {
|
||||
"vlan_id": {
|
||||
"value": 40
|
||||
},
|
||||
"name": {
|
||||
"value": "test-l2-vxlan"
|
||||
},
|
||||
"status": {
|
||||
"value": "active"
|
||||
},
|
||||
"vlan_type": {
|
||||
"value": "standard"
|
||||
},
|
||||
"trunk_groups": {
|
||||
"value": null
|
||||
},
|
||||
"stp_enabled": {
|
||||
"value": true
|
||||
},
|
||||
"vni": {
|
||||
"node": {
|
||||
"vni": {
|
||||
"value": 110040
|
||||
},
|
||||
"vni_type": {
|
||||
"value": "l2vni"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"InfraInterfaceVlan": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"vlan": {
|
||||
"node": {
|
||||
"vlan_id": {
|
||||
"value": 4090
|
||||
},
|
||||
"name": {
|
||||
"value": "mlag-peer"
|
||||
},
|
||||
"status": {
|
||||
"value": "active"
|
||||
},
|
||||
"vlan_type": {
|
||||
"value": "mlag_peer"
|
||||
},
|
||||
"trunk_groups": {
|
||||
"value": ["mlag-peer"]
|
||||
},
|
||||
"stp_enabled": {
|
||||
"value": false
|
||||
},
|
||||
"vni": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"node": {
|
||||
"vlan": {
|
||||
"node": {
|
||||
"vlan_id": {
|
||||
"value": 4091
|
||||
},
|
||||
"name": {
|
||||
"value": "mlag-ibgp"
|
||||
},
|
||||
"status": {
|
||||
"value": "active"
|
||||
},
|
||||
"vlan_type": {
|
||||
"value": "mlag_ibgp"
|
||||
},
|
||||
"trunk_groups": {
|
||||
"value": ["mlag-peer"]
|
||||
},
|
||||
"stp_enabled": {
|
||||
"value": false
|
||||
},
|
||||
"vni": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
32
infrahub/transforms/tests/vlan_yang/output.json
Normal file
32
infrahub/transforms/tests/vlan_yang/output.json
Normal file
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"name": "test-l2-vxlan",
|
||||
"status": "ACTIVE",
|
||||
"stp_enabled": true,
|
||||
"trunk_groups": null,
|
||||
"vlan_id": 40,
|
||||
"vlan_type": "standard",
|
||||
"vni": 110040,
|
||||
"vni_type": "l2vni"
|
||||
},
|
||||
{
|
||||
"name": "mlag-peer",
|
||||
"status": "ACTIVE",
|
||||
"stp_enabled": false,
|
||||
"trunk_groups": ["mlag-peer"],
|
||||
"vlan_id": 4090,
|
||||
"vlan_type": "mlag_peer",
|
||||
"vni": null,
|
||||
"vni_type": null
|
||||
},
|
||||
{
|
||||
"name": "mlag-ibgp",
|
||||
"status": "ACTIVE",
|
||||
"stp_enabled": false,
|
||||
"trunk_groups": ["mlag-peer"],
|
||||
"vlan_id": 4091,
|
||||
"vlan_type": "mlag_ibgp",
|
||||
"vni": null,
|
||||
"vni_type": null
|
||||
}
|
||||
]
|
||||
15
infrahub/transforms/tests/vlan_yang/test.yml
Normal file
15
infrahub/transforms/tests/vlan_yang/test.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
version: "1.0"
|
||||
infrahub_tests:
|
||||
- resource: Jinja2Transform
|
||||
resource_name: vlan_yang_transform
|
||||
tests:
|
||||
- name: smoke_check
|
||||
spec:
|
||||
kind: jinja2-transform-smoke
|
||||
- name: render_leaf1
|
||||
spec:
|
||||
kind: jinja2-transform-unit-render
|
||||
directory: infrahub/transforms/tests/vlan_yang
|
||||
input: input.json
|
||||
output: output.json
|
||||
62
infrahub/transforms/tests/vxlan_yang/input.json
Normal file
62
infrahub/transforms/tests/vxlan_yang/input.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"data": {
|
||||
"InfraVTEP": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"source_address": {
|
||||
"value": "10.0.255.11/32"
|
||||
},
|
||||
"udp_port": {
|
||||
"value": 4789
|
||||
},
|
||||
"learn_restrict": {
|
||||
"value": "any"
|
||||
},
|
||||
"source_interface": {
|
||||
"node": {
|
||||
"name": {
|
||||
"value": "Loopback1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"vlan_vni_mappings": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"description": {
|
||||
"value": "VLAN 40 <-> VNI 110040"
|
||||
},
|
||||
"vlan": {
|
||||
"node": {
|
||||
"vlan_id": {
|
||||
"value": 40
|
||||
},
|
||||
"name": {
|
||||
"value": "test-l2-vxlan"
|
||||
}
|
||||
}
|
||||
},
|
||||
"vni": {
|
||||
"node": {
|
||||
"vni": {
|
||||
"value": 110040
|
||||
},
|
||||
"vni_type": {
|
||||
"value": "l2vni"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"InfraVRFDeviceAssignment": {
|
||||
"edges": []
|
||||
}
|
||||
}
|
||||
}
|
||||
12
infrahub/transforms/tests/vxlan_yang/output.json
Normal file
12
infrahub/transforms/tests/vxlan_yang/output.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"vtep": {
|
||||
"learn_restrict": "any",
|
||||
"source_address": "10.0.255.11/32",
|
||||
"source_interface": "Loopback1",
|
||||
"udp_port": 4789,
|
||||
"vlan_vni_mappings": [
|
||||
{"vlan_id": 40, "vlan_name": "test-l2-vxlan", "vni": 110040, "vni_type": "l2vni"}
|
||||
],
|
||||
"vrf_vni_mappings": []
|
||||
}
|
||||
}
|
||||
15
infrahub/transforms/tests/vxlan_yang/test.yml
Normal file
15
infrahub/transforms/tests/vxlan_yang/test.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
version: "1.0"
|
||||
infrahub_tests:
|
||||
- resource: Jinja2Transform
|
||||
resource_name: vxlan_yang_transform
|
||||
tests:
|
||||
- name: smoke_check
|
||||
spec:
|
||||
kind: jinja2-transform-smoke
|
||||
- name: render_leaf1
|
||||
spec:
|
||||
kind: jinja2-transform-unit-render
|
||||
directory: infrahub/transforms/tests/vxlan_yang
|
||||
input: input.json
|
||||
output: output.json
|
||||
Reference in New Issue
Block a user