Назад | Перейти на главную страницу

Ansible заменяет все значения соответствующим именем переменной

Я новичок в Ansible и могу ошибаться в этом, но это единственный способ, которым я знаю, как справиться с этой проблемой.

У меня есть файл ini, который содержит около 4000 записей. Пытаясь выполнить конфигурацию как код, я извлек значения каждой записи в файл переменных в формате sectionheader--keyname: originalvalue и заменил их шаблоном токена и именем переменной, которая теперь содержит их значение.

Я знаю, что Ansible может выполнять замену регулярных выражений, но не смог найти способ сделать это так динамично, как этот.

исходный файл:

[sectionheader1]

keyname1=value1

[sectionheader2]

keyname1=value2

файл с заменой токенов теперь хранится в исходном коде и доступен для развертывания:

[sectionheader1]

keyname1=%<sectionheader1--keyname1>

[sectionheader2]

keyname1=%<sectionheader2--keyname1>

переменные:

testenvironment:
  sectionheader1--keyname1: value1
  sectionheader2--keyname1: value2
prodenvironment:
  sectionheader1--keyname1: value1 (specific to prod)
  sectionheader2--keyname1: value2 (specific to prod)

И тогда идея в том, что я бы заменил каждое вхождение шаблона токена %<> что я нахожу подходящее имя переменной, и альт, я создал свой файл конфигурации, специфичный для среды, в которой я работаю. И теперь я могу проверить, есть ли у меня какие-либо %<> шаблоны, я знаю, что не все переменные были определены, и может вызвать ошибку. Octopus deploy таким образом обрабатывает замену переменных в файлах конфигурации, и это то, с чем у меня больше всего опыта.

Есть ли у Ansible способ сделать это? Я мог бы написать сценарий для этого, я полагаю, и просто вызвал бы его в Ansible, но я надеялся на встроенный способ замены переменной конфигурации в виде кода.

С соответствующим шаблоном установки вы сможете настроить все с помощью dict.
.Ini - это, по сути, двухуровневый словарь, поэтому мы просто будем рассматривать его как таковой, используя 2 вложенных цикла jinja2 for в шаблоне .j2.

В этом примере я устанавливаю переменную env в командной строке для компактности, но ее можно установить в файлах inventory, host_vars или group_vars.

ansible/example.yml

---
- hosts: localhost
  gather_facts: false
  vars:
    dev:
      section1:
        key1: value1
      section2:
        key1: value1
    prod:
      section1:
        key1: value2 #(specific to prod)
      section2:
        key1: value2 #(specific to prod)
  tasks:
    - template: src=example.ini.j2  dest=/tmp/ansible.ini

ansible/templates/example.ini.j2

{% for section in vars[vars.env] %}
[{{section}}]
{% for key in vars[env][section] %}
{{key}}={{vars[env][section][key]}}
{% endfor %}
{% endfor %}

.

$ ansible-playbook ansible/test.yml -e env=dev; cat /tmp/ansible.ini

PLAY [localhost] ********************************************************************************************************************************************

TASK [template] *********************************************************************************************************************************************
changed: [localhost]

PLAY RECAP **************************************************************************************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[section1]
key1=value1
[section2]
key1=value1

.

$ ansible-playbook ansible/test.yml -e env=prod; cat /tmp/ansible.ini

PLAY [localhost] ********************************************************************************************************************************************

TASK [template] *********************************************************************************************************************************************
changed: [localhost]

PLAY RECAP **************************************************************************************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[section1]
key1=value2
[section2]
key1=value2

В ini_file модуль может быть использован.

Задача ниже

- ini_file:
    path: /scratch/testenvironment.ini
    section: "{{ item.key.split('--').0 }}"
    option: "{{ item.key.split('--').1 }}"
    value: "{{ item.value }}"
  loop: "{{ testenvironment|dict2items }}"

дает

$ cat /scratch/testenvironment.ini 

[sectionheader2]
keyname1 = value2
[sectionheader1]
keyname1 = value1

Если разделы должны быть отсортированы по алфавиту, используйте

 loop: "{{ testenvironment|dict2items|sort(attribute='key') }}"