Ansible:如何通过with_nested实现多组数据的组合遍历输出
问题:Ansible实现安全组、端口与CIDR范围的全组合输出
现有一段可正常运行的Ansible代码,能从安全组数据中提取group_id并拆分vpn_ports列表,通过subelements生成端口与安全组的对应输出。现在需要引入cidr_ranges变量,实现每个端口、安全组与每个CIDR范围的组合输出,但用with_nested的写法未成功,求正确实现方法。
现有代码
- hosts: localhost gather_facts: false vars: sec_group_info_output: security_groups: - group_id: sg-123456 tags: vpn_ports: "5432,22,53" - group_id: sg-987654 tags: vpn_ports: "22" - group_id: sg-18374923 tags: vpn_ports: "22,3389" tasks: - set_fact: vpn_groups: "{{ vpn_groups + [{'group_id': item.group_id, 'ports': item.tags.vpn_ports.split(',')}] }}" vars: vpn_groups: [] with_items: "{{ sec_group_info_output | json_query('security_groups') }}" - debug: msg: "open port {{ item.1 }} for group {{ item.0.group_id }}" loop: "{{ vpn_groups|subelements('ports') }}"
期望输出示例
"msg": "open port 5432 for group sg-123456 for cidr 10.1.0.0/16" "msg": "open port 5432 for group sg-123456 for cidr 10.2.0.0/16" ...(其余示例输出略)
尝试的错误写法
- debug: msg: "open port {{ item.1 }} for group {{ item.0.group_id }}" with_nested: - "{{ vpn_groups|subelements('ports') }}" - "{{ cidr_ranges }}"
正确实现方法
方案1:使用product过滤器组合多维度数据
先在vars中定义cidr_ranges,通过product过滤器将subelements生成的(安全组+端口)组合与CIDR范围做笛卡尔积,再调整变量引用路径即可:
- hosts: localhost gather_facts: false vars: sec_group_info_output: security_groups: - group_id: sg-123456 tags: vpn_ports: "5432,22,53" - group_id: sg-987654 tags: vpn_ports: "22" - group_id: sg-18374923 tags: vpn_ports: "22,3389" cidr_ranges: - "10.1.0.0/16" - "10.2.0.0/16" tasks: - set_fact: vpn_groups: "{{ vpn_groups + [{'group_id': item.group_id, 'ports': item.tags.vpn_ports.split(',')}] }}" vars: vpn_groups: [] with_items: "{{ sec_group_info_output | json_query('security_groups') }}" - debug: msg: "open port {{ item.0.1 }} for group {{ item.0.0.group_id }} for cidr {{ item.1 }}" loop: "{{ vpn_groups|subelements('ports') | product(cidr_ranges) }}"
方案2:提前构建包含CIDR的完整结构(可选)
如果需要更清晰的数据结构,可以先通过set_fact生成包含所有组合的列表,再输出:
- hosts: localhost gather_facts: false vars: sec_group_info_output: security_groups: - group_id: sg-123456 tags: vpn_ports: "5432,22,53" - group_id: sg-987654 tags: vpn_ports: "22" - group_id: sg-18374923 tags: vpn_ports: "22,3389" cidr_ranges: - "10.1.0.0/16" - "10.2.0.0/16" tasks: - set_fact: vpn_groups: "{{ vpn_groups + [{'group_id': item.group_id, 'ports': item.tags.vpn_ports.split(',')}] }}" vars: vpn_groups: [] with_items: "{{ sec_group_info_output | json_query('security_groups') }}" - set_fact: vpn_cidr_combinations: "{{ vpn_cidr_combinations + [{'group_id': item.0.group_id, 'port': item.1, 'cidr': item.1}] }}" vars: vpn_cidr_combinations: [] loop: "{{ vpn_groups|subelements('ports') | product(cidr_ranges) }}" - debug: msg: "open port {{ item.port }} for group {{ item.group_id }} for cidr {{ item.cidr }}" loop: "{{ vpn_cidr_combinations }}"
错误写法的问题说明
之前的with_nested写法中,item的结构是[[安全组对象, 端口], CIDR],原msg里的item.1实际指向CIDR而非端口,导致变量引用错误。通过product过滤器明确组合关系后,调整变量引用路径即可解决。
内容的提问来源于stack exchange,提问作者WarrenG
相关产品推荐
相关产品推荐

