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