Merging shared parameters with environment specifi

2019-07-13 08:55发布

问题:

I run my playbooks specifying the target server environment on the command line, e.g.:

ansible-playbook -e env=staging playbook.yml

Now I want to be able to provide parameters, e.g. dictionary of users to create on the server in such a way that there are users common to all environments, and also users that are specific to that one environment for which I run the playbook.

The directory structure could look like this:

├── group_vars
│   ├── all
│   │   ├── users.yml
│   │  
│   ├── development
│   │   ├── users.yml
│   │  
│   ├── production
│   │   ├── users.yml
│   │  
│   └── staging
│       ├── users.yml

I initially thought that a setup like this would do the job. However, the users.yml dictionaries for each environment are never merged with all/users.yml

ansible-playbook -e env=production playbook.yml would just read from production/users.yml.

How can I have Ansible merge users.yml from specific environments with all/users.yml - so that I always have the common and env-specific users created?

回答1:

Ansible by default will override hash/dictionary values by their equivalents that have a higher precedence.

You can override this by change the hash_behaviour option in ansible.cfg if you really want but I would suggest against it at such a global level.

Instead you could define your users like this:

users:
  name: dev-foo
  ...

and then also have an all_users variable defined in your all group_vars like this:

all_users:
  name: common-foo
  ...

And then you could combine the variables either by using a set_fact task to create the merged variable like this:

name: combine users
set_fact:
  combined_users: '{{ users | combine(all_users) }}'

Or you could combine it directly in the task where you intend to use it:

name: create users
user:
  name: {{ item.name }}
  ...
with_items: '{{ users | combine(all_users) }}'

If you're simply trying to combine 2 lists you can do this with simple addition of the lists:

name: combine users
set_fact:
  combined_users: '{{ users + all_users }}'

Or just directly:

name: create users
user:
  name: {{ item.name }}
  ...
with_items: users + all_users