如何使用嵌套循环来循环 .yml 文件列表,然后循环每个文件中的列表

问题描述 投票:0回答:2

我有一个保存为变量的 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
ansible ansible-2.x ansible-awx
2个回答
1
投票

您的大多数示例都不起作用,因为

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   

...我想这就是你所追求的。


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
© www.soinside.com 2019 - 2024. All rights reserved.