Variable:
customers:
- name: CompanyX
destination_addresses:
- 192.168.0.0/24
- 192.168.1.0/24
- name: CompanyY
destination_addresses:
- 192.168.2.0/24
- 192.168.3.0/24
I'm trying to create address objects for each address in destination_addresses, and create an address group object that stores all addresses per customer.
The creation of each address works as expected like this:
- name: add address object for destination networks
fortinet.fortios.fortios_firewall_address:
state: present
firewall_address:
name: "{{ item.0.name }}-{{ item.1 }}"
subnet: "{{ item.1 }}"
loop: "{{ customers | subelements('destination_addresses') }}"
This creates:
CompanyX-192.168.0.0/24
CompanyX-192.168.1.0/24
CompanyY-192.168.2.0/24
CompanyY-192.168.3.0/24
But I'm struggling how to group the address objects.
This is what I use now:
- set_fact:
grp_members: "{{ grp_members | default([]) + [{ 'name': item.0.name ~ '-' ~ item.1 }] }}"
loop: "{{ customers | subelements('destination_addresses') }}"
loop_control:
extended: yes
- name: create address group
fortinet.fortios.fortios_firewall_addrgrp:
state: present
firewall_addrgrp:
name: "{{ item.name }}"
member: "{{ grp_members }}"
loop: "{{ customers }}"
Which creates the group CompanyX and CompanyY but with all addresses in each group, because the grp_members
variable contains all addresses.
How can I limit the group members to only contain the addresses for CompanyX & CompanyY separately?
Current output:
- debug:
var: grp_members
"grp_members": [
{
"name": "CompanyX-192.168.0.0/24"
},
{
"name": "CompanyX-192.168.1.0/24"
},
{
"name": "CompanyY-192.168.2.0/24"
},
{
"name": "CompanyY-192.168.3.0/24"
}
]
Desired result for each customer:
"grp_members": [
{
"name": "CompanyX-192.168.0.0/24"
},
{
"name": "CompanyX-192.168.1.0/24"
}
]
"grp_members": [
{
"name": "CompanyY-192.168.2.0/24"
},
{
"name": "CompanyY-192.168.3.0/24"
}
]
The fortinet.fortios.fortios_firewall_addrgrp module expects a dictionary in the above syntax.
With the changed conditions you need the following:
- name: create address group
fortinet.fortios.fortios_firewall_addrgrp:
state: present
firewall_addrgrp:
name: "{{ item.name }}"
member: "{{ grp_members }}"
vars:
grp_members: "{{ [item.name] | product(item.destination_addresses) | map('join', '-') | map('community.general.dict_kv', 'name') }}"
loop: "{{ customers }}"
You continue iterating over customers
. The variable grp_members
is generated locally for each iteration.
product
a cross product of the customer with each IP is createdjoin
the two elements customer name and IP are connected.dict_kv
creates a dict from the list with the key name
.You don't need your task with set_fact
anymore.
Here you can see the sample output of the joined addresses.
This task
- name: generate kv dict with customer-address
debug:
msg: "{{ grp_members }}"
vars:
grp_members: "{{ [item.name] | product(item.destination_addresses) | map('join', '-') | map('community.general.dict_kv', 'name') }}"
loop: "{{ customers }}"
produces this output
TASK [generate kv dict with customer-address] *******************************************************************************
ok: [localhost] => (item={'name': 'CompanyX', 'destination_addresses': ['192.168.0.0/24', '192.168.1.0/24']}) => {
"msg": [
{
"name": "CompanyX-192.168.0.0/24"
},
{
"name": "CompanyX-192.168.1.0/24"
}
]
}
ok: [localhost] => (item={'name': 'CompanyY', 'destination_addresses': ['192.168.2.0/24', '192.168.3.0/24']}) => {
"msg": [
{
"name": "CompanyY-192.168.2.0/24"
},
{
"name": "CompanyY-192.168.3.0/24"
}
]
}
I think that's what you're looking for.
- name: create address group
fortinet.fortios.fortios_firewall_addrgrp:
state: present
firewall_addrgrp:
name: "{{ item.name }}"
member: "{{ item.destination_addresses | join(',') }}"
loop: "{{ customers }}"
I guess that member
should be all addresses of the respective customer? These are in a list for the respective customer and you can join them to a string via join
function.
So the task set_fact
for grp_members
would not be necessary.
If this is not the result you need, you have to describe it exactly.
Here you can see the sample output of the joined addresses.
This task
- name: Iterate over customers.
debug:
msg: "{{ item.name }}: {{ item.destination_addresses | join(',') }}"
loop: "{{ customers }}"
produces this output
TASK [Iterate over customers.] ***************************************************************************************
ok: [localhost] => (item={'name': 'CompanyX', 'destination_addresses': ['192.168.0.0/24', '192.168.1.0/24']}) => {
"msg": "CompanyX: 192.168.0.0/24,192.168.1.0/24"
}
ok: [localhost] => (item={'name': 'CompanyY', 'destination_addresses': ['192.168.2.0/24', '192.168.3.0/24']}) => {
"msg": "CompanyY: 192.168.2.0/24,192.168.3.0/24"
}