You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:50:23