Lakukan iterasi kamus dengan daftar

15

Saya memiliki variabel berikut yang dimuat melalui 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

Saya ingin memasukkan informasi ini ke shellperintah untuk mengatur izin yang sesuai.

Saya sudah mencoba beberapa teknik dari sini: http://docs.ansible.com/playbooks_loops.html tetapi gagal menemukan solusi yang berfungsi.

Apakah mungkin untuk mengulangi struktur ini? Jika tidak, bagaimana cara menyusun ulang untuk membuatnya berfungsi? Apakah mungkin untuk melakukan ini tanpa melanggar aturan KERING (misalnya, memasukkan nama pengguna ke dalam setiap catatan)?

Slava Fomin II
sumber

Jawaban:

21

Pertama, Anda mungkin ingin mempertimbangkan untuk menggunakan filemodul , bukan shell. Ini kurang rawan kegagalan, dan seolah-olah idempoten. Namun, itu mungkin memberi Anda beberapa masalah dengan pencampuran direktori, file, dan file gumpalan. YMMV.

Adapun inti dari pertanyaan, saya akan mengatur variabel Anda seperti:

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

Drama itu akan terlihat seperti ini:

- 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
sumber
Ide yang hebat! Terima kasih! Bekerja seperti pesona. BTW Saya menggunakan shellmodul karena saya perlu melakukan ACL rekursif dan itu tidak didukung oleh aclmodul.
Slava Fomin II
Logika yang solid. Sepertinya shellini taruhan terbaik Anda dengan ACL dan rekursi.
Christopher Karel
BTW apakah mungkin untuk mengabaikan kunci hash yang hilang seperti recursivedalam contoh saya? Ketika saya mencoba mengaksesnya dan itu hilang, Ansible akan menghentikan eksekusi playbook dan melemparkan pengecualian. Saya lebih suka tidak menambahkan recursive: falseke setiap record.
Slava Fomin II
1
Saya pikir sintaks default harus bekerja: {{ some_variable | default() }}. Jadi, dalam hal ini: {{ item.1.recursive | default(false) }}
Christopher Karel
Bagaimana tugas berubah jika kunci "direktori" hanya daftar bukan kamus juga?
Chris F
7

Ini adalah contoh keluaran yang bagus yang bisa Anda coba sendiri. Buat buku pedoman baru bernama 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

Kemudian jalankan playbook seperti ini: ansible-playbook -i '172.16.222.131,' iteration_loop.yml

dan output akan memberi Anda bagaimana item diakses:

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

Dengan asumsi itu dict={a:[1,2,3],b:[1,2]}dan seterusnya:

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

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

Max Murphy
sumber
0

Saya akan memformat ulang vars Anda ke format di bawah ini:

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

dan kemudian buku pedoman saya seperti di bawah ini:

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
pengguna42826
sumber