如何在Ansible中遍历字典的多个列表?

时间:2019-03-17 03:09:43

标签: ansible

我需要使用Ansible为存储库创建目录。路径应类似于:

./centos/6/repo1/x86_64/
./centos/7/repo1/x86_64/
./rhel/7/repo2/noarch/

因此,发行名称,主要发行版本,回购名称和基本目录的组合可以是任意的,并且不会创建任何其他目录。 看起来Ansible文件模块适合此工作,因此我创建了具有这种结构的变量列表:

repos:
    - name: repo1
        os_list:
          - centos
          - rhel
        major_distribution_list:
          - 6
          - 7
          - 8    
        archs:
          - noarch
          - x86_64

现在,我一直在努力寻找右循环控件。
with_items 仅允许我遍历键值对,而不是列出元素。
with_subelements 更加方便,但是它只允许我使用列表/子元素之一,而我需要两个或更多:

    - name: Create dirs
        file:
          dest: './centos/7/{{ item[0].name }}/{{ item[1] | default("noarch") }}'
          state: directory
        loop:  '{{ repos | subelements("archs") }}'

这是 with_subelements 所能得到的最好的结果。
with_nested 确实组合了任意多的元素,但是我找不到从变量列表中获取元素的方法。我能做的最好的事情是创建一整堆可能的目录,而不管实际需要哪个目录:

   - name: Create dirs
       file:
         dest: '/centos/{{ item[2] }}/{{ item[0].name }}/{{ item[1] | default("noarch") }}'
         state: directory
     with_nested:
       -  '{{ repos }}'
       -  [x86_64, noarch]
       -  [6, 7]

with_cartesian 似乎几乎相同。

所以问题是:

有没有办法使用具有多个列表的复杂变量并将它们全部组合在一个任务中?

2 个答案:

答案 0 :(得分:1)

一个选择是循环 include_tasks 。下面的游戏

vars:
  repos:
    - name: repo1
      os_list:
        - centos
        - rhel
      major_distribution_list:
        - 6
        - 7
        - 8    
      archs:
        - noarch
        - x86_64
tasks:
  - include_tasks: repo-paths.yml
    loop: "{{ repos }}"
    loop_control:
      loop_var: repo
...

# cat repo-paths.yml
- debug: msg="./{{ item.0 }}/{{ item.1 }}/{{ item.2 }}/{{ item.3 }}"
  with_nested:
    - "{{ repo.os_list }}"
    - "{{ repo.major_distribution_list }}"
    - "{{ repo.name }}"
    - "{{ repo.archs }}"

给予:

"msg": "./centos/6/repo1/noarch"
"msg": "./centos/6/repo1/x86_64"
"msg": "./centos/7/repo1/noarch"
"msg": "./centos/7/repo1/x86_64"
"msg": "./centos/8/repo1/noarch"
"msg": "./centos/8/repo1/x86_64"
"msg": "./rhel/6/repo1/noarch"
"msg": "./rhel/6/repo1/x86_64"
"msg": "./rhel/7/repo1/noarch"
"msg": "./rhel/7/repo1/x86_64"
"msg": "./rhel/8/repo1/noarch"
"msg": "./rhel/8/repo1/x86_64"

答案 1 :(得分:0)

您应该创建嵌套的dict文件,而不是进行映射。

例如。

操作系统:   centos:     --   瑞尔     -

通过这种方式,您可以控制每个操作系统和每个分布的循环。

另外,我的建议是使用明显事实中的一些值

操作系统名称,操作系统主要分布,体系结构等变量可以很容易地从ansible事实中获取,这将减少dict的创建,并且实现ansible模块将很容易