Возможна итерация словаря со списками

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, но не смог найти рабочее решение.

Можно ли повторить эту структуру? Если нет, то как мне его реструктурировать, чтобы он работал? Можно ли сделать это без нарушения правила СУХОГО (например, включить имя пользователя в каждую запись)?

Слава Фомин II
источник

Ответы:

21

Прежде всего, вы можете рассмотреть возможность использования fileмодуля , а не shell. Он менее подвержен неудачам и якобы идемпотентен. Однако это может привести к некоторым проблемам со смешиванием каталогов, файлов и файловых глобусов. 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модулем.
Слава Фомин II
Сплошная логика. Похоже, shellэто ваша лучшая ставка с ACL и рекурсией.
Кристофер Карел
Кстати, можно ли игнорировать отсутствующий ключ хеша, как recursiveв моем примере? Когда я пытаюсь получить к нему доступ, а его нет, Ansible остановит выполнение playbook и выдаст исключение. Я предпочитаю не добавлять recursive: falseк каждой записи.
Слава Фомин II
1
Я думаю , что синтаксис по умолчанию должен работать: {{ some_variable | default() }}. Итак, в данном случае: {{ item.1.recursive | default(false) }}
Кристофер Карел
Как изменится задача, если ключ "directoryies" - это просто список вместо словаря?
Крис Ф
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

Затем запустите playbook следующим образом: 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

Я переформатирую ваши переменные в формат ниже:

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
user42826
источник