Ansible用列表迭代字典


15

我通过加载以下变量include_vars

access:
    username-foo:
      - path: /
        permissions: rwX
        recursive: true

    username-bar:
      - path: /
        permissions: rX

      - path: /css
        permissions: rwX
        recursive: true

      - path: /data
        permissions: rX

      - path: /data/reviews.yml
        permissions: rw

      - path: /js
        permissions: rX

      - path: /js/*.js
        permissions: rw

我想将此信息提供给shell命令以设置适当的权限。

我从这里尝试了一些技术:http : //docs.ansible.com/playbooks_loops.html, 但未能提出有效的解决方案。

是否可以迭代此结构?如果没有,我如何重新组织它以使其正常工作?是否可以在不违反DRY规则的情况下做到这一点(例如,在每个记录中包括用户名)?

Answers:


21

首先,您可能需要考虑使用file模块,而不是shell。它不太容易失败,而且表面上是幂等的。但是,这可能会给您混合目录,文件和文件glob带来一些问题。YMMV。

至于问题的核心,我将像这样设置您的变量:

users:
  - username: bar
    directories:
      - path: /data
        permissions: rX
      - path: /js
        permissions: rX
  - username: foo
    directories:
      - path: /
        permissions: rwX

该剧将如下所示:

- name: Change mod/own
  shell: chown {{ item.0.username }} {{ item.1.path }};chmod u+{{ item.1.permissions }} {{ item.1.path }
  with_subelements:
    - users
    - directories

好点子!谢谢!奇迹般有效。顺便说一句,我正在使用shell模块,因为我需要执行递归ACL,而acl模块不支持。
Slava Fomin II

坚实的逻辑。看起来shell最好是使用ACL和递归的方法。
Christopher Karel

顺便说一句,是否有可能像recursive我的示例那样忽略丢失的哈希键?当我尝试访问它且缺少它时,Ansible将停止执行剧本并引发异常。我宁愿不要添加recursive: false到每条记录中。
Slava Fomin II

1
我觉得默认的语法应该工作: {{ some_variable | default() }}。因此,在这种情况下: {{ item.1.recursive | default(false) }}
Christopher Karel 2014年

如果“目录”键也只是列表而不是字典,那么任务将如何改变?
克里斯F

7

这是一个很好的输出示例,您可以尝试一下。创建一个新的剧本,名为iteration_loop.yml

---

- name: Change mod/own
  hosts: all
  tasks:
  - name: show me the iterations
    debug: msg={{ item.0.username }} {{ item.1.path }} then {{ item.1.permissions }} {{ item.1.path }}
    with_subelements:
      - users
      - directories
  vars:
    users:
      - username: bar
        directories:
          - path: /data
            permissions: rX
          - path: /js
            permissions: rX
      - username: foo
        directories:
          - path: /
            permissions: rwX

然后像这样运行剧本: ansible-playbook -i '172.16.222.131,' iteration_loop.yml

并且输出应该给您如何访问项目:

PLAY [Change mod/own] ********************************************************* 

GATHERING FACTS *************************************************************** 
ok: [172.16.222.131]

TASK: [show me the iterations] ************************************************ 
ok: [172.16.222.131] => (item=({'username': 'bar'}, {'path': '/data', 'permissions': 'rX'})) => {
    "item": [
        {
            "username": "bar"
        }, 
        {
            "path": "/data", 
            "permissions": "rX"
        }
    ], 
    "msg": "bar"
}
ok: [172.16.222.131] => (item=({'username': 'bar'}, {'path': '/js', 'permissions': 'rX'})) => {
    "item": [
        {
            "username": "bar"
        }, 
        {
            "path": "/js", 
            "permissions": "rX"
        }
    ], 
    "msg": "bar"
}
ok: [172.16.222.131] => (item=({'username': 'foo'}, {'path': '/', 'permissions': 'rwX'})) => {
    "item": [
        {
            "username": "foo"
        }, 
        {
            "path": "/", 
            "permissions": "rwX"
        }
    ], 
    "msg": "foo"
}

PLAY RECAP ******************************************************************** 
172.16.222.131             : ok=2    changed=0    unreachable=0    failed=0   

1

假设如此dict={a:[1,2,3],b:[1,2]},依此类推:

- name: Flattened list
  set_fact:
    flattened: "{{ dict.values() | sum(start=[]) }}"

现在 flattened == [1,2,3,1,2]


0

我会将您的var重新格式化为以下格式:

access:
- username: foo
  directories:
    - path: /
      permissions: rwX
      recursive: true

- username: bar
  directories:
    - path: /
      permissions: rX
      recursive: false

    - path: /css
      permissions: rwX
      recursive: true

    - path: /data
      permissions: rX
      recursive: false

    - path: /data/reviews.yml
      permissions: rw
      recursive: false

    - path: /js
      permissions: rX
      recursive: false

    - path: /js/*.js
      permissions: rw
      recursive: false

然后我的剧本如下:

tasks:
- name: Iterate the vars inside var4 when recursive
  debug: msg="username is {{ item.0.username }} and path is {{ item.1.path }} permission is {{ item.1.permissions }} and recursive"
  when: item.1.recursive
  ignore_errors: true
  with_subelements:
    - "{{ access }}"
    - directories
- name: Iterate the vars inside var4 when no recursive
  debug: msg="username is {{ item.0.username }} and path is {{ item.1.path }} permission is {{ item.1.permissions }}"
  when: not item.1.recursive
  ignore_errors: true
  with_subelements:
    - "{{ access }}"
    - directories
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.