This question already has an answer here:
- Ansible : host in multiple groups 2 answers
I am using ansible to manage configuration as for production, as well as for vagrant box. I have file with default values: 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"
In host_vars/vagrantbox I want tohave something like:
db:
root_pwd: super_easy_password
But this one is overriding completely db dictrionary, while I want to override single key. How to achieve that?
UPDATE 1 Just checked with ansible.cfg:
[defaults]
host_key_checking=false
hash_behaviour=merge
groups_vars/all
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
I am getting following error:
One or more undefined variables: 'dict object' has no attribute 'name'
What I do wrong?
Just tried with ansible 1.9.3 and it works fine. Not sure but it seems you just have a typo within name of
group_vars
directory (notgroups_vars
).The best way I have found is to use variables as the value of the dictionary item, and override that. I find this allows simple and powerful variable precedence with regards to ansible's order of variable
role/parent/defaults/main.yml
role/child/defaults/main.yml
Note:
role/child/meta/main.yml
containsdependencies: - { role: parent }
play-me.yml
roles/parent/tasks/main.yml & roles/child/tasks/main.yml
Run
ansible -i localhost, --connection="local" play-me.yml
and you get the following output:And these are defaults. If you specify
root_pw_value
at more specific levels of precedence, such as inventory group/host variables, role variables, extra_vars on the command line, or anything from the precedence order[0] you'll get those.[0] http://docs.ansible.com/ansible/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable
Starting with Ansible 2.0, you can use the Jinja2
combine
filter to merge YAML hashes/dictionaries without having to sethash_behavior=merge
at a global level in youransible.cfg
file.Relevant docs: http://docs.ansible.com/ansible/playbooks_filters.html#combining-hashes-dictionaries
By default, Ansible overrides variables at the first level. If you want to be able to merge dictionaries, you have to change your
ansible.cfg
file and set :(the default value being
replace
).Note that the Ansible team does not recommend this (but do not explain why). I guess this is a real dividing setting between users. A kind of decision that is done once for all : when you start using this feature, you can not go back, and you probably can not share your playbook with
replace
-type people.However, you can still benefit from the playbooks out there (I don't hink playbooks use
replace
behaviour as a "feature"). It's like having an AB blood type, being an universal receiver... but since the magic usually happens at variable resolution, not inside tasks or templates, I think it is often possible to share your roles without any changes.If you need to override a single key from, let's say, role parameters, you'll have to pass parameters in some convoluted way.
For instance, to override
post_max_size
andupload_max_size
keys in aphp5
dictionnary for a specific role, you'll have to do it this way :This being said, I use
merge
behaviour since the beginning, and I'm pretty happy with it. It is very handy to keep variables organised.