I'm new at Ansible and trying to automate a Fortigate configuration using the fortinet.fortios modules.
I'm having a problem with fortios_firewall_addrgrp
specifically that does not support the append of a firewall address to a group.
I have this set in my variables:
addresses:
host_0:
subnet: 192.168.1.10/24
group: group_0
host_1:
subnet: 192.168.1.11/24
group: group_0
host_2:
subnet: 192.168.10.10/24
group: group_1
host_3:
subnet: 192.168.10.11/24
group: group_1
And I'm running this task to generate an address group.
- name: Configure IPv4 address groups.
fortios_firewall_addrgrp:
vdom: '{{ vdom }}'
state: present
firewall_addrgrp:
name: '{{ item.value.group }}'
member:
- name: '{{ item.key }}'
loop: '{{ addresses | dict2items }}'
It loops through each host and generates an address group, but it results in having 2 groups containing only the last hostname in the list.
Ideally, the module should support the append of a hostname to an existing group, but it doesn't, so I'm trying to work around it to make the following happening:
member:
- name: host_0
- name: host_1
The example above would work, but I cannot know in advance groups and hostnames in the variable.
I could generate or filter the input variable into a dictionary of host and groups and give it to members. Still, I cannot understand how to loop through it dynamically.
The problem you are having is related to the data structure you are using for the loop. As you mentioned, the fortios_firewall_addrgrp
module expects a list of dictionaries for the members
key, representing each host.
So, you need to create a new data structure that fits the input of the fortios_firewall_addrgrp
module. Here is an example of how to do it:
---
- hosts: localhost
gather_facts: 'no'
vars:
addresses:
host_0:
subnet: 192.168.1.10/24
group: group_0
host_1:
subnet: 192.168.1.11/24
group: group_0
host_2:
subnet: 192.168.10.10/24
group: group_1
host_3:
subnet: 192.168.10.11/24
group: group_1
tasks:
- set_fact:
addresses_by_group: |
{{
addresses_by_group | default({}) | combine({
item.value.group: (addresses_by_group[item.value.group] | default([])) + [{"name": item.key}]
})
}}
loop: '{{ addresses | dict2items }}'
- name: Configure IPv4 address groups.
fortios_firewall_addrgrp:
vdom: '{{ vdom }}'
state: present
firewall_addrgrp:
name: '{{ item.key }}'
member: '{{ item.value }}'
loop: '{{ addresses_by_group | dict2items }}'
We create a new variable called addresses_by_group
that will store a list of hosts for each group. The combine
filter allows you to combine two different dictionaries, while the default
filter sets a default value for an undefined variable. We use the +
operator to concatenate two lists. If you debug the value of the variable addresses_by_group
you'll see this:
TASK [debug] *******************************************************************
ok: [localhost] =>
addresses_by_group:
group_0:
- name: host_0
- name: host_1
group_1:
- name: host_2
- name: host_3
Which is just what we need. Bear in mind that we didn't touch the addresses
variables so that you can use them later on.