diff --git a/.infrahub.yml b/.infrahub.yml index a2e5752..ed74a4f 100644 --- a/.infrahub.yml +++ b/.infrahub.yml @@ -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: transforms/queries/vlan_intent.gql + - name: interface_intent + file_path: transforms/queries/interface_intent.gql + - name: vxlan_intent + file_path: transforms/queries/vxlan_intent.gql + +jinja2_transforms: + - name: vlan_yang_transform + description: "Generate VLAN configuration payload from Infrahub intent" + query: vlan_intent + template_path: transforms/templates/vlan_yang.j2 + - name: interface_yang_transform + description: "Generate interface configuration payload from Infrahub intent" + query: interface_intent + template_path: transforms/templates/interface_yang.j2 + - name: vxlan_yang_transform + description: "Generate VXLAN/VTEP configuration payload from Infrahub intent" + query: vxlan_intent + template_path: transforms/templates/vxlan_yang.j2 diff --git a/transforms/queries/interface_intent.gql b/transforms/queries/interface_intent.gql new file mode 100644 index 0000000..1cb1106 --- /dev/null +++ b/transforms/queries/interface_intent.gql @@ -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 + } + } + } + } + } + } + } +} diff --git a/transforms/queries/vlan_intent.gql b/transforms/queries/vlan_intent.gql new file mode 100644 index 0000000..bcd0f7b --- /dev/null +++ b/transforms/queries/vlan_intent.gql @@ -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 + } + } + } + } + } + } + } + } +} diff --git a/transforms/queries/vxlan_intent.gql b/transforms/queries/vxlan_intent.gql new file mode 100644 index 0000000..ed182c6 --- /dev/null +++ b/transforms/queries/vxlan_intent.gql @@ -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 + } + } + } + } + } + } + } + } + } +} diff --git a/transforms/templates/interface_yang.j2 b/transforms/templates/interface_yang.j2 new file mode 100644 index 0000000..f0164ea --- /dev/null +++ b/transforms/templates/interface_yang.j2 @@ -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, + "enabled": iface.enabled.value, + "mtu": iface.mtu.value, + "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 = null -%} + {%- if iface.lag and iface.lag.node -%} + {%- set lag_name = iface.lag.node.name.value -%} + {%- endif -%} + {%- set _ = interfaces.append({ + "type": "ethernet", + "name": iface.name.value, + "description": iface.description.value, + "enabled": iface.enabled.value, + "mtu": iface.mtu.value, + "speed": iface.speed.value, + "mode": iface.mode.value, + "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 = null -%} + {%- if iface.vlan and iface.vlan.node -%} + {%- set vlan_id = iface.vlan.node.vlan_id.value -%} + {%- endif -%} + {%- set _ = interfaces.append({ + "type": "vlan", + "name": iface.name.value, + "description": iface.description.value, + "enabled": iface.enabled.value, + "mtu": iface.mtu.value, + "vlan_id": vlan_id, + "virtual_router_address": iface.virtual_router_address.value, + "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, + "enabled": iface.enabled.value, + "mtu": iface.mtu.value, + "lacp_mode": iface.lacp_mode.value, + "mlag_id": iface.mlag_id.value, + "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) }} diff --git a/transforms/templates/vlan_yang.j2 b/transforms/templates/vlan_yang.j2 new file mode 100644 index 0000000..bd7a057 --- /dev/null +++ b/transforms/templates/vlan_yang.j2 @@ -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 = null -%} + {%- set vni_type_val = null -%} + {%- if vlan_node.vni and vlan_node.vni.node -%} + {%- 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 | upper, + "vlan_type": vlan_node.vlan_type.value, + "trunk_groups": vlan_node.trunk_groups.value if vlan_node.trunk_groups.value else [], + "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 and svi_edge.node.vlan.node -%} + {%- set vlan_node = svi_edge.node.vlan.node -%} + {%- set vid = vlan_node.vlan_id.value | string -%} + {%- if vid not in vlans -%} + {%- set vni_val = null -%} + {%- set vni_type_val = null -%} + {%- if vlan_node.vni and vlan_node.vni.node -%} + {%- 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 | upper, + "vlan_type": vlan_node.vlan_type.value, + "trunk_groups": vlan_node.trunk_groups.value if vlan_node.trunk_groups.value else [], + "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) }} diff --git a/transforms/templates/vxlan_yang.j2 b/transforms/templates/vxlan_yang.j2 new file mode 100644 index 0000000..62f3280 --- /dev/null +++ b/transforms/templates/vxlan_yang.j2 @@ -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 = null -%} + {%- if vtep.source_interface and vtep.source_interface.node -%} + {%- 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 = null -%} + {%- set vlan_name = null -%} + {%- if m.vlan and m.vlan.node -%} + {%- set vlan_id = m.vlan.node.vlan_id.value -%} + {%- set vlan_name = m.vlan.node.name.value -%} + {%- endif -%} + {%- set vni_val = null -%} + {%- set vni_type_val = null -%} + {%- if m.vni and m.vni.node -%} + {%- 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 = null -%} + {%- set l3vni = null -%} + {%- set import_rts = [] -%} + {%- set export_rts = [] -%} + {%- if assignment.vrf and assignment.vrf.node -%} + {%- set vrf_node = assignment.vrf.node -%} + {%- set vrf_name = vrf_node.name.value -%} + {%- if vrf_node.l3vni and vrf_node.l3vni.node -%} + {%- 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, + "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, + "vlan_vni_mappings": vlan_vni_list | sort(attribute='vlan_id'), + "vrf_vni_mappings": vrf_vni_list + } + } -%} +{%- else -%} + {%- set result = { + "vtep": null, + "vrf_vni_mappings": [] + } -%} +{%- endif -%} +{{ result | tojson(indent=2) }} diff --git a/transforms/tests/interface_yang/input.json b/transforms/tests/interface_yang/input.json new file mode 100644 index 0000000..815043e --- /dev/null +++ b/transforms/tests/interface_yang/input.json @@ -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": [ + { + "node": { + "address": { + "value": "10.0.255.11/32" + } + } + } + ] + } + } + } + ] + }, + "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.255.255.0/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": [] + } + } + } + ] + }, + "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": [] + } + } + } + ] + } + } +} diff --git a/transforms/tests/interface_yang/output.json b/transforms/tests/interface_yang/output.json new file mode 100644 index 0000000..f4f79e2 --- /dev/null +++ b/transforms/tests/interface_yang/output.json @@ -0,0 +1,106 @@ +[ + { + "type": "ethernet", + "name": "Ethernet1", + "description": "host1", + "enabled": true, + "mtu": null, + "speed": null, + "mode": "trunk", + "lag": "Port-Channel1", + "ip_addresses": [] + }, + { + "type": "ethernet", + "name": "Ethernet10", + "description": "mlag peer link", + "enabled": true, + "mtu": null, + "speed": null, + "mode": "trunk", + "lag": "Port-Channel999", + "ip_addresses": [] + }, + { + "type": "ethernet", + "name": "Ethernet11", + "description": "spine1", + "enabled": true, + "mtu": 9214, + "speed": null, + "mode": "routed", + "lag": null, + "ip_addresses": ["10.0.1.1/31"] + }, + { + "type": "ethernet", + "name": "Ethernet12", + "description": "spine2", + "enabled": true, + "mtu": 9214, + "speed": null, + "mode": "routed", + "lag": null, + "ip_addresses": ["10.0.2.1/31"] + }, + { + "type": "loopback", + "name": "Loopback0", + "description": "Router-ID", + "enabled": true, + "mtu": null, + "ip_addresses": ["10.0.250.11/32"] + }, + { + "type": "loopback", + "name": "Loopback1", + "description": "VTEP", + "enabled": true, + "mtu": null, + "ip_addresses": ["10.0.255.11/32"] + }, + { + "type": "lag", + "name": "Port-Channel1", + "description": "host1", + "enabled": true, + "mtu": null, + "lacp_mode": "active", + "mlag_id": 1, + "members": ["Ethernet1"], + "ip_addresses": [] + }, + { + "type": "lag", + "name": "Port-Channel999", + "description": "MLAG Peer", + "enabled": true, + "mtu": null, + "lacp_mode": "active", + "mlag_id": null, + "members": ["Ethernet10"], + "ip_addresses": [] + }, + { + "type": "vlan", + "name": "Vlan4090", + "description": "MLAG Peer-Link", + "enabled": true, + "mtu": null, + "vlan_id": 4090, + "virtual_router_address": null, + "autostate": false, + "ip_addresses": ["10.255.255.0/31"] + }, + { + "type": "vlan", + "name": "Vlan4091", + "description": "MLAG iBGP Peering", + "enabled": true, + "mtu": 9214, + "vlan_id": 4091, + "virtual_router_address": null, + "autostate": true, + "ip_addresses": [] + } +] diff --git a/transforms/tests/interface_yang/test.yml b/transforms/tests/interface_yang/test.yml new file mode 100644 index 0000000..040d385 --- /dev/null +++ b/transforms/tests/interface_yang/test.yml @@ -0,0 +1,13 @@ +--- +# Integration test for interface_yang_transform +# Usage: infrahubctl test transforms/tests/interface_yang/test.yml +apiVersion: infrahub.app/v1 +kind: IntegrationTest +spec: + kind: jinja2-transform-integration + name: interface_yang_transform_leaf1 + transform: interface_yang_transform + params: + device_name: leaf1 + input: input.json + output: output.json diff --git a/transforms/tests/vlan_yang/input.json b/transforms/tests/vlan_yang/input.json new file mode 100644 index 0000000..73469ec --- /dev/null +++ b/transforms/tests/vlan_yang/input.json @@ -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": [] + }, + "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 + } + } + } + } + ] + } + } +} diff --git a/transforms/tests/vlan_yang/output.json b/transforms/tests/vlan_yang/output.json new file mode 100644 index 0000000..a816e5a --- /dev/null +++ b/transforms/tests/vlan_yang/output.json @@ -0,0 +1,32 @@ +[ + { + "vlan_id": 40, + "name": "test-l2-vxlan", + "status": "ACTIVE", + "vlan_type": "standard", + "trunk_groups": [], + "stp_enabled": true, + "vni": 110040, + "vni_type": "l2vni" + }, + { + "vlan_id": 4090, + "name": "mlag-peer", + "status": "ACTIVE", + "vlan_type": "mlag_peer", + "trunk_groups": ["mlag-peer"], + "stp_enabled": false, + "vni": null, + "vni_type": null + }, + { + "vlan_id": 4091, + "name": "mlag-ibgp", + "status": "ACTIVE", + "vlan_type": "mlag_ibgp", + "trunk_groups": ["mlag-peer"], + "stp_enabled": false, + "vni": null, + "vni_type": null + } +] diff --git a/transforms/tests/vlan_yang/test.yml b/transforms/tests/vlan_yang/test.yml new file mode 100644 index 0000000..7546d61 --- /dev/null +++ b/transforms/tests/vlan_yang/test.yml @@ -0,0 +1,13 @@ +--- +# Integration test for vlan_yang_transform +# Usage: infrahubctl test transforms/tests/vlan_yang/test.yml +apiVersion: infrahub.app/v1 +kind: IntegrationTest +spec: + kind: jinja2-transform-integration + name: vlan_yang_transform_leaf1 + transform: vlan_yang_transform + params: + device_name: leaf1 + input: input.json + output: output.json diff --git a/transforms/tests/vxlan_yang/input.json b/transforms/tests/vxlan_yang/input.json new file mode 100644 index 0000000..69a19c5 --- /dev/null +++ b/transforms/tests/vxlan_yang/input.json @@ -0,0 +1,62 @@ +{ + "data": { + "InfraVTEP": { + "edges": [ + { + "node": { + "source_address": { + "value": "10.0.255.11" + }, + "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": [] + } + } +} diff --git a/transforms/tests/vxlan_yang/output.json b/transforms/tests/vxlan_yang/output.json new file mode 100644 index 0000000..b8353da --- /dev/null +++ b/transforms/tests/vxlan_yang/output.json @@ -0,0 +1,17 @@ +{ + "vtep": { + "source_address": "10.0.255.11", + "source_interface": "Loopback1", + "udp_port": 4789, + "learn_restrict": "any", + "vlan_vni_mappings": [ + { + "vlan_id": 40, + "vlan_name": "test-l2-vxlan", + "vni": 110040, + "vni_type": "l2vni" + } + ], + "vrf_vni_mappings": [] + } +} diff --git a/transforms/tests/vxlan_yang/test.yml b/transforms/tests/vxlan_yang/test.yml new file mode 100644 index 0000000..f911870 --- /dev/null +++ b/transforms/tests/vxlan_yang/test.yml @@ -0,0 +1,13 @@ +--- +# Integration test for vxlan_yang_transform +# Usage: infrahubctl test transforms/tests/vxlan_yang/test.yml +apiVersion: infrahub.app/v1 +kind: IntegrationTest +spec: + kind: jinja2-transform-integration + name: vxlan_yang_transform_leaf1 + transform: vxlan_yang_transform + params: + device_name: leaf1 + input: input.json + output: output.json