exit: support custom VRF imports
Ten minutes to set up and ten hours to convince Ansible to not be quite so retarded. The list2dict filter seems to be the (or another) missing piece. Now let’s rewrite everything else using it. Or not.
This commit is contained in:
parent
99aef43574
commit
82b10e8133
14
filter_plugins/util.py
Normal file
14
filter_plugins/util.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
class FilterModule(object):
|
||||
'''Helper filters to make Ansible less unpleasant'''
|
||||
def filters(self):
|
||||
return {
|
||||
'list2dict': self.list2dict,
|
||||
}
|
||||
|
||||
def list2dict(self, items, key):
|
||||
'''
|
||||
Like items2dict but keep entire dictionaries as values.
|
||||
'''
|
||||
return {item[key]: item for item in items}
|
|
@ -5,7 +5,7 @@
|
|||
- name: Install keepalived
|
||||
import_tasks: keepalived.yml
|
||||
|
||||
- name: Configure relay for old DHCP server
|
||||
- name: Configure DHCP relays
|
||||
template:
|
||||
dest: '/etc/default/isc-dhcp-relay-{{ prefixes | selectattr("prefix", "==", item.0 | ipaddr("network/prefix")) | map(attribute="vrf.name") | first }}'
|
||||
src: isc-dhcp-relay.j2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
| selectattr('role') | selectattr('role.value', '==', 'loopback')
|
||||
| map(attribute='address') %}
|
||||
{% set inside_vrfs = interfaces | selectattr('parent') | selectattr('parent.name', '==', 'bridge')
|
||||
| selectattr('vrf') | map(attribute='vrf') | rejectattr('name', '==', 'outside') -%}
|
||||
| selectattr('vrf') | map(attribute='vrf.name') | reject('==', 'outside') | sort %}
|
||||
|
||||
frr defaults datacenter
|
||||
log syslog informational
|
||||
|
@ -158,7 +158,7 @@ router bgp {{ asn.asn }} vrf inside
|
|||
|
||||
redistribute connected route-map loopback-inside
|
||||
{% for vrf in inside_vrfs %}
|
||||
import vrf {{ vrf.name }}
|
||||
import vrf {{ vrf }}
|
||||
{% endfor %}
|
||||
import vrf default
|
||||
import vrf route-map inside-import
|
||||
|
@ -180,14 +180,14 @@ router bgp {{ asn.asn }} vrf inside
|
|||
|
||||
redistribute connected route-map loopback-inside
|
||||
{% for vrf in inside_vrfs %}
|
||||
import vrf {{ vrf.name }}
|
||||
import vrf {{ vrf }}
|
||||
{% endfor %}
|
||||
import vrf default
|
||||
import vrf route-map inside-import
|
||||
exit-address-family
|
||||
|
||||
|
||||
{% for vrf in inside_vrfs %}
|
||||
{% for vrf in vrfs.values() | selectattr('name', 'in', inside_vrfs) %}
|
||||
# VRF for L2 network {{ vrf.name }}. Imports gateway from inside VRF.
|
||||
router bgp {{ asn.asn }} vrf {{ vrf.name }}
|
||||
bgp bestpath as-path multipath-relax
|
||||
|
@ -195,13 +195,27 @@ router bgp {{ asn.asn }} vrf {{ vrf.name }}
|
|||
address-family ipv4 unicast
|
||||
redistribute connected
|
||||
import vrf inside
|
||||
{% if vrf.custom_fields.imports %}
|
||||
{% for import in vrf.custom_fields.imports %}
|
||||
import vrf {{ import.name }}
|
||||
{% endfor %}
|
||||
import vrf route-map {{ vrf.name }}-import
|
||||
{% else %}
|
||||
import vrf route-map office-import
|
||||
{% endif %}
|
||||
exit-address-family
|
||||
|
||||
address-family ipv6 unicast
|
||||
redistribute connected
|
||||
import vrf inside
|
||||
{% if vrf.custom_fields.imports %}
|
||||
{% for import in vrf.custom_fields.imports %}
|
||||
import vrf {{ import.name }}
|
||||
{% endfor %}
|
||||
import vrf route-map {{ vrf.name }}-import
|
||||
{% else %}
|
||||
import vrf route-map office-import
|
||||
{% endif %}
|
||||
exit-address-family
|
||||
|
||||
{% endfor %}
|
||||
|
@ -213,8 +227,8 @@ ipv6 prefix-list default permit ::/0
|
|||
ip prefix-list fabric permit 10.34.0.0/24 ge 32
|
||||
ipv6 prefix-list fabric permit 2001:1470:fffd:3400::/64 ge 128
|
||||
|
||||
{% for prefix in vrf_prefixes
|
||||
| selectattr('vrf.id', 'in', inside_vrfs|map(attribute='id'))
|
||||
# common prefix list for all inside networks
|
||||
{% for prefix in vrf_prefixes | selectattr('vrf.name', 'in', inside_vrfs)
|
||||
| sort(attribute='family.value') | sort(attribute='vlan.vid') %}
|
||||
{% if prefix.family.value == 4 %}
|
||||
ip prefix-list office permit {{ prefix.prefix }} ge {{ prefix.prefix | ipaddr('prefix') }}
|
||||
|
@ -223,6 +237,16 @@ ipv6 prefix-list office permit {{ prefix.prefix }} ge {{ prefix.prefix | ipaddr(
|
|||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
# individual prefix lists for each inside network
|
||||
{% for prefix in vrf_prefixes | selectattr('vrf.name', 'in', inside_vrfs)
|
||||
| sort(attribute='family.value') | sort(attribute='vlan.vid') %}
|
||||
{% if prefix.family.value == 4 %}
|
||||
ip prefix-list {{ prefix.vrf.name }} permit {{ prefix.prefix }} ge {{ prefix.prefix | ipaddr('prefix') }}
|
||||
{% else %}
|
||||
ipv6 prefix-list {{ prefix.vrf.name }} permit {{ prefix.prefix }} ge {{ prefix.prefix | ipaddr('prefix') }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if wg_net is defined %}
|
||||
ip prefix-list vpn permit {{ wg_net | ipaddr('subnet') }}
|
||||
{% endif %}
|
||||
|
@ -278,6 +302,20 @@ route-map inside-import permit 20
|
|||
route-map inside-import permit 21
|
||||
match ipv6 address prefix-list office
|
||||
|
||||
{% for vrf in vrfs.values() | selectattr('custom_fields.imports') %}
|
||||
route-map {{ vrf.name }}-import permit 10
|
||||
match ip address prefix-list default
|
||||
route-map {{ vrf.name }}-import permit 11
|
||||
match ipv6 address prefix-list default
|
||||
{% for import in vrf.custom_fields.imports %}
|
||||
route-map {{ vrf.name }}-import permit {{ 100 + 10*loop.index0 }}
|
||||
match ip address prefix-list {{ import.name }}
|
||||
route-map {{ vrf.name }}-import permit {{ 101 + 10*loop.index0 }}
|
||||
match ipv6 address prefix-list {{ import.name }}
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
# Route maps for advertised and received routes.
|
||||
# Default VRF ↔ fabric.
|
||||
route-map default->fabric permit 10
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
set_fact:
|
||||
vlans: '{{ query("netbox.netbox.nb_lookup", "vlans", api_filter="group=new-net", raw_data=true)
|
||||
| sort(attribute="vid") }}'
|
||||
vrfs: '{{ query("netbox.netbox.nb_lookup", "vrfs", raw_data=true) | list2dict("name") }}'
|
||||
prefixes: '{{ query("netbox.netbox.nb_lookup", "prefixes", raw_data=true)
|
||||
| sort(attribute="prefix") | sort(attribute="family.value") }}'
|
||||
|
||||
|
|
Loading…
Reference in a new issue