Ansible iteriert ein Wörterbuch mit Listen

15

Ich habe die folgende Variable geladen über 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

Ich möchte diese Informationen an den shellBefehl weitergeben, um die entsprechenden Berechtigungen festzulegen.

Ich habe hier einige Techniken ausprobiert: http://docs.ansible.com/playbooks_loops.html, konnte aber keine funktionierende Lösung finden.

Ist es möglich, diese Struktur zu iterieren? Wenn nicht, wie strukturiere ich es um, damit es funktioniert? Ist es möglich, dies zu tun, ohne die DRY-Regel zu brechen (z. B. Benutzernamen in jeden Datensatz aufnehmen)?

Slava Fomin II
quelle

Antworten:

21

Zuallererst möchten Sie vielleicht lieber das fileModul verwenden als shell. Es ist weniger fehleranfällig und angeblich idempotent. Dies kann jedoch zu Problemen beim Mischen von Verzeichnissen, Dateien und Datei-Globs führen. YMMV.

Was den Kern der Frage betrifft, würde ich Ihre Variablen folgendermaßen einrichten:

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

Das Stück würde dann so aussehen:

- 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
quelle
Großartige Idee! Vielen Dank! Klappt wunderbar. Übrigens verwende ich das shellModul, weil ich eine rekursive ACL ausführen muss, die vom aclModul nicht unterstützt wird .
Slava Fomin II
Solide Logik. Sieht aus wie shellist Ihre beste Wette mit ACLs und Rekursion.
Christopher Karel
BTW ist es möglich, fehlende Hash-Schlüssel wie recursivein meinem Beispiel zu ignorieren ? Wenn ich versuche, darauf zuzugreifen, und es fehlt, stoppt Ansible die Ausführung des Playbooks und löst eine Ausnahme aus. Ich ziehe es vor, nicht recursive: falsezu jedem Datensatz hinzuzufügen .
Slava Fomin II
1
Ich denke , dass die Standard - Syntax sollte funktionieren: {{ some_variable | default() }}. Also, in diesem Fall: {{ item.1.recursive | default(false) }}
Christopher Karel
Wie würde sich die Aufgabe ändern, wenn der "Verzeichnis" -Schlüssel auch nur eine Liste anstelle eines Wörterbuchs ist?
Chris F
7

Dies ist ein gutes Ausgabebeispiel, das Sie selbst ausprobieren können. Erstelle ein neues Spielbuch mit dem Namen 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

Dann starte das Playbook wie folgt: ansible-playbook -i '172.16.222.131,' iteration_loop.yml

und die Ausgabe sollte Ihnen anzeigen, wie auf die Elemente zugegriffen wird:

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
quelle
1

Vorausgesetzt, dass dict={a:[1,2,3],b:[1,2]}und so weiter:

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

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

Max Murphy
quelle
0

Ich werde Ihre vars auf das folgende Format formatieren:

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

und dann mein playbook wie folgt:

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
quelle