Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .infrahub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ jinja2_transforms:
description: "Template to generate startup configuration for network devices"
query: "device_startup_info"
template_path: "templates/device_startup_config.tpl.j2"
- name: "device_startup_interfaces"
description: "Template to generate startup interface configuration for network devices"
query: "device_startup_interfaces"
template_path: "templates/device_startup_interfaces.j2"

- name: "clab_topology"
query: "topology_info"
Expand Down Expand Up @@ -82,6 +86,8 @@ queries:
file_path: "transforms/oc_interfaces.gql"
- name: device_startup_info
file_path: "templates/device_startup_info.gql"
- name: device_startup_interfaces
file_path: "templates/device_startup_interfaces.gql"
- name: upstream_interfaces
file_path: "generators/upstream_interfaces.gql"
- name: drained_circuit_bgp_sessions
Expand Down
58 changes: 4 additions & 54 deletions templates/device_startup_config.tpl.j2
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
{% set ns = namespace(loopback_intf_name=none, loopback_ip=none, management_intf_name=none, management_ip=none) %}
{% for intf in data.InfraDevice.edges[0].node.interfaces.edges %}
{% if intf.node.role.value == "loopback" %}
{% set ns.loopback_intf_name = intf.node.name.value %}
{% set ns.loopback_ip = intf.node.ip_addresses.edges[0].node.address.value.split('/')[0] %}
{% elif intf.node.role.value == "management" %}
{% set ns.management_intf_name = intf.node.name.value %}
{% set ns.management_ip = intf.node.ip_addresses.edges[0].node.address.value.split('/')[0] %}
{% endif %}
{% endfor %}

no aaa root
!
username admin privilege 15 role network-admin secret sha512 $6$q4ez.aZgB/G/eeWW$ukvRobb5RtYmUlCcY0atxhwPmA6FPoRjR3AxYFJqNFoCRgJjrohKGrBsbY12n1uRZeCer1L8oejx5aPlrf.op0
Expand All @@ -29,50 +20,9 @@ management api gnmi
management api netconf
transport ssh default
!
{% for intf in data.InfraDevice.edges[0].node.interfaces.edges %}
{% if intf.node.name.value != ns.management_intf_name and intf.node.name.value != ns.loopback_intf_name %}
interface {{ intf.node.name.value }}
{% if intf.node["description"]["value"] %}
description {{ intf.node["description"]["value"] }}
{% else %}
description role: {{ intf.node.role.value }}
{% endif %}
{% if "mtu" in intf.node and intf.node["mtu"]["value"] %}
mtu {{ intf.node["mtu"]["value"] }}
{% endif %}
{% if not intf.node["enabled"]["value"] %}
shutdown
{% endif %}
{% if intf.node["ip_addresses"] %}
{% for ip in intf.node["ip_addresses"]["edges"] %}
ip address {{ ip.node["address"]["value"] }}
no switchport
{% if intf.node.role.value == "peer" or intf.node.role.value == "backbone" %}
ip ospf network point-to-point
{% endif %}
{% endfor %}
{% endif %}
!
{% endif %}
{% endfor %}
!
interface {{ ns.management_intf_name }}
{% for intf in data.InfraDevice.edges[0]["interfaces"] %}
{% if intf.node.name.value == ns.management_intf_name %}
{% for ip in intf["ip_addresses"] %}
ip address {{ ip["address"]["value"] }}
{% endfor %}
{% endif %}
{% endfor %}
!
interface {{ ns.loopback_intf_name }}
{% for intf in data.InfraDevice.edges[0]["interfaces"] %}
{% if intf.node.name.value == ns.loopback_intf_name %}
{% for ip in intf["ip_addresses"] %}
ip address {{ ip["address"]["value"] }}
{% endfor %}
{% endif %}
{% endfor %}

{% from "templates/device_startup_interfaces.j2" import render_interfaces %}
{{ render_interfaces(data.InfraDevice.edges[0].node.interfaces.edges) }}
!
ip prefix-list BOGON-Prefixes seq 10 permit 172.16.0.0/12 le 24
ip prefix-list BOGON-Prefixes seq 20 permit 192.168.0.0/16 le 24
Expand Down
35 changes: 35 additions & 0 deletions templates/device_startup_interfaces.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
query device_startup_interface ($device: String, $interface: String) {
InfraInterface(device__name__value: $device, name__value: $interface) {
edges {
node {
id
name {
value
}
description {
value
}
enabled {
value
}
mtu {
value
}
role {
value
}
... on InfraInterfaceL3 {
ip_addresses {
edges {
node {
address {
value
}
}
}
}
}
}
}
}
}
60 changes: 60 additions & 0 deletions templates/device_startup_interfaces.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{% macro render_interfaces(device_interfaces) %}
{% set ns = namespace(loopback_intf_name=none, loopback_ip=none, management_intf_name=none, management_ip=none) %}
{% for intf in device_interfaces %}
{% if intf.node.role.value == "loopback" %}
{% set ns.loopback_intf_name = intf.node.name.value %}
{% set ns.loopback_ip = intf.node.ip_addresses.edges[0].node.address.value.split('/')[0] %}
{% elif intf.node.role.value == "management" %}
{% set ns.management_intf_name = intf.node.name.value %}
{% set ns.management_ip = intf.node.ip_addresses.edges[0].node.address.value.split('/')[0] %}
{% endif %}
{% endfor %}
{% for intf in device_interfaces %}
{% if intf.node.name.value != ns.management_intf_name and intf.node.name.value != ns.loopback_intf_name %}
interface {{ intf.node.name.value }}
{% if intf.node["description"]["value"] %}
description {{ intf.node["description"]["value"] }}
{% else %}
description role: {{ intf.node.role.value }}
{% endif %}
{% if "mtu" in intf.node and intf.node["mtu"]["value"] %}
mtu {{ intf.node["mtu"]["value"] }}
{% endif %}
{% if not intf.node["enabled"]["value"] %}
shutdown
{% endif %}
{% if intf.node["ip_addresses"] %}
{% for ip in intf.node["ip_addresses"]["edges"] %}
ip address {{ ip.node["address"]["value"] }}
no switchport
{% if intf.node.role.value == "peer" or intf.node.role.value == "backbone" %}
ip ospf network point-to-point
{% endif %}
{% endfor %}
{% endif %}
!
{% endif %}
{% endfor %}
!
interface {{ ns.management_intf_name }}
{% for intf in device_interfaces %}
{% if intf.node.name.value == ns.management_intf_name %}
{% for ip in intf["ip_addresses"] %}
ip address {{ ip["address"]["value"] }}
{% endfor %}
{% endif %}
{% endfor %}
!
interface {{ ns.loopback_intf_name }}
{% for intf in device_interfaces %}
{% if intf.node.name.value == ns.loopback_intf_name %}
{% for ip in intf["ip_addresses"] %}
ip address {{ ip["address"]["value"] }}
{% endfor %}
{% endif %}
{% endfor %}
!
{%- endmacro -%}
{%- if data is defined %}
{{ render_interfaces(data.InfraInterface.edges) }}
{% endif %}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this conditional if-statement all the rendering of the base template fails because data is not defined. Another approach to this would be to place all macros in a separate file. Though in that case this stand-alone interface template would only import the macro and then render the macro.