
En ansible [core 2.13.3] mi archivo var.yml es así:
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
El objetivo es lanzar una tarea para cada elemento de las vlans (Servidores, Clientes, Impresoras...) y para cada modo (etiquetado, sin etiquetar, prohibido...).
Iteré con éxito en VLAN pero no en VLAN ni en modo. No puedo encontrar la buena manera de lograr el éxito en el bucle anidado. Pruebe todo como subelement, with_subelements, loop_nested sin éxito.
- 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
¿Cómo puedo hacer un bucle anidado en Ansible?
- name: Debug2
debug:
msg: "Name: {{ item.key }} - mode: {{ item.value.mode }}"
loop: "{{ lookup('dict', vlans) }}"
when: "'mode' in dict(item.value)"
tags:
- debug
Depuración 2 retorno:
ok: [sw39stack01.group.corp] => (item={'key': 'Servidores', 'valor': {'vlan_id': 10, 'ip': '192.168.22.20', 'máscara': '255.255 .255.0', 'modo': {'tagged': '1/1,1/2', 'untagged': '1/3'}}}) => { "msg": "Nombre: Servidores - modo: {'tagged': '1/1,1/2', 'sin etiquetar': '1/3'}" } ok: [sw39stack01.group.corp] => (item={'key': 'Clientes', 'valor': {'vlan_id': 20, 'modo': {'tagged': '1/1,1/3'}}}) => { "msg": "Nombre: Clientes - modo: {'tagged ': '1/1,1/3'}" } saltando: [sw39stack01.group.corp] => (item={'key': 'Impresoras', 'valor': {'vlan_id': 30}}) => { "ansible_loop_var": "item", "item": { "key": "Impresoras", "value": { "vlan_id": 30 } } }
Atentamente,
Respuesta1
Convertir los diccionariosmodoa listas
modes: |
{% for k,v in vlans.items() %}
{{ k }}:
mode: {{ v.mode|d({})|dict2items }}
{% endfor %}
vlans2: "{{ vlans|combine(modes|from_yaml, recursive=true) }}"
da
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
Convertir el diccionariovlans2a una lista e iterar consubelementos valor.modo
- debug:
msg: "{{ item.0.key }} {{ item.1.key }} {{ item.1.value }}"
loop: "{{ vlans2|dict2items|subelements('value.mode') }}"
da (abreviado)
msg: Servers tagged 1/1,1/2
msg: Servers untagged 1/3
msg: Clients tagged 1/1,1/3
Ejemplo de un libro de jugadas completo
- 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') }}"
Respuesta2
El archivo de inventario se edita así:
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
Y se utiliza la consulta:
- name: Debug1
ansible.builtin.debug: var=item
loop: "{{ query('subelements', vlans, 'mode', {'skip_missing': True}) }}"
tags:
- debug
La salida funciona como se esperaba:
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"
}
]
}