Ansible Roles¶
See roles in Ansible.
Roles are used to organize and reuse playbook content.
Roles are essentially a collection of tasks and their associated resources (variables,
templates, handlers, etc.) packaged together for a specific purpose.
The purpose can be something like configuring a web server or setting up a database.
They're somewhat similar to classes in object-oriented programming.
Table of Contents¶
Role Directory Structure¶
A role has a predefined structure with specific directories for different types of content.
This is what a typical role looks like:
roles/
└── myrole/
├── tasks/ # Contains the main list of tasks to execute
│ └── main.yml # Entry point for tasks
├── handlers/ # Contains handlers (triggered by tasks)
│ └── main.yml
├── templates/ # Contains Jinja2 template files
├── files/ # Contains static files to copy to remote machines
├── vars/ # Contains variable definitions (static)
│ └── main.yml
├── defaults/ # Contains default variable definitions (can be overridden)
│ └── main.yml
├── meta/ # Contains metadata about the role (dependencies, etc.)
│ └── main.yml
└── tasks/main.yml # Main entry point for the role
tasks/
: Where you define the main tasks for the role.handlers/
: Define handlers that are triggered by notify
directive in tasks
.templates/
: Store Jinja2
templates for dynamically generating files.files/
: Store static files that can be copied to remote hosts.vars/
: Define variables that are specific to the role.defaults/
: Define default values for variables (lowest precedence).meta/
: Include metadata about the role (like depenencies).
Creating and Using a Role¶
Creating a Role¶
You can manually create the directory structure.
You can also use the ansible-galaxy
command:
ansible-galaxy init roles/myrole # Initialize a new role
myrole
under the
roles
directory.
Defining Role Tasks¶
The file roles/myrole/tasks/main.yml
is used to define tasks for the role.
- name: Install NGINX
apt:
name: nginx
state: present
update_cache: yes
- name: Enxure NGINX is started
service:
name: nginx
state: started
enabled: yes
Using a Role in a Playbook¶
Use the name of the role in a playbook using the roles
key.
- name: Example Playbook play
hosts: webserver
roles:
- myrole
myrole
role.This runs the tasks and resources defined in the role (
roles/myrole
).
NOTE: If you have a playbook that you're inheriting roles in (as above), any tasks in that playbook will always happen after roles are executed.
If you need tasks to happen before roles, usepre_tasks
instead oftasks
.
Where you can Use Roles¶
- Playbooks
- hosts: webservers roles: - myrole - otherrole
- Role dependencies
- Roles can depend on other roles. Define dependencies in
roles/myrole/meta/main.yml
dependencies: - role: common - role: firewall - role: otherrole
- Roles can depend on other roles. Define dependencies in
- In the
include_role
task. You can include roles dynamically in a task.
- name: Include the myrole role include_role: name: myrole
- In collections. Roles can be part of an Ansible collection.
- This can make them easy to distribute and reuse.
Example of Using a Role in Ansible¶
Directory Structure¶
This is the directory structure for the example:
myproject/
├── roles/
│ └── nginx/
│ ├── tasks/
│ │ └── main.yml
│ ├── handlers/
│ │ └── main.yml
│ ├── templates/
│ │ └── nginx.conf.j2
│ ├── files/
│ ├── vars/
│ │ └── main.yml
│ ├── defaults/
│ │ └── main.yml
│ ├── meta/
│ │ └── main.yml
├── inventory
└── site.yml
Playbook: site.yml
¶
- hosts: webservers
roles:
- nginx
-
Indicates the start of the play.This will inherit and run all the
tasks
in the nginx
role.All tasks will be run on the
webservers
hosts defined in the inventory.yml
Role tasks: roles/nginx/tasks/main.yml
¶
- name: Install NGINX
apt:
name: nginx
state: present
- name: Deploy NGINX configuration
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: 0644
- name: Start and Enable NGINX
service:
name: nginx
state: started
enabled: yes
Basic Role Usage¶
-
Create a directory called
roles
:
mkdir roles cd roles
-
Then initialize a role:
Then a bunch of directories are created.ansible-galaxy init <role_name>
This can be overwhelming at first but if you just need to run tasks then you only need look at thetasks
directory. -
Look in the
<role_name>/tasks/
directory for a file calledmain.yml
.
Put any tasks you want to run in that file. -
Then, in your playbook:
All the tasks in that- name: Name of the playbook hosts: your-hosts roles: - role_name
main.yml
file should be run.
If you need to use variables, templates, etc., there are other directories where you put those (like <role_name>/vars
for variables).
Using Variables to Assign Roles Dynamically¶
If you want to assign roles dynamically based on host variables, you can do:
- name: Apply roles based on host variables
hosts: all
roles:
- "{{ assigned_roles }}"
Then, in your inventory:
[web_servers]
web1 ansible_host=192.168.1.10 assigned_roles=["webserver_role"]
web2 ansible_host=192.168.1.11 assigned_roles=["webserver_role"]
[db_servers]
db1 ansible_host=192.168.1.20 assigned_roles=["database_role"]
db2 ansible_host=192.168.1.21 assigned_roles=["database_role"]
assigned_roles
variable will be used to determine which roles to run on each given host.
Variables with Roles¶
Specify variables to use inside roles in the role-name/vars/main.yml
file.
When defining variables inside a role (roles/role_name/vars/main.yml
), those
variables will only be available inside the role itself. They will not be
accesible in a playbook that calls that roll.
If you need to access variables inside the main playbook, use set_fact
or define
the variable in either the inventory, the playbook vars
section, or a role default.
Example vars/main.yml
:
# roles/role-name/vars/main.yml
my_var: "This is the value of the variable"
some_number: 2
These vars will then be available anywhere inside the role role-name
:
- tasks/
- handlers/
- templates/
- files/
- meta/
Conditionally Calling Roles¶
You can set up conditions for roles in playbooks.
To do this, you specify a dictionary inline in the roles section.
roles:
- role1
- role2
- role3
- { role: role4, when: myvar | default(false) == true }
- role5
role4
.The
role4
role will only be run when the variable myvar
is true
. We're using
a jinja2 filter to make it default to false
if it's not defined.