Possibilité d'itérer un dictionnaire avec des listes

15

J'ai la variable suivante chargée via 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

Je souhaite alimenter ces informations à la shellcommande afin de définir les autorisations appropriées.

J'ai essayé quelques techniques à partir d'ici: http://docs.ansible.com/playbooks_loops.html mais je n'ai pas réussi à trouver une solution de travail.

Est-il possible d'itérer cette structure? Sinon, comment puis-je le restructurer afin de le faire fonctionner? Est-il possible de le faire sans enfreindre la règle DRY (par exemple, inclure le nom d'utilisateur dans chaque enregistrement)?

Slava Fomin II
la source

Réponses:

21

Tout d'abord, vous voudrez peut-être envisager d'utiliser le filemodule plutôt que shell. Il est moins sujet aux pannes et ostensiblement idempotent. Cependant, cela peut vous poser quelques problèmes avec le mélange des répertoires, des fichiers et des globes de fichiers. YMMV.

Quant au cœur de la question, je configurerais vos variables comme suit:

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

Le jeu ressemblerait alors à ceci:

- name: Change mod/own
  shell: chown {{ item.0.username }} {{ item.1.path }};chmod u+{{ item.1.permissions }} {{ item.1.path }
  with_subelements:
    - users
    - directories
Christopher Karel
la source
Bonne idée! Merci! Fonctionne comme un charme. BTW J'utilise le shellmodule parce que je dois faire une ACL récursive et qui n'est pas prise en charge par le aclmodule.
Slava Fomin II du
Logique solide. On dirait que shellc'est votre meilleur pari avec les ACL et la récursivité.
Christopher Karel
BTW est-il possible d'ignorer la clé de hachage manquante comme recursivedans mon exemple? Lorsque j'essaie d'y accéder et qu'il est manquant, Ansible arrêtera l'exécution du playbook et lèvera une exception. Je préfère ne pas ajouter recursive: falseà chaque enregistrement.
Slava Fomin II du
1
Je pense que la syntaxe par défaut devrait fonctionner: {{ some_variable | default() }}. Donc, dans ce cas: {{ item.1.recursive | default(false) }}
Christopher Karel
Comment la tâche changerait-elle si la clé "répertoires" n'était qu'une liste au lieu d'un dictionnaire également?
Chris F
7

Ceci est un bon exemple de sortie que vous pouvez essayer vous-même. Créez un nouveau livre de jeu appelé 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

Ensuite, exécutez le playbook comme ceci: ansible-playbook -i '172.16.222.131,' iteration_loop.yml

et la sortie devrait vous indiquer comment accéder aux éléments:

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   
Egidijus
la source
1

En supposant cela dict={a:[1,2,3],b:[1,2]}et ainsi de suite:

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

Maintenant flattened == [1,2,3,1,2]

Max Murphy
la source
0

Je reformaterai vos vars au format ci-dessous:

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

puis mon playbook comme ci-dessous:

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
user42826
la source