从变量集构建的 Ansible 循环

Ansible loop built from variable sets

作为一名网络工程师,我对 Ansible 还很陌生,但发现它伤了我的脑筋。我在一些 Ansible 剧本中使用了基本循环。现在我正在尝试一些更复杂的东西,我确信我遗漏了一些东西,因为感觉它应该很简单。

我想在剧本中使用这些变量:

  vars:
    smb_tcp_ports:
      - '139'
      - '445'
    smb_udp_ports:
      - '137'
      - '138'
    smb_ips:
      - '172.16.13.130'
      - '172.16.13.0/26'
      - '200X:8X0:fX4a:X053::/64'
      - '200X:8X0:fX4a:X050::130' 

并循环遍历它们,因此我构建了一个像这样的新变量:

  vars: 
    smb_allowed_ips_tcp: 
     - { ip: "172.16.13.130", port: ['139','445'] }
     - { ip: "172.16.13.0/26", port: ['139','445'] }
     - { ip: "X001:8X0:fX4a:X053::/64", port: ['139','445'] }
     - { ip: "X001:8X0:fX4a:X050::130", port: ['139','445'] }
    smb_allowed_ips_udp:
     - { ip: "172.16.13.130", port: ['137','138'] }
     - { ip: "172.16.13.0/26", port: ['137','138'] }
     - { ip: "200X:8X0:fX4a:X053::/64", port: ['137','138'] }
     - { ip: "200X:8X0:fX4a:X050::130", port: ['137','138'] }

^^^ 我想要生成的上面的位是我正在努力的位 ^^^ 然后我可以将它发送到这里:

- name: Allow SMB TCP
  ufw:
    rule: allow
    src: '{{ item.0.ip }}'
    port: '{{ item.1 }}'
    proto: tcp
  with_subelements:
    - "{{ smb_allowed_ips_tcp }}"
    - port
  when: "'smbserver' in group_names"

- name: Allow SMB UDP
  ufw:
    rule: allow
    src: '{{ item.0.ip }}'
    port: '{{ item.1 }}'
    proto: udp
  with_subelements:
    - "{{ smb_allowed_ips_udp }}"
    - port
  when: "'smbserver' in group_names"

这个问题以前在这里有很多词。我删除了它。谢谢拉斯克斯。我希望这更清楚?

我尝试了 set_facts,但是在我看到的例子中有很多我不理解的东西,比如添加 |符号和书写列表、产品等,我总是以失败告终。它似乎也没有作为数组添加,它覆盖了。

此处回答:使用 https://ansibledaily.com/process-complex-variables-with-set_fact-and-with_items/

---

- hosts: myhosts
  gather_facts: true
  become: true
  vars:
    smb_tcp_ports:
      - '139'
      - '445'
    smb_udp_ports:
      - '137'
      - '138'
    smb_ips:
      - '172.16.13.130'
      - '172.16.13.0/26'
      - '200X:8X0:fX4a:X053::/64'
      - '200X:8X0:fX4a:X050::130'
    smb_ips_tcp: {}

  tasks:
  - name: Populate IPs in dict
    set_fact:
      smb_ips_tcp: "{{ smb_ips_tcp | combine({'ip': item}) }}"
    with_items:
      - "{{ smb_ips }}"
    register: smbout

  - name: Populate ports in dict
    set_fact:
      smb_ips_tcp: "{{ item | combine({'port': smb_tcp_ports}) }}"
    with_items:
      - "{{ smbout.results | map(attribute='ansible_facts.smb_ips_tcp') | list  }}"
    register: smbout

  - name: smbout results
    set_fact:
      smb_ips_tcp: "{{ smbout.results | map(attribute='ansible_facts.smb_ips_tcp') | list   }}"

  - name: Allow SMB TCP
    ufw:
      rule: allow
      src: '{{ item.0.ip }}'
      port: '{{ item.1 }}'
      proto: tcp
    with_subelements:
      - "{{ smb_ips_tcp }}"
      - port

我想我错过了寄存器位。因此,当我尝试寄存器事实位之前,它一直给我留下一个键值对。这是没用的。虽然寄存器允许我保留所有键值并再次使用它们。

现在不确定这是否是一个重复的问题。

听起来您可能已经解决了您的问题,但我认为您可能对替代实施感兴趣。我可能会使用 product 过滤器解决这个问题,它产生两个列表的笛卡尔积。例如,要生成 smb_allowed_ips_tcp,我会写:

    - name: create smb_allowed_ips_tcp
      set_fact:
        smb_allowed_ips_tcp: "{{ smb_allowed_ips_tcp + [{'ip': item.0, 'port': item.1}] }}"
      loop: "{{ smb_ips|product(smb_tcp_ports)|list }}"
      vars:
        smb_allowed_ips_tcp: []

这会生成如下所示的数据结构:

TASK [debug] ******************************************************************************************
ok: [localhost] => {
    "smb_allowed_ips_tcp": [
        {
            "ip": "172.16.13.130",
            "port": "139"
        },
        {
            "ip": "172.16.13.130",
            "port": "445"
        },
        {
            "ip": "172.16.13.0/26",
            "port": "139"
        },
        {
            "ip": "172.16.13.0/26",
            "port": "445"
        },
        {
            "ip": "200X:8X0:fX4a:X053::/64",
            "port": "139"
        },
        {
            "ip": "200X:8X0:fX4a:X053::/64",
            "port": "445"
        },
        {
            "ip": "200X:8X0:fX4a:X050::130",
            "port": "139"
        },
        {
            "ip": "200X:8X0:fX4a:X050::130",
            "port": "445"
        }
    ]
}

我们可以像这样将其提供给 ufw 模块:

    - name: Allow SMB TCP
      ufw:
        rule: allow
        src: '{{ item.ip }}'
        port: '{{ item.port }}'
        proto: tcp
      loop: "{{ smb_allowed_ips_tcp }}"

此解决方案所需的任务较少,我认为逻辑更容易理解。