Я хочу создать шаблоны конфигураций php.ini для apache2 и cli. Я отфильтровал параметры по умолчанию и добавил их в словарь следующим образом:
php_config_options:
cli:
engine: "On"
short_open_tag: "Off"
precision: 14
[...]
apache2:
engine: "On"
short_open_tag: "Off"
precision: 14
[...]
Я поместил это под vars/Ubuntu-22.yaml
, чтобы иметь возможность постоянно настраивать его для выпусков. Мой шаблон выглядит так:
{% if php_config_options[environment] is defined %}
{% for option, value in php_config_options[environment].items() %}
{{ option }} = {{ value }}
{% endfor %}
{% endif %}
и моя задача такая:
- name: setup | Template php.ini
ansible.builtin.template:
src: "{{ php_version }}/php.ini.j2"
dest: /etc/php/{{ php_version }}/apache2/php.ini
owner: root
group: root
mode: 0644
vars:
environment: "apache2"
Когда я пытаюсь запустить его, я получаю сообщение об ошибке dict object has no element []
, но не знаю почему. Может ли кто-нибудь помочь мне здесь?
Моя идея состоит в том, чтобы использовать эти переменные по умолчанию, но когда я захочу изменить одну из них, я установлю ее либо в group_vars, либо в host_vars, и он выберет эту + другие переменные по умолчанию.
Кстати, должны быть библиотеки, которые могут генерировать действительный INI-файл из dict. Выполнение этого с помощью шаблонов Jinja чрезвычайно подвержено ошибкам. Случайная новая строка или что-то в этом роде, и вы испортите синтаксис INI.
Потому что вы пытаетесь создать INI-файл PHP…?!
Вам следует дважды проверить свои примеры перед публикацией, потому что ваша структура данных вводила в заблуждение и заставляла людей отвечать вне контекста. Я исправил переменную вашего примера.
Вам следует использовать модуль Community.general.ini_file, который был разработан именно для вашего случая использования — чтобы настроить существующие настройки, не сохраняя значения по умолчанию самостоятельно.
Я создал минимальный воспроизводимый сборник сценариев, чтобы проиллюстрировать, как можно сопоставить настройки yaml с существующим ini-файлом.
Допустим, у нас есть файл config.ini в каталоге playbook со следующим содержимым:
[section0]
key0 = value0
[section1]
key1 = old_value
Затем мы можем выполнить следующий файл playbook.yaml
- name: Generate ini from yaml
hosts: localhost
vars:
default_php_config_options:
section1:
key1: default_value
section2:
key2: default_value
section3:
key3: default_value
php_config_options:
section1:
key1: value1
section2:
key2: value2
key3: value4
tasks:
- name: Generate INI file from YAML variable
community.general.ini_file:
path: "{{ playbook_dir }}/config.ini"
section: "{{ item.0 }}"
option: "{{ item.1 }}"
value: "{{ item.2 }}"
mode: "0644"
loop: >-
{%- set results = [] -%}
{%- for section in default_php_config_options | combine(php_config_options) | items -%}
{%- for item in section.1.items() -%}
{%- set _ = results.append([section.0, item.0, item.1]) %}
{%- endfor -%}
{%- endfor -%}
{{ results }}
В этой книге мы определяем две переменные: default_php_config_options
с настройками по умолчанию, которые необходимо переопределить, и php_config_options
которые содержат переопределения для параметров по умолчанию.
Вывод команды ansible-playbook playbook.yaml
будет содержать
TASK [Generate INI file from YAML variable]
changed: [localhost] => (item=['section1', 'key1', 'value1'])
changed: [localhost] => (item=['section2', 'key2', 'value2'])
changed: [localhost] => (item=['section2', 'key3', 'value4'])
changed: [localhost] => (item=['section3', 'key3', 'default_value'])
и содержимое файла config.ini
[section0]
key0 = value0
[section1]
key1 = value1
[section2]
key2 = value2
key3 = value4
[section3]
key3 = default_value
Обратите внимание, что значение ключа1 в разделе 1 было заменено и добавлены отсутствующие параметры, в то время как исходные значения раздела 0 остались неизменными.
Теперь об этом цикле: что мы делаем — мы объединяем default_php_config_options
с php_config_options
, таким образом переопределяя первое значения из более позднего, если оно присутствует (см. документацию по объединению фильтров), а затем для каждой пары ключ/значение в каждом разделе, который мы создаем. список, содержащий
И выполнение модуля init_file для каждого сгенерированного списка. Я уверен, что другие джинджа-гуру могут придумать умную функцию для решения той же задачи, но мне нравится, чтобы мои книги были ясными.
Предостережение заключается в том, что если вы удалите что-то из default_php_config_options
или в php_config_options
, но в ключе, которого не было в настройках по умолчанию, это не приведет к изменению уже измененных ключей или разделов обратно к значениям по умолчанию. В этом случае вам следует либо явно указать старое значение, либо создать отдельную задачу для удаления ненужных ключей.
Обновлено: добавлен пример объединения. default_php_config_options | combine(php_config_options)
можно использовать и с примером @Vladimir Botka, но я оставлю свой ответ, который дает возможность работать с существующими ini-файлами.
спасибо за этот хороший ответ, но я думаю, что это подходит для моего случая. Я хочу иметь значения по умолчанию и иметь возможность их переопределять. cli — это дополнительный файл, и apache тоже. Это не разделы в одном файле. очень важно иметь значения по умолчанию, например. в vars/main.yaml и иметь возможность переопределять их, например. host_vars, но без необходимости указывать их все.
Добавлен пример объединения некоторых значений по умолчанию с некоторыми значениями, отличными от значений по умолчанию.
Большое спасибо. Когда у меня есть одна и та же опция в обоих словарях, занимает ли место приоритет переменной?
Учитывая упрощенный словарь
php_config_options:
cli:
engine: "On"
short_open_tag: "Off"
precision: 14
Используйте фильтр Community.general.to_ini. Например, шаблон
{{ php_config_options | community.general.to_ini }}
дает
[cli]
engine = On
short_open_tag = Off
precision = 14
Example of a complete playbook for testing
- hosts: localhost
vars:
php_config_options:
cli:
engine: "On"
short_open_tag: "Off"
precision: 14
tasks:
- copy:
dest: /tmp/ansible/php.ini
content: |
{{ php_config_options | community.general.to_ini }}
Это была комбинация того и другого, но это более простой вариант. Я просто не использовал копию, вместо этого я использовал шаблон, но это сработало. Предварительно я объединил словари в другую переменную с суффиксом _merged.
Вы можете использовать его в файле шаблона, блоке контента или где-либо еще. Шаблон Jinja2 такой же. Модуль копирования использовался для простоты.
Возможно, вы захотите использовать
{% if environment in php_config_options %}