21

In some ansible roles (e.g. roles/my-role/) I've got quite some big default variables files (defaults/main.yml). I'd like to split the main.yml into several smaller files. Is it possible to do that?

I've tried creating the files defaults/1.yml and defaults/2.yml, but they aren't loaded by ansible.

myrdd
  • 2,272
  • 1
  • 17
  • 22

2 Answers2

51

The feature I'm describing below has been available since Ansible 2.6, but got a bugfix in v2.6.2 and another (minor) one in v2.7.
To see a solution for older versions, see Paul's answer.


defaults/main/

Instead of creating defaults/main.yml, create a directorydefaults/main/ — and place all YAML files in there.

  • defaults/main.ymldefaults/main/*.yml

Ansible will load any *.yml file inside that directory, so you can name your files like roles/my-role/defaults/main/{1,2}.yml.

Note, the old file — defaults/main.yml — must not exist. See this Github comment.


vars/main/

By the way, the above solution also works for vars/:

  • vars/main.ymlvars/main/*.yml

further details

The feature has been introduced in v2.6 — git commit, Pull Request, main Github issue.

There have been two bugfixes:

myrdd
  • 2,272
  • 1
  • 17
  • 22
  • That is awesome news! – Paul Calabro Sep 27 '18 at 18:05
  • Great news! Nevertheless I was running ansible 2.6.1 on my local machine and it was not working. After upgrade to current latest ansible (2.7.6) it was working properly. – Michael Aicher Feb 06 '19 at 14:24
  • 1
    @Lorex I now believe you have been running into a bug fixed in v2.6.2, see my updated answer, if interested – myrdd Apr 08 '19 at 09:40
  • @Arash this has been asked and answered [here](https://github.com/ansible/ansible/issues/11639#issuecomment-122525531) (*”It's just closer to current functionality. If all files started to be read it would be a breaking change.“*) and [here](https://github.com/ansible/ansible/issues/14248#issuecomment-261734510) (*”[`include_role`](https://docs.ansible.com/ansible/latest/modules/include_role_module.html) allows you to specify ’alternate‘ files [.] via [the] `defaults_from` option“*). The `include_role` module also has a `vars_from` parameter. – myrdd Jul 24 '19 at 06:35
4

If you aren't using 2.6 (which you probably should, but I understand that isn't always an option), then you might find include_vars useful.

- name: Include vars of stuff.yaml into the 'stuff' variable (2.2).
  include_vars:
    file: stuff.yaml
    name: stuff

- name: Conditionally decide to load in variables into 'plans' when x is 0, otherwise do not. (2.2)
  include_vars:
    file: contingency_plan.yaml
    name: plans
  when: x == 0

- name: Load a variable file based on the OS type, or a default if not found. Using free-form to specify the file.
  include_vars: "{{ item }}"
  with_first_found:
    - "{{ ansible_distribution }}.yaml"
    - "{{ ansible_os_family }}.yaml"
    - default.yaml

- name: Bare include (free-form)
  include_vars: myvars.yaml

- name: Include all .json and .jsn files in vars/all and all nested directories (2.3)
  include_vars:
    dir: vars/all
    extensions:
        - json
        - jsn

- name: Include all default extension files in vars/all and all nested directories and save the output in test. (2.2)
  include_vars:
    dir: vars/all
    name: test

- name: Include default extension files in vars/services (2.2)
  include_vars:
    dir: vars/services
    depth: 1

- name: Include only files matching bastion.yaml (2.2)
  include_vars:
    dir: vars
    files_matching: bastion.yaml

Note that this is a task directive, though. It isn't as neat as just being able to include it into the defaults file itself.

Paul Hodges
  • 8,723
  • 1
  • 12
  • 28