【问题标题】:Ansible loop built from variable sets从变量集构建的 Ansible 循环
【发布时间】:2020-05-12 19:51:15
【问题描述】:

作为一名网络工程师,我对 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

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

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

【问题讨论】:

  • 我不清楚你想要完成什么。根据docs.ansible.com/ansible/latest/modules/ufw_module.html port 选项只需要一个字符串。也许您可以详细说明您的预期规则输出是什么?
  • 我不是在谈论模块的使用。我说的是循环函数与变量的使用,我有更多的动态控制来节省一遍又一遍的重复。我将编辑以解释更多。谢谢。
  • 我在“好的,这就是我想看到的”之后迷路了。到目前为止,我认为这个问题很清楚,但是在阅读了它之后,我并不清楚到底是什么问题或者你想要完成什么。我希望看到你在这个问题上提供更多的焦点(并且可能更少的措辞)。
  • 谢谢@larsks。我想了更多。也许上面更重要?

标签: ansible nested-loops


【解决方案1】:

听起来您可能已经解决了您的问题,但我认为您可能对替代实现感兴趣。我可能会使用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 }}"

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

【讨论】:

  • 是的,看起来好多了。泰。我想当我在早期阅读中看到“笛卡尔”这个词时,我的大脑一片空白。谷歌搜索显示我应该早点用谷歌搜索它。 :D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
  • 1970-01-01
  • 1970-01-01
  • 2022-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多