
There are a few different ways to invoke one or more roles in a playbook.
- roles
- import_playbook
- import_role
- include_role (this article)
- include_tasks
- import_tasks
Let's say you have the following structure.
├── /usr/local
│ ├── main.yml
│ ├── roles
│ │ ├── foo
│ │ ├── ├── tasks
│ │ ├── ├── ├── main.yml
│ │ ├── bar
│ │ ├── ├── tasks
│ │ ├── ├── ├── main.yml
And the foo role creates and then deletes the /tmp/foo.txt file and the bar role creates and then deletes the /tmp/bar.txt file.
~]$ cat roles/foo/tasks/main.yml
- name: touch /tmp/foo.txt
ansible.builtin.file:
path: /tmp/foo.txt
state: touch
- name: delete /tmp/foo.txt
ansible.builtin.file:
path: /tmp/foo.txt
state: absent
~]$ cat roles/bar/tasks/main.yml
- name: touch /tmp/bar.txt
ansible.builtin.file:
path: /tmp/bar.txt
state: touch
- name: delete /tmp/bar.txt
ansible.builtin.file:
path: /tmp/bar.txt
state: absent
Here is a simple example of how roles "foo" and "bar" could be run using include_role. This assumes that the "foo" and "bar" roles are included in one of your roles search directories.
---
- hosts: localhost
tasks:
- name: include_role foo
ansible.builtin.include_role:
name: foo
- name: include_role bar
ansible.builtin.include_role:
name: bar
...
Running this playbook should return something like this.
PLAY [localhost] *********************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************
ok: [localhost]
TASK [include_role foo] **************************************************************************************************************************************************************************************
TASK [foo : touch /tmp/foo.txt] ******************************************************************************************************************************************************************************
changed: [localhost]
TASK [foo : delete /tmp/foo.txt] *****************************************************************************************************************************************************************************
changed: [localhost]
TASK [include_role bar] **************************************************************************************************************************************************************************************
TASK [bar : touch /tmp/bar.txt] ******************************************************************************************************************************************************************************
changed: [localhost]
TASK [bar : delete /tmp/bar.txt] *****************************************************************************************************************************************************************************
changed: [localhost]
PLAY RECAP ***************************************************************************************************************************************************************************************************
localhost : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Let's say you are using when to do something like this.
---
- hosts: all
roles:
- role: foo
when: x is defined
- role: bar
when: y is defined
...
This is not ideal, as each task in the playbook that is not used will be skipped, making for messy output and a messy ansible.log with a bunch of "skipping" tasks.
PLAY [localhost] *********************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************
ok: [localhost]
TASK [foo : touch /tmp/foo.txt] ******************************************************************************************************************************************************************************
skipping: [localhost]
TASK [foo : delete /tmp/foo.txt] *****************************************************************************************************************************************************************************
skipping: [localhost]
TASK [bar : touch /tmp/bar.txt] ******************************************************************************************************************************************************************************
skipping: [localhost]
TASK [bar : delete /tmp/bar.txt] *****************************************************************************************************************************************************************************
skipping: [localhost]
PLAY RECAP ***************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
One thing that is really nice about include_role is that if the when statement does not evaluate to true the role will just totally be skipped and you won't get a bunch of output with "skipping" tasks.
---
- hosts: all
tasks:
- name: include_role foo when x is defined
ansible.builtin.include_role:
name: foo
when: x is defined
- name: include_role bar when y is defined
ansible.builtin.nclude_role:
name: bar
when: y is defined
...
Now, the role will be skipped without iterating through each task in the role.
PLAY [localhost] *********************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************
ok: [localhost]
TASK [include_role foo] **************************************************************************************************************************************************************************************
skipping: [localhost]
TASK [include_role bar] **************************************************************************************************************************************************************************************
skipping: [localhost]
PLAY RECAP ***************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
By default, the tasks in the main.yml file in the role will be invoked. In this example, the tasks in roles/foo/tasks/main.yml would be run.
---
- hosts: all
tasks:
- name: include_role foo
ansible.builtin.include_role:
name: foo
...
tasks_from can be used to invoke the tasks in a specific YAML file. In this example, the tasks in roles/foo/tasks/bar.yml would be run.
---
- hosts: all
tasks:
- name: include_role foo bar.yml
ansible.builtin.include_role:
name: foo
tasks_from: bar.yml
...
Including variables (vars and vars_from)
By default, if there is a "vars" directory that contains a main.yml file in the same directory as the role, the variables in the vars main.yml file will be available in the tasks main.yml file.
roles/foo/tasks/main.yml
roles/foo/vars/main.yml
If you have other yaml files in the role vars directory, such as roles/foo/vars/bar.yml, the vars_from parameter can be used to include the variable in bar.yml.
---
- hosts: all
tasks:
- name: include the variables in roles/foo/vars/bar.yml
ansible.builtin.include_role:
name: foo
vars_from: bar
...
Or, variables can be define using vars.
---
- hosts: all
tasks:
- ansible.builtin.include_role:
name: foo
vars:
bar: Hello World
...
Apply can be used to use delegate_to to run all of the tasks in the role on localhost. It almost always makes sense to also have run_once: true since you probably don't want to run the tasks on localhost more than once.
---
- hosts: all
tasks:
- ansible.builtin.include_role:
name: foo
apply:
delegate_to: localhost
run_once: true
...
apply can also be used to use in the role so that all tasks in the role are invoked using become.
---
- hosts: all
tasks:
- ansible.builtin.include_role:
name: foo
apply:
become: yes
become_user: jane.doe
...
Did you find this article helpful?
If so, consider buying me a coffee over at