Reputation: 153
I know that similar questions have been asked before, but I still can't get the results that I want in my scenario. I have the following code snippet within my group_vars
folder. There are two BGP neighbors (1.1.1.1 and 1.1.1.2)
, which are listed at the group level. However, I want to be able to list one ore more additional neighbors, which I want to override at the host_vars level. The substitution for variable {{ bgp_neighbor_01 }}
does not work because as I understand, Ansible does not perform variable substitution for the dictionary keys. Is there a way to keep my first two IP addresses at the group level, but also define additional IP addresses at the host level? Thank you in advance.
bgp_neighbors:
1.1.1.1:
peer_group: EVPN-OVERLAY-PEERS
description: SPINE1_EVPN_ADDRESS_FAMILY
1.1.1.2:
peer_group: EVPN-OVERLAY-PEERS
description: SPINE2_EVPN_ADDRESS_FAMILY
'{{ bgp_neighbor_01 }}': <-- this variable does not get substituted
peer_group: '{{ peer_group_name }}'
description: '{{ description }}'
This is how I resolved my issue based on suggestion provided by Vladimir. I created the following dictionary variable in my group_vars
file.
evpn_bgp_neighbors:
1.1.1.1:
peer_group: EVPN-OVERLAY-PEERS
description: SPINE1_EVPN_ADDRESS_FAMILY
1.1.1.2:
peer_group: EVPN-OVERLAY-PEERS
description: SPINE2_EVPN_ADDRESS_FAMILY
Then, in each of my individual host files, I created host specific bgp neighbors dictionary, and then I used combine filter to combine group level and host level dictionaries.
underlay_bgp_neighbors:
192.168.1.0:
peer_group: IPv4-UNDERLAY-PEERS
description: SPINE1_IPv4_ADDRESS_FAMILY
192.168.1.128:
peer_group: IPv4-UNDERLAY-PEERS
description: SPINE2_IPv4_ADDRESS_FAMILY
my_bgp_neighbors: "{{ evpn_bgp_neighbors | combine(underlay_bgp_neighbors) }}"
Finally, back in my group_vars
file, I referenced the combined dictionary:
router_bgp:
neighbors: "{{ my_bgp_neighbors }}"
I did not need to make any modifications to my playbook. I only made changes to group_vars and host_vars files.
Upvotes: 0
Views: 938
Reputation: 68384
Q: "Keep my first two IP addresses at the group level, but also define additional IP addresses at the host level"
A: Combine the dictionary within the host_vars. For example, given the inventory
shell> cat hosts
[group1]
srv1
and the group_vars
shell> cat group_vars/group1.yml
bgp_neighbors:
1.1.1.1:
peer_group: EVPN-OVERLAY-PEERS
description: SPINE1_EVPN_ADDRESS_FAMILY
1.1.1.2:
peer_group: EVPN-OVERLAY-PEERS
description: SPINE2_EVPN_ADDRESS_FAMILY
combine the dictionary bgp_neighbors with bgp_neighbor_01 and create the variable my_bgp_neighbors within the host_vars
shell> cat host_vars/srv1.yml
bgp_neighbor_01:
peer_group: '{{ peer_group_name }}'
description: '{{ description }}'
my_bgp_neighbors: '{{ bgp_neighbors|default({})|
combine({"bgp_neighbor_01": bgp_neighbor_01}) }}'
Then the playbook
shell> cat playbook.yml
- hosts: srv1
vars:
peer_group_name: my-peer-group-name
description: my-description
tasks:
- debug:
var: my_bgp_neighbors
gives
ok: [srv1] =>
my_bgp_neighbors:
1.1.1.1:
description: SPINE1_EVPN_ADDRESS_FAMILY
peer_group: EVPN-OVERLAY-PEERS
1.1.1.2:
description: SPINE2_EVPN_ADDRESS_FAMILY
peer_group: EVPN-OVERLAY-PEERS
bgp_neighbor_01:
description: my-description
peer_group: my-peer-group-name
Unfortunately, it's not possible to combine dictionaries recursively within host_vars
shell> cat host_vars/srv1.yml
bgp_neighbor_01:
peer_group: '{{ peer_group_name }}'
description: '{{ description }}'
bgp_neighbors: '{{ bgp_neighbors|default({})|
combine({"bgp_neighbor_01": bgp_neighbor_01}) }}'
would crash
Error was a <class ''ansible.errors.AnsibleError''>, original message: recursive loop detected in template string: {{ bgp_neighbors|default({})| combine({"bgp_neighbor_01": bgp_neighbor_01}) }}'
Upvotes: 0
Reputation: 630
Why not change the group_vars to
bgp_neighbour:
- neighbour:
ip: 1.1.1.1:
peer_group: EVPN-OVERLAY-PEERS
description: SPINE1_EVPN_ADDRESS_FAMILY
- neighbour:
ip: 1.1.1.2:
peer_group: EVPN-OVERLAY-PEERS
description: SPINE2_EVPN_ADDRESS_FAMILY
- neighbour:
ip: '{{ bgp_neighbor_01 | default('empty')}}'
peer_group: '{{ peer_group_name }}'
description: '{{ description }}'
and loop over that in a for loop and stop when ip is empty? Also check https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable
Upvotes: 1