Ansible 中带有用户和文件夹的嵌套循环

Nested loop with user and folder in Ansible

我有以下任务:

- name: Create required folders.
  become: true
  ansible.builtin.file:
    owner: "{{ item.key }}"
    group: ftp
    mode: '0755'  
    path: '/data/{{ item.key }}/in'
    state: directory
  loop: "{{ query('dict', ftp) | list }}"
  when: "'state' not in item.value or item.value.state == 'present'"

以及以下具有不同用户的主机变量:

ftp:
  test:
     ssh_public_key: "XXXX"
     password: "XXX" 
     home: /data/test
  test2:
     ssh_public_key: "XXXX"
     password: "XXX" 
     home: /data/test2

我想要的是为每个用户创建两个目录:

path: '/data/{{ user }}/in' # item.key, in the code above
path: '/data/{{ user }}/out' # item.key, in the code above

但我已经需要迭代用户本身的循环:

loop: "{{ query('dict', ftp) | list }}"

我该如何处理这个问题,例如,使用嵌套循环?

使用 product filter 生成 user/folder 的所有可能组合。

loop: "{{ ftp.keys() | product(['in', 'out']) }}"

然后,分别

  • item.0 包含用户字典键
  • item.1 包含文件夹

目前还不完全清楚你的条件 when 实际上做了什么,为了适应它,但我猜你确实有一个 absentpresent 状态使用字典。

因此,最终的任务应该类似于

- name: Create required folders
  ansible.builtin.file:
    owner: "{{ item.0 }}"
    group: ftp
    mode: '0755'
    path: "/data/{{ item.0 }}/{{ item.1 }}"
    state: directory
  loop: "{{ ftp.keys() | product(['in', 'out']) }}"
  loop_control:
    label: "/data/{{ item.0 }}/{{ item.1 }}"
  when: "ftp[item.0].state | default('absent') == 'present'"
  become: true 

给定上述任务,当 运行 这些数据时:

ftp:
  test:
    state: present
  test1:
  test2:
    state: present

它将产生:

TASK [Create required folders] ***************************************
ok: [localhost] => (item=/data/test/in)
ok: [localhost] => (item=/data/test/out)
skipping: [localhost] => (item=/data/test1/in) 
skipping: [localhost] => (item=/data/test1/out) 
ok: [localhost] => (item=/data/test2/in)
ok: [localhost] => (item=/data/test2/out)

先测试一下,例如

    - debug:
        msg: "Create /data/{{ item.0.key }}/{{ item.1 }}"
      with_nested:
        - "{{ ftp|dict2items }}"
        - [in, out]
      when: item.0.value.state|d('present') == 'present'

给出(删节)

  msg: Create /data/test/in
  msg: Create /data/test/out
  msg: Create /data/test2/in
  msg: Create /data/test2/out

然后尝试创建字典

    - file:
        owner: "{{ item.0.key }}"
        group: ftp
        mode: '0755'  
        path: "/data/{{ item.0.key }}/{{ item.1 }}"
        state: directory
      with_nested:
        - "{{ ftp|dict2items }}"
        - [in, out]
      when: item.0.value.state|d('present') == 'present'

(未测试)