Reputation: 493
I'm currently making the transition from Puppet to Ansible and so far so good. Yet I want to automatize as much as possible.
I'm trying to use a with_items
loop inside vars_files
to load variable files based on a given list of items. Ansible complains about the syntax and I can't seem to find an example of a similar solution, only examples that use with_items
inside tasks and roles.
For example:
vars_files:
- ["vars/{{ item }}-{{ ansible_fqdn }}.yml", "vars/{{ item }}-{{ system_environment }}.yml", "vars/{{ item }}.yml"]
with_items:
- php
- nginx
The goal here is to loop the second line for as long as there are items in with_items
using an array to fallback on the next item if it can't find the given file (which works).
Not sure if this is at all possible, but I wanted to ask before taking another direction.
Upvotes: 6
Views: 11988
Reputation: 493
Putting this in a separate answer to expand on the group and host variables solution I eventually came up with (cc @udondan).
Basically I group all my hosts in my inventory file under several sub and parent groups no matter what. Then I create files for group vars whenever applicable so it follows a certain order of precedence (first is highest and overrides all others, last applies to all hosts and can be overridden down the chain):
task vars > playbook vars > host_vars > web/database-local > local > web/database > all
That way I can define variables for all hosts to use (all), just web/database (mostly production values), all local servers (local group), all local web/database servers, et cetera, or per-host (the standard host_vars
). Of course playbook and task vars override these further. All of this following the Ansible guidelines.
An example of a local inventory (replace default with your hostname or IP, add as many as you like per group, x-local can be omitted if this would be a production inventory):
[web-local]
default
[database-local]
default
[local:children]
web-local
database-local
[web:children]
web-local
[database:children]
database-local
Then my group_vars
folder with directories for each inventory group and variables split into files to keep it structured (could just have one database-local.yaml
file for the database-local
group for instance instead of folders and split YAML-files):
group_vars/
all/
always_applied_variables.yaml
swap.yaml
web/
database/
database_only_variables.yaml
database-production/
production_database_variables.yaml
production/
random_production_only_variables.yaml
local/
users.yaml
web-local/
database-local/
local_database_variables.yaml
host_vars/
default/
php.yaml
mysql.yaml
other_specific_host_variables.yaml
Hope this is somewhat clear. I'd be happy to answer any questions.
Upvotes: 0
Reputation: 59989
with_items
, or in general all loops, are a feature of tasks. vars_files
though is no task. So it won't work the way you tried it and the short answer would be: It is not possible.
I don't know of a clean way to solve your exact problem. A custom vars plugin might be an option. But vars plugin work on a global level while your vars seem to be used in a role.
A custom lookup plugin might be a solution if solving this on task level is an option for you. The lookup plugin takes your input, checks for presence of the files and returns an array of the files which need to be include. This then can be used with the include_vars module.
- include_vars: "{{ item }}"
with_my_custom_plugin:
- php
- nginx
An ugly solution would be to combine the with_items loop with a with_first_found loop. Though, since you cannot directly nest loops, you need to work with an include.
- include: include_vars.yml
with_items:
- php
- nginx
And inside include_vars.yml
you then can use with_first_found
with the include_vars module.
- include_vars: "{{ item }}"
with_first_found:
- vars/{{ item }}-{{ ansible_fqdn }}.yml
- vars/{{ item }}-{{ system_environment }}.yml
- vars/{{ item }}.yml
Upvotes: 5