我有一个保存为变量的 yaml 文件列表,每个文件中都有一个名为“virtual_servers”的列表,我需要循环并执行 Ansible 模块。
列表示例:
listOfFiles: [/config/gtm/file1.yml, /config/gtm/file2.yml, /config/gtm/file3.yml, /config/gtm/file4.yml]
每个文件的示例:
sever_datacenter: East
server_product: generic-host
server_devices:
- name: aaptestserver1d
address: 10.4.5.6
server_health_monitors:
- /Common/prg_tcp
virtual_servers:
- virtual_server_name: aaptestserver1d_443
virtual_server_state: enabled
virtual_server_port: 443
virtual_server_ip_address: 10.4.5.6
- virtual_server_name: aaptestserver2d_443
virtual_server_state: enabled
virtual_server_port: 443
virtual_server_ip_address: 10.4.5.7
我尝试过使用循环、with_items、with_nested 和 with_sublelements,这似乎是最有希望的,但当我尝试时,我收到一条错误消息,指出“子元素查找需要字典”。
- debug:
msg: "{{ item.1 }}"
with_subelements:
- "{{ listOfFiles }}"
- virtual_servers
显然,使用 with_nested 中的第二项来引用第一项是行不通的。
- debug:
msg: "{{ item.1 }}"
with_nested:
- "{{ listOfFiles }}"
- item.0.virtual_servers
在此示例中,我期望它打印出“virtual_servers”列表中的每个项目:
- virtual_server_name: aaptestserver1d_443
virtual_server_state: enabled
virtual_server_port: 443
virtual_server_ip_address: 10.4.5.6
- virtual_server_name: aaptestserver2d_443
virtual_server_state: enabled
virtual_server_port: 443
virtual_server_ip_address: 10.4.5.7
您的大多数示例都不起作用,因为
listOfFiles
只是文件名列表。它不包含 virtual_servers
键,也不包含任何列表成员。这意味着像...这样的表达
with_subelements:
- "{{ listOfFiles }}"
- virtual_servers
...永远不会起作用。
一种选择是构建所有数据文件的内容列表。像这样的东西:
- set_fact:
configs: >-
{{ configs + [lookup("file", item)|from_yaml] }}
loop: "{{ listOfFiles }}"
vars:
configs: []
这将创建一个列表
configs
,其中的项目是listOfFiles
中列出的文件的内容。在剧本中使用它可能看起来像这样:
- hosts: localhost
gather_facts: false
vars_files:
- listoffiles.yaml
tasks:
- set_fact:
configs: >-
{{ configs + [lookup("file", item)|from_yaml] }}
loop: "{{ listOfFiles }}"
vars:
configs: []
- debug:
msg: "{{ item.1 }}"
loop: "{{ configs|subelements('virtual_servers') }}"
loop_control:
label: "{{ item.0.server_datacenter }}/{{ item.1.virtual_server_name }}"
假设
listoffiles.yaml
包含:
listOfFiles:
- config/file1.yaml
- config/file2.yaml
并且
file1.yaml
包含:
server_datacenter: West
server_product: generic-host
server_devices:
- name: aaptestserver1d
address: 10.6.5.4
server_health_monitors:
- /Common/prg_tcp
virtual_servers:
- virtual_server_name: aaptestserver3d_443
virtual_server_state: enabled
virtual_server_port: 443
virtual_server_ip_address: 10.6.5.4
- virtual_server_name: aaptestserver4d_443
virtual_server_state: enabled
virtual_server_port: 443
virtual_server_ip_address: 10.7.5.4
并且
file2.yaml
包含:
server_datacenter: East
server_product: generic-host
server_devices:
- name: aaptestserver1d
address: 10.4.5.6
server_health_monitors:
- /Common/prg_tcp
virtual_servers:
- virtual_server_name: aaptestserver1d_443
virtual_server_state: enabled
virtual_server_port: 443
virtual_server_ip_address: 10.4.5.6
- virtual_server_name: aaptestserver2d_443
virtual_server_state: enabled
virtual_server_port: 443
virtual_server_ip_address: 10.4.5.7
然后运行上面的剧本会产生:
PLAY [localhost] ***************************************************************
TASK [set_fact] ****************************************************************
ok: [localhost] => (item=config/file1.yaml)
ok: [localhost] => (item=config/file2.yaml)
TASK [debug] *******************************************************************
ok: [localhost] => (item=West/aaptestserver3d_443) => {
"msg": {
"virtual_server_ip_address": "10.6.5.4",
"virtual_server_name": "aaptestserver3d_443",
"virtual_server_port": 443,
"virtual_server_state": "enabled"
}
}
ok: [localhost] => (item=West/aaptestserver4d_443) => {
"msg": {
"virtual_server_ip_address": "10.7.5.4",
"virtual_server_name": "aaptestserver4d_443",
"virtual_server_port": 443,
"virtual_server_state": "enabled"
}
}
ok: [localhost] => (item=East/aaptestserver1d_443) => {
"msg": {
"virtual_server_ip_address": "10.4.5.6",
"virtual_server_name": "aaptestserver1d_443",
"virtual_server_port": 443,
"virtual_server_state": "enabled"
}
}
ok: [localhost] => (item=East/aaptestserver2d_443) => {
"msg": {
"virtual_server_ip_address": "10.4.5.7",
"virtual_server_name": "aaptestserver2d_443",
"virtual_server_port": 443,
"virtual_server_state": "enabled"
}
}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
...我想这就是你所追求的。
创建文件内容列表
listOfData: |
{% filter from_yaml %}
{% for f in listOfFiles %}
- {{ lookup('file', f)|indent(2) }}
{% endfor %}
{% endfilter %}
现在,您可以迭代listOfData
- debug:
msg: "{{ item.1 }}"
with_subelements:
- "{{ listOfData }}"
- virtual_servers
用于测试的完整剧本示例
shell> cat pb.yml
- hosts: all
vars:
listOfFiles: [file1.yml, file2.yml, file3.yml]
listOfData: |
{% filter from_yaml %}
{% for f in listOfFiles %}
- {{ lookup('file', f)|indent(2) }}
{% endfor %}
{% endfilter %}
tasks:
- debug:
msg: "{{ item.1 }}"
with_subelements:
- "{{ listOfData }}"
- virtual_servers
鉴于简化数据
shell> cat files/file1.yml
sever_datacenter: East
virtual_servers:
- virtual_server_ip_address: 10.4.5.1
virtual_server_state: enabled
- virtual_server_ip_address: 10.4.5.2
virtual_server_state: enabled
shell> cat files/file2.yml
sever_datacenter: East
virtual_servers:
- virtual_server_ip_address: 10.4.5.3
virtual_server_state: enabled
- virtual_server_ip_address: 10.4.5.4
virtual_server_state: enabled
shell> cat files/file3.yml
sever_datacenter: East
virtual_servers:
- virtual_server_ip_address: 10.4.5.5
virtual_server_state: enabled
- virtual_server_ip_address: 10.4.5.6
virtual_server_state: enabled
给出(删节)
shell> ansible-playbook pb.yml
...
msg:
virtual_server_ip_address: 10.4.5.1
virtual_server_state: enabled
msg:
virtual_server_ip_address: 10.4.5.2
virtual_server_state: enabled
msg:
virtual_server_ip_address: 10.4.5.3
virtual_server_state: enabled
msg:
virtual_server_ip_address: 10.4.5.4
virtual_server_state: enabled
msg:
virtual_server_ip_address: 10.4.5.5
virtual_server_state: enabled
msg:
virtual_server_ip_address: 10.4.5.6
virtual_server_state: enabled