Использование Ansible ini_file с вложенным dict?

Я пытаюсь достичь следующего. Предположим, у нас есть playbook , подобный следующему:

---

- hosts: local
  tasks:
    - ini_file:
      path: test.ini
      create: yes
      section: "{{???}}"
      option: "{{???}}"
      value: "{{???}}"
    loop: "{{inidict ...???}}"
  vars:
    inidict:
      section1:
        option1: value1
        option2: value2
      section2:
        option1: value1
        option2: value2

Вышеупомянутый playbook недействителен из-за строк с ??? в них.

Теперь моя цель - чтобы сопоставить этот dict с разделами / параметрами / значениями внутри файла INI и получить следующее содержимое INI:

[section1]
option1 = value1
option2 = value2

[section2]
option1 = value1
option2 = value2

К сожалению, это не удается, поскольку мне нужно как-то добавить вторичный уровень вложенности для цикла в ] перебирать разделы во внешнем цикле, а затем - параметры / значения во внутреннем.

Есть ли более элегантный или «ответственный» (из-за отсутствия термина Ansible, соответствующего pythonic) способ добиться этого, чем путем его обертывания уровень цикла в роли и итерация по именам разделов с использованием, скажем, include_role , при передаче имени раздела и списка опций / значений в качестве переменной?

Я полагаю, что одной альтернативой могло бы быть «сглаживание» словарь таким образом, чтобы получилось что-то, что составляет (YAML):

  vars:
    inicontents:
      - section: section1
        key: option1
        value: value1
      - section: section1
        key: option2
        value: value2
      - section: section2
        key: option1
        value: value1
      - section: section2
        key: option2
        value: value2

Я просто хотел бы оставить его СУХИМ и аннулируйте дублирование имени раздела, когда ясно, что dict будет идеально соответствовать «модели данных» файла INI.

3
задан 28 November 2018 в 19:03
1 ответ

Я не знаю о способе сделать это с ansible по умолчанию кроме использования Вашей "приглушенной" версии. К счастью, Вы можете иметь лучший из обоих миров и записать Ваш собственный плагин фильтра для выравнивания dict для Вас. Просто добавьте что-то как следующее к filter_plugins каталог в Вашем каталоге проекта или в ~/.ansible/plugins/filter_plugins и назовите его чем-то как filters.py:

class FilterModule(object):
    def filters(self):
        return { 'ini_dict_flatten': self.ini_dict_flatten }

    def ini_dict_flatten(self, arg):
        ret = []
        for section, subdict in arg.items():
            for key, value in subdict.items():
                ret.append(dict(section=section,
                                key=key,
                                value=value))
        return ret

После этого можно использовать новый фильтр в проекте как это:

- hosts: localhost
  tasks:
    - ini_file:
        path: /tmp/test.ini
        create: yes
        section: "{{ item.section }}"
        option: "{{ item.key }}"
        value: "{{ item.value }}"
      loop: "{{ inidict | ini_dict_flatten }}"
  vars:
    inidict:
      section1:
        option1: value1
        option2: value2
      section2:
        option1: value1
        option2: value2

иногда помогает, знаете ли Вы Python начиная с того способа, которым можно записать собственные плагины для ansible.

РЕДАКТИРОВАНИЕ: Я буду включать намного менее читаемый и не рекомендуемое решение также. Начиная с loop: работы с json отформатированными строками и jinja2 применяются к строкам в ansible, прежде чем они будут обработаны, можно использовать логику Джинджи для создания "flattend" для Вас непосредственно в сборнике пьес. Это решение является намного более ужасным и менее допускающим повторное использование, чем запись Вашего собственного фильтра, но thecnically все еще работает.

- hosts: localhost
  vars:
    inidict:
      section1:
        option1: value1
        option2: value2
      section2:
        option1: value1
        option2: value2
  tasks:
    - ini_file:
        path: /tmp/test.ini
        create: yes
        section: "{{ item.section }}"
        option: "{{ item.key }}"
        value: "{{ item.value }}"
      loop: >-
        [
        {% for section, subdict in inidict.items() %}
          {% for key, value in subdict.items() %}
            {'section': '{{ section }}',
             'key': '{{ key }}',
             'value': '{{ value }}'}
            {% if not loop.last %}
              ,
            {% endif %}
          {% endfor %}
          {% if not loop.last %}
            ,
          {% endif %}
        {% endfor %}
        ]

0
ответ дан 3 December 2019 в 07:49

Теги

Похожие вопросы