Is it possible to have group vars defined in roles?
For example I have the following structure in my role repo:
my_repo
|-defaults
| |-main.yml
| |-debian.yml
| |-redhat.yml
In debian.yml
I have defined a variable called ssh-package
as well in redhat.yml
but with different values.
If I install my role with ansible-galaxy and I have hosts defined in group redhat or debian, they wont pickup the variables. Do I need to specify the roles variables inside my target structure?
The statement in Role directory structure is horrible
Directories defaults and vars may also include nested directories. If your variables file is a directory, Ansible reads all variables files and directories inside in alphabetical order. If a nested directory contains variables files as well as directories, Ansible reads the directories first. Below is an example of a vars/main directory
IMO, you can put default variables into the files in the directory defaults/main instead of the file defaults/main.yml. This is what the above statement tries to describe. Other directories and files will be ignored. For example, given the inventory
shell> cat hosts
host_A
[debian]
host_B
host_D
[redhat]
host_C
host_D
Create the role my_repo
shell> tree roles
roles
└── my_repo
├── defaults
│ ├── debian.yml
│ ├── main.yml
│ └── redhat.yml
└── tasks
shell> cat roles/my_repo/defaults/main.yml
test_var: defaults
shell > cat roles/my_repo/defaults/debian.yml
test_var: debian
shell > cat roles/my_repo/defaults/redhat.yml
test_var: redhat
shell> cat roles/my_repo/tasks/main.yml
- debug:
msg: |
test_var: {{ test_var }}
group_names: {{ group_names }}
The play
shell> cat pb.yml
- hosts: all
roles:
- my_repo
gives (abridged)
ok: [host_A] =>
msg: |-
test_var: defaults
group_names: ['ungrouped']
ok: [host_B] =>
msg: |-
test_var: defaults
group_names: ['debian']
ok: [host_D] =>
msg: |-
test_var: defaults
group_names: ['debian', 'redhat']
ok: [host_C] =>
msg: |-
test_var: defaults
group_names: ['redhat']
All values of test_var are defaults because only roles/my_repo/defaults/main.yml was included.
What will be the best option to include debian.yml and redhat.yml? Look at the Resolving local relative paths
Ansible tries to find the file in the following order: In the current role. In its appropriate subdirectory: “files”, “vars”, “templates”, or “tasks”; depending on the kind of file Ansible is searching for...
Knowing this, let's put the debian.yml and redhat.yml files into the directory vars. Remember, the files will be ignored if not in the directory vars/main
shell> tree roles/
roles/
└── my_repo
├── defaults
│ └── main.yml
├── tasks
│ └── main.yml
└── vars
├── debian.yml
└── redhat.yml
Use include_vars
shell> cat roles/my_repo/tasks/main.yml
- include_vars: "vars/{{ item }}.yml"
loop: "{{ group_names | difference(['ungrouped']) }}"
- debug:
msg: |
test_var: {{ test_var }}
group_names: {{ group_names }}
gives (abridged)
ok: [host_A] =>
msg: |-
test_var: defaults
group_names: ['ungrouped']
ok: [host_B] =>
msg: |-
test_var: debian
group_names: ['debian']
ok: [host_D] =>
msg: |-
test_var: redhat
group_names: ['debian', 'redhat']
ok: [host_C] =>
msg: |-
test_var: redhat
group_names: ['redhat']
Notes:
See group_names
You can omit the directory vars in include_vars
- include_vars: "{{ item }}.yml"
shell> tree roles/my_repo
roles/my_repo
├── defaults
│ └── main.yml
└── tasks
└── main.yml
shell> cat roles/my_repo/defaults/main.yml
test_var: |
{% if 'redhat' in group_names %}
redhat
{% elif 'debian' in group_names %}
debian
{% else %}
default
{% endif %}
Then, the include_vars task is not needed. The below debug will give the same results
shell> cat roles/my_repo/tasks/main.yml
- debug:
msg: |
test_var: {{ test_var }}
group_names: {{ group_names }}