Анзибль. переопределить один ключ словаря
Я использую ansible для управления конфигурацией как для производства, так и для vagrant box. У меня есть файл со значениями по умолчанию: group_vars / all.
---
env: prod
wwwuser: www-data
db:
root_pwd: root_pwd
pdo_driver: pdo_mysql
host: localhost
name: test
user: test
pwd: test
charset: utf8
domain: somedomain
projectdir: /var/www/application
webrootdir: "{{ projectdir }}/web"
В host_vars/vagrantbox я хочу иметь что-то вроде:
db:
root_pwd: super_easy_password
Но этот переопределяет полностью db dictrionary, а я хочу переопределить один ключ. Как этого добиться?
ОБНОВЛЕНИЕ 1 Только что проверил с ansible.cfg:
[defaults]
host_key_checking=false
hash_behaviour=merge
groups_vars / все
db:
root_pwd: some_strong_pwd
pdo_driver: pdo_mysql
host: localhost
name: dbname
user: dbuser
pwd: some password
charset: utf8
host_vars/vagrantbox
db:
root_pwd: root
Я получаю следующую ошибку:
One or more undefined variables: 'dict object' has no attribute 'name'
Что я делаю не так?
4 ответа
По умолчанию Ansible переопределяет переменные на первом уровне. Если вы хотите иметь возможность объединять словари, вы должны изменить свой ansible.cfg
файл и набор:
hash_behaviour=merge
(значение по умолчанию replace
).
Обратите внимание, что команда Ansible не рекомендует это (но не объясняет почему). Я предполагаю, что это реальное разделение настроек между пользователями. Это своеобразное решение, которое принимается раз и навсегда: когда вы начнете использовать эту функцию, вы не сможете вернуться назад и, вероятно, не сможете поделиться своей книгой с replace
люди типа
Тем не менее, вы все равно можете извлечь выгоду из playbooks там (я не думаю, что playbooks использовать replace
поведение как "особенность"). Это все равно что иметь группу крови AB, быть универсальным приемником... но поскольку магия обычно происходит с переменным разрешением, а не внутри задач или шаблонов, я думаю, что часто можно поделиться своими ролями без каких-либо изменений.
Если вам нужно переопределить один ключ из, скажем, параметров роли, вам придется передавать параметры некоторым запутанным способом.
Например, переопределить post_max_size
а также upload_max_size
ключи в php5
словарь для конкретной роли, вам придется сделать это следующим образом:
- { role: php5-fpm, php5: { post_max_size: 40M,
upload_max_filesize: 20M }}
Как говорится, я использую merge
поведение с самого начала, и я очень доволен этим. Это очень удобно для организации переменных.
Начиная с Ansible 2.0, вы можете использовать Jinja2 combine
фильтр для объединения хэшей / словарей YAML без необходимости установки hash_behavior=merge
на глобальном уровне в вашем ansible.cfg
файл.
Соответствующие документы: http://docs.ansible.com/ansible/playbooks_filters.html
Лучший способ, который я нашел, - это использовать переменные в качестве значения элемента словаря и переопределить его. Я считаю, что это позволяет простой и мощный приоритет переменной в отношении порядка переменной ansible
Роль / родитель / по умолчанию / main.yml
---
root_pw_value: ParentPassword
parent_dict:
- root_pw: "{{ root_pw_value }}"
Роль / ребенок / по умолчанию / main.yml
Замечания: role/child/meta/main.yml
содержит dependencies: - { role: parent }
---
root_pw_value: ChildPassword
игра-me.yml
---
- hosts: all
roles:
- child
Роли / родитель / задачи / main.yml & Роли / ребенок / задачи / main.yml
- debug: var=parent_dict
Бежать ansible -i localhost, --connection="local" play-me.yml
и вы получите следующий вывод:
PLAY [all] ********************************************************************
GATHERING FACTS ***************************************************************
ok: [localhost]
TASK: [parent | debug var=parent_dict] ****************************************
ok: [localhost] => {
"var": {
"parent_dict": [
{
"root_pw": "ParentPassword"
}
]
}
}
TASK: [child | debug var=parent_dict] *****************************************
ok: [localhost] => {
"var": {
"parent_dict": [
{
"root_pw": "ChildPassword"
}
]
}
}
PLAY RECAP ********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
И это по умолчанию. Если вы укажете root_pw_value
на более конкретных уровнях приоритета, таких как переменные группы / хоста, переменные роли, extra_vars в командной строке или что-либо из порядка приоритета [0], вы получите их.
[0] http://docs.ansible.com/ansible/playbooks_variables.html
Только что попробовал с ansible 1.9.3 и работает нормально. Не уверен, но кажется, что вы просто опечатка в имени group_vars
каталог (не groups_vars
).