Ansible:循环内循环

Ansible:循环内循环

在 ansible [core 2.13.3] 上,我的 var.yml 文件如下:

vlans:
  Servers:
    vlan_id: 10
    ip: 192.168.22.20
    mask: 255.255.255.0
    mode:
      tagged: 1/1,1/2
      untagged: 1/3
  Clients:
    vlan_id: 20
    mode:
      tagged: 1/1,1/3
  Printers:
    vlan_id: 30

目标是为 VLAN 中的每个元素(服务器、客户端、打印机……)和每种模式(标记、未标记、禁止……)启动一项任务。

我成功地在 VLAN 上迭代,但在 VLAN 和模式下却不行。我找不到成功嵌套循环的好方法。尝试了所有方法,如 subelement、with_subelements、loop_nested,但都没有成功。

  - name: Set member of vlan
    arubaoss_vlan:
      command: config_vlan_port
      config: "create"
      vlan_id: "{{ item.value.vlan_id }}"
      port_id: "{{ item.value.port | default('') }}"
      port_mode: "{{ item.value.mode | default('POM_UNTAGGED') | regex_replace('^tagged$', 'POM_TAGGED_STATIC') | regex_replace('^untagged$', 'POM_UNTAGGED') | regex_replace('^forbid$', 'POM_FORBIDDEN') }}"
      api_version: "{{ ansible_api_version }}"
      use_ssl: "{{ ansible_use_ssl }}"
      port: "{{ ansible_port }}"
      host: "{{ ansible_host }}"
      username: "{{ ansible_user }}"
      password: "{{ ansible_password }}"
    loop: "{{ lookup('dict', vlans) }}"
    when: "'port' in dict(item)"
    tags:
      - vlans
      - vlans_mode

如何在 Ansible 中创建嵌套循环?

  - name: Debug2
    debug:
      msg: "Name: {{ item.key }} - mode: {{ item.value.mode }}"
    loop: "{{ lookup('dict', vlans) }}"
    when: "'mode' in dict(item.value)"
    tags:
      - debug

调试2返回:

确定:[sw39stack01.group.corp] =>(item = {'key':'服务器','值':{'vlan_id':10,'ip':'192.168.22.20','掩码':'255.255.255.0','模式':{'tagged':'1 / 1,1/2','untagged':'1/3'}}})=> {“ msg”:“名称:服务器 - 模式:{'tagged':'1/1,1/2','untagged':'1/3'}”} 确定:[sw39stack01.group.corp] =>(item = {'key':'客户端','值':{'vlan_id':20,'模式':{'tagged':'1/1,1/3'}}})=> { “msg”:“名称:客户端 - 模式:{'tagged':'1 / 1,1 / 3'}”}跳过:[sw39stack01.group.corp] =>(item = {'key':'打印机','value':{'vlan_id':30}})=> {“ansible_loop_var”:“item”,“item”:{“key”:“打印机”,“value”:{“vlan_id”:30}} }

此致,

答案1

转换词典模式列表

  modes: |
    {% for k,v in vlans.items() %}
    {{ k }}:
      mode: {{ v.mode|d({})|dict2items }}
    {% endfor %}
  vlans2: "{{ vlans|combine(modes|from_yaml, recursive=true) }}"

给出

  vlans2:
    Clients:
      mode:
      - key: tagged
        value: 1/1,1/3
      vlan_id: 20
    Printers:
      mode: []
      vlan_id: 30
    Servers:
      ip: 192.168.22.20
      mask: 255.255.255.0
      mode:
      - key: tagged
        value: 1/1,1/2
      - key: untagged
        value: 1/3
      vlan_id: 10

转换字典VLAN2到列表中并迭代子元素 值模式

    - debug:
        msg: "{{ item.0.key }} {{ item.1.key }} {{ item.1.value }}"
      loop: "{{ vlans2|dict2items|subelements('value.mode') }}"

给出(节选)

  msg: Servers tagged 1/1,1/2
  msg: Servers untagged 1/3
  msg: Clients tagged 1/1,1/3

完整剧本的示例

- hosts: localhost

  vars:

    vlans:
      Servers:
        vlan_id: 10
        ip: 192.168.22.20
        mask: 255.255.255.0
        mode:
          tagged: 1/1,1/2
          untagged: 1/3
      Clients:
        vlan_id: 20
        mode:
          tagged: 1/1,1/3
      Printers:
        vlan_id: 30

    modes: |
      {% for k,v in vlans.items() %}
      {{ k }}:
        mode: {{ v.mode|d({})|dict2items }}
      {% endfor %}
    vlans2: "{{ vlans|combine(modes|from_yaml, recursive=true) }}"

  tasks:

    - debug:
        var: modes|from_yaml
    - debug:
        var: vlans2
    - debug:
        msg: "{{ item.0.key }} {{ item.1.key }} {{ item.1.value }}"
      loop: "{{ vlans2|dict2items|subelements('value.mode') }}"

答案2

库存文件编辑如下:

vlans:
  - name: Servers
    vlan_id: 10
    ip: 192.168.22.20
    mask: 255.255.255.0
    mode:
      - tagged: 1/1,1/2
      - untagged: 1/3
  - name: Clients
    vlan_id: 20
    mode:
      - tagged: 1/1,1/3
  - name: Printers
    vlan_id: 30

并使用查询:

  - name: Debug1
    ansible.builtin.debug: var=item
    loop: "{{ query('subelements', vlans, 'mode', {'skip_missing': True}) }}"
    tags:
      - debug

输出工作符合预期:

ok: [sw] => (item=[{'name': 'Servers', 'vlan_id': 10, 'ip': '192.168.22.20', 'mask': '255.255.255.0'}, {'tagged': '1/1,1/2'}]) => {
    "ansible_loop_var": "item",
    "item": [
        {
            "ip": "192.168.22.20",
            "mask": "255.255.255.0",
            "name": "Servers",
            "vlan_id": 10
        },
        {
            "tagged": "1/1,1/2"
        }
    ]
}
ok: [sw] => (item=[{'name': 'Servers', 'vlan_id': 10, 'ip': '192.168.22.20', 'mask': '255.255.255.0'}, {'untagged': '1/3'}]) => {
    "ansible_loop_var": "item",
    "item": [
        {
            "ip": "192.168.22.20",
            "mask": "255.255.255.0",
            "name": "Servers",
            "vlan_id": 10
        },
        {
            "untagged": "1/3"
        }
    ]
}

相关内容