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
12 changes: 12 additions & 0 deletions .infrahub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ 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_bgp"
description: "Template to generate startup BGP configuration for network devices"
query: "device_startup_bgp"
template_path: "templates/device_startup_bgp.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 +90,10 @@ queries:
file_path: "transforms/oc_interfaces.gql"
- name: device_startup_info
file_path: "templates/device_startup_info.gql"
- name: device_startup_bgp
file_path: "templates/device_startup_bgp.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
38 changes: 38 additions & 0 deletions templates/device_startup_bgp.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
query device_startup_info ($device: String!, $bgp_group: String) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Require device but allow the filtering of a group to be optional

InfraDevice(name__value: $device) {
edges {
node {
asn {
node {
asn {
value
}
}
}
}
}
}
InfraBGPPeerGroup(name__value: $bgp_group) {
edges {
node {
name {
value
}
local_as {
node {
asn {
value
}
}
}
remote_as {
node {
asn {
value
}
}
}
}
}
}
}
14 changes: 14 additions & 0 deletions templates/device_startup_bgp.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% if data.InfraDevice.edges[0].node.asn %}
router bgp {{ data.InfraDevice.edges[0].node.asn.node.asn.value }}
router-id {{ loopback_ip }}
{% for peer_group in data.InfraBGPPeerGroup.edges %}
neighbor {{ peer_group.node.name.value }} peer group
{% if peer_group.node.local_as %}
neighbor {{ peer_group.node.name.value }} local-as {{ peer_group.node.local_as.node.asn.value }}
{% endif %}
{% if peer_group.node.remote_as and peer_group.node.remote_as.node %}
neighbor {{ peer_group.node.name.value }} remote-as {{ peer_group.node.remote_as.node.asn.value }}
{% endif %}
{% endfor %}
!
{% endif %}
74 changes: 6 additions & 68 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 %}
{% set device_interfaces = data.InfraDevice.edges[0].node.interfaces.edges %}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Previously we had a section that set the loopback and management interface at the top of the startup config template. There we'd iterate over data.InfraDevice.edges[0].node.interfaces.edges as we now have another template where we don't query for InfraDevice but instead for InfraInterface we need to manage these different scenarios. For this reason we set the device_interfaces variable within the main template and use a conditional statement in the imported device_startup_interfaces.j2 for the alternative.

{% include "templates/device_startup_interfaces.j2" %}

!
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 All @@ -83,20 +33,8 @@ ip routing
!
ip route 0.0.0.0/0 172.20.20.1
!
{% if data.InfraDevice.edges[0].node.asn %}
router bgp {{ data.InfraDevice.edges[0].node.asn.node.asn.value }}
router-id {{ loopback_ip }}
{% for peer_group in data.InfraBGPPeerGroup.edges %}
neighbor {{ peer_group.node.name.value }} peer group
{% if peer_group.node.local_as %}
neighbor {{ peer_group.node.name.value }} local-as {{ peer_group.node.local_as.node.asn.value }}
{% endif %}
{% if peer_group.node.remote_as and peer_group.node.remote_as.node %}
neighbor {{ peer_group.node.name.value }} remote-as {{ peer_group.node.remote_as.node.asn.value }}
{% endif %}
{% endfor %}
!
{% endif %}
{% include "templates/device_startup_bgp.j2" %}

!
router ospf 1
router-id {{ loopback_ip }}
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
}
}
}
}
}
}
}
}
}
59 changes: 59 additions & 0 deletions templates/device_startup_interfaces.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{% if device_interfaces is not defined %}
{% set device_interfaces = data.InfraInterface.edges %}
{% endif %}

{% set ns = namespace(loopback_intf_name=none, loopback_ip=none, management_intf_name=none, management_ip=none) %}
{% for intf in device_interfaces %}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The only difference when this file is moved is that we iterate over device_interfaces instead of 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 %}
{% 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 %}
!