如何在Ansible中为FortiGate按客户分组地址对象?
解决Fortinet Ansible模块中客户地址组的成员匹配问题
现有变量
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
已完成的地址对象创建任务
已成功为每个destination_addresses中的地址创建独立的地址对象,对应的Ansible任务如下:
- 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') }}"
该任务生成的地址对象包括:
CompanyX-192.168.0.0/24CompanyX-192.168.1.0/24CompanyY-192.168.2.0/24CompanyY-192.168.3.0/24
地址组创建的问题
当前创建地址组的任务会导致每个客户的地址组包含所有地址对象,而非仅对应客户的地址:
- 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 }}"
当前输出
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" } ]
期望输出
每个客户的地址组仅包含自身对应的地址对象:
CompanyX对应的成员:
"grp_members": [ { "name": "CompanyX-192.168.0.0/24" }, { "name": "CompanyX-192.168.1.0/24" } ]
CompanyY对应的成员:
"grp_members": [ { "name": "CompanyY-192.168.2.0/24" }, { "name": "CompanyY-192.168.3.0/24" } ]
注:fortinet.fortios.fortios_firewall_addrgrp模块要求成员采用上述字典格式
解决方案
不需要提前合并所有成员到一个变量,而是在循环每个客户时,动态生成该客户对应的成员列表。以下是两种可行的实现方式:
方式一:直接在任务中生成成员列表
- name: create address group for each customer fortinet.fortios.fortios_firewall_addrgrp: state: present firewall_addrgrp: name: "{{ item.name }}" member: "{{ item.destination_addresses | map('regex_replace', '^(.*)$', '{\"name\": \"' ~ item.name ~ '-\\1\"}') | map('from_json') | list }}" loop: "{{ customers }}"
方式二:先预先生成每个客户的成员分组
- name: prepare address group members per customer set_fact: customer_groups: "{{ customer_groups | default([]) + [ { 'name': item.name, 'members': item.destination_addresses | map('regex_replace', '^(.*)$', '{\"name\": \"' ~ item.name ~ '-\\1\"}') | map('from_json') | list } ] }}" loop: "{{ customers }}" - name: create address group using prepared members fortinet.fortios.fortios_firewall_addrgrp: state: present firewall_addrgrp: name: "{{ item.name }}" member: "{{ item.members }}" loop: "{{ customer_groups }}"
两种方式的核心逻辑都是为每个客户单独处理其destination_addresses,生成仅属于该客户的成员字典列表,避免将所有成员合并到同一个变量中。
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

