Перебор списка в словаре в ansible

У меня есть переменная, структурированная так. Я успешно использовал это с with_dict с одним ключом в accessible_from

vars:
  mysql_dbs:
    db1:
      user: db1_user
      pass: "password"
      accessible_from: localhost
    db2:
      user: db2_user
      pass: "password2"
      accessible_from: '%'

Это применяется с использованием mysql_db ANSIBLE модуль, как это:

- name: Configure mysql users
  mysql_user: name={{ item.value.user }} password={{ item.value.pass }} host={{ item.value.accessible_from | default('localhost')}} priv={{ item.key }}.*:ALL state=present
  with_dict: "{{ mysql_dbs }}"

мне бы хотелось accessible_from иметь возможность быть списком. Неважно, должен ли это быть список, но одной пары ключ / значение недостаточно:) Так, например:

vars:
  mysql_dbs:
    db1:
      user: db1_user
      pass: "password"
      accessible_from:
        - server1
        - server2
        - localhost
    db2:
      user: db2_user
      pass: "password"
      accessible_from:
        - '%'

Итак, цель - создать все базы данных и пользователей в одной игре. Я пытался поиграть с with_subelements, безуспешно. Возможно ли это сделать? Или необходимо реструктурировать данные или переписать игру? Я сделаю это, если придется, но мне было интересно, есть ли другой способ обойти это.

2 ответа

Во-первых: вы можете изменить свой mysql_dbs в список (потому что в with_subelements Вы не можете ссылаться на ключи предметов), например:

mysql_dbs:
  - name: db1
    user: db1_user
    pass: "password"
    accessible_from:
      - server1
      - server2
      - localhost
  - name: db2
    user: db2_user
    pass: "password2"
    accessible_from: 
      - '%'

И пользователь with_subelements:

- mysql_user: name={{ item[0].user }} password={{ item[0].pass }} host={{ item[1] }} priv={{ item[0].name }}.*:ALL state=present
  with_subelements:
    - "{{ mysql_dbs }}"
    - accessible_from

Но это не удастся, если accessible_from не определено для любой базы данных. Вы можете использовать skip_missing, но это пропустит всю БД. Таким образом, вы не можете опустить accessible_from в этом случае.

Второе: вы можете использовать помощника set_fact сформировать список с ключом и значением, также по умолчанию accessible_from в localhost, Это будет работать без рефакторинга ваших данных:

- set_fact:
    db_name: "{{ item.key }}"
    db_params: "{{ dict(accessible_from=['localhost']) | combine(item.value) }}"
  with_dict: "{{ mysql_dbs }}"
  register: mysql_dbs_fact
  loop_control:
    label: "{{ item.key }}"

- debug:
    msg: "mysql_user: name={{ item[0].db_params.user }} password={{ item[0].db_params.pass }} host={{ item[1] }} priv={{ item[0].db_name }}.*:ALL state=present"
  with_subelements:
    - "{{ mysql_dbs_fact.results | map(attribute='ansible_facts') | list }}"
    - db_params.accessible_from
  loop_control:
    label: "{{ item[0].db_name }}->{{ item[1] }}"

Попробуй это:

 vars:
     mysql_dbs:
       db1:
         user: db1_user
         pass: "password"
         accessible_from:
           - acc_from: server1
           - acc_from: server2
           - acc_from: localhost
       db2:
         user: db2_user
         pass: "password"
         accessible_from:
           - acc_from: '%'
      tasks:
      - name: Configure mysql users
        debug: msg="{{ item.0.user }} password={{ item.0.pass }} host={{ item.1.acc_from }} priv={{ item.0 }}.*:ALL state=present"
        with_subelements:
           - "{{ mysql_dbs }}"
           - accessible_from
Другие вопросы по тегам