Ansible: Schleife innerhalb einer Schleife

Ansible: Schleife innerhalb einer Schleife

Unter Ansible [Core 2.13.3] sieht meine var.yml-Datei wie folgt aus:

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

Das Ziel besteht darin, für jedes Element in VLANs (Server, Clients, Drucker usw.) und für jeden Modus (markiert, ungetaggt, verboten usw.) eine Aufgabe zu starten.

Ich iteriere erfolgreich über VLANs, aber nicht über VLANs und Modus. Ich kann keinen guten Weg finden, um eine verschachtelte Schleife erfolgreich auszuführen. Habe alles wie Subelement, with_subelements, loop_nested ohne Erfolg ausprobiert.

  - 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

Wie kann ich in Ansible eine verschachtelte Schleife erstellen?

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

Debug 2 gibt zurück:

ok: [sw39stack01.group.corp] => (item={'key': 'Servers', 'value': {'vlan_id': 10, 'ip': '192.168.22.20', 'mask': '255.255.255.0', 'mode': {'tagged': '1/1,1/2', 'untagged': '1/3'}}}) => { "msg": "Name: Server - Modus: {'tagged': '1/1,1/2', 'untagged': '1/3'}" } ok: [sw39stack01.group.corp] => (item={'key': 'Clients', 'value': {'vlan_id': 20, 'mode': {'tagged': '1/1,1/3'}}}) => { "msg": "Name: Clients - Modus: {'tagged': '1/1,1/3'}" } überspringen: [sw39stack01.group.corp] => (item={'key': 'Drucker', 'value': {'vlan_id': 30}}) => { "ansible_loop_var": "item", "item": { "key": "Drucker", "value": { "vlan_id": 30 } } }

Beste grüße,

Antwort1

Konvertieren der WörterbücherModuszu Listen

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

gibt

  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

Konvertieren des Wörterbuchsvlans2zu einer Liste und iteriere mitUnterelemente Wert.Modus

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

gibt (gekürzt)

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

Beispiel eines vollständigen Playbooks

- 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') }}"

Antwort2

Inventardateien werden wie folgt bearbeitet:

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

Und die Abfrage wird verwendet:

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

Die Ausgabe funktioniert wie erwartet:

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"
        }
    ]
}

verwandte Informationen