Анзибль. переопределить один ключ словаря
Я использую возможность управлять конфигурацией как для производства, так и для бродячего бокса.
У меня есть файл со значениями по умолчанию: 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'
Что я делаю неправильно?
Ответы
Ответ 1
По умолчанию Ansible переопределяет переменные на первом уровне. Если вы хотите объединить словари, вы должны изменить свой файл ansible.cfg
и установить:
hash_behaviour=merge
(значение по умолчанию replace
).
Обратите внимание, что команда Ansible не рекомендует это (но не объясняйте почему).
Я предполагаю, что это реальное разделение между пользователями. Одно решение для всех: когда вы начинаете использовать эту функцию, вы не можете вернуться, и вы, вероятно, не сможете поделиться своим плейером с людьми replace
.
Тем не менее, вы по-прежнему можете пользоваться учебниками для воспроизведения (я не считаю, что в книжных играх используется поведение replace
как "функция" ). Это похоже на наличие типа крови AB, являющегося универсальным приемником... но поскольку магия обычно происходит при переменном разрешении, а не внутри задач или шаблонов, я думаю, что часто можно делиться своими ролями без каких-либо изменений.
Если вам нужно переопределить один ключ из, скажем, параметров ролей, вам придется передавать параметры каким-то запутанным способом.
Например, чтобы переопределить ключи post_max_size
и upload_max_size
в php5
dictionnary для определенной роли, вам придется сделать это следующим образом:
- { role: php5-fpm, php5: { post_max_size: 40M,
upload_max_filesize: 20M }}
При этом я использую поведение merge
с самого начала, и я очень доволен им. Это очень удобно для сохранения переменных.
Ответ 2
Начиная с Ansible 2.0, вы можете использовать фильтр Jinja2 combine
для объединения хэшей/словарей YAML без необходимости устанавливать hash_behavior=merge
на глобальном уровне в вашем файле ansible.cfg
.
Соответствующие документы: http://docs.ansible.com/ansible/playbooks_filters.html#combining-hashes-dictionaries
Ответ 3
Лучший способ, который я нашел, - использовать переменные в качестве значения словаря и переопределить это. Я нахожу, что это позволяет простое и мощное приоритетное значение переменной в отношении незаменимого порядка переменной
Роль/родителя/дефолты/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
role/parent/tasks/main.yml и role/child/tasks/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#variable-precedence-where-should-i-put-a-variable
Ответ 4
Просто попробовал с помощью 1.9s 1.9, и он отлично работает. Не уверен, но кажется, что у вас есть только опечатка в имени каталога group_vars
(не groups_vars
).