Creating and Managing Roles
1. Understanding Role Structure
| Directory | Description | Example |
|---|---|---|
| defaults | Default variables for the role | main.yml |
| vars | Variables for the role (not defaults) | main.yml |
| tasks | Main list of tasks to execute | main.yml |
| handlers | Handlers triggered by notify in tasks | main.yml |
| files | Static files to be copied to the target | config.json |
| templates | Template files (Jinja2) to be rendered | nginx.conf.j2 |
| meta | Role dependencies and other metadata | main.yml |
| library | Custom modules (optional) | my_module.py |
| lookup_plugins | Custom lookup plugins (optional) | my_lookup.py |
Example: Basic role directory structure
my_role/
├── defaults/
│ └── main.yml
├── vars/
│ └── main.yml
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── files/
│ └── config.json
├── templates/
│ └── nginx.conf.j2
└── meta/
└── main.yml
2. Creating Roles
Example: Basic Role Structure
my_role/
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── vars/
│ └── main.yml
├── defaults/
│ └── main.yml
├── meta/
│ └── main.yml
├── files/
├── templates/
└── library/
| Directory | Description | Usage |
|---|---|---|
| tasks/main.yml | Contains the main list of tasks to execute | Required for all roles |
| handlers/main.yml | Contains handlers that can be called by tasks | Optional |
| vars/main.yml | Contains role variables | Optional |
| defaults/main.yml | Contains default values for variables | Optional |
| meta/main.yml | Contains metadata and dependencies | Optional |
| files/ | Contains files to be copied to the target system | Optional |
| templates/ | Contains template files to be rendered | Optional |
| library/ | Contains custom modules | Optional |
Note: The
main.yml files are the entry points for each directory and must be present to define content.
3. Defining Role Tasks
| Task | Description | Parameters | Example |
|---|---|---|---|
| name | Human-readable description of the task | string |
|
| action | Module to execute (e.g., copy, file, yum) |
string |
|
| when | Conditional expression to control task execution | string |
|
| loop | Iterate over a list or set of items | list |
|
| notify | Triggers a handler after task completion | string |
|
Example: Basic Role Task
- name: "Ensure web server is running"
systemd:
name: nginx
state: started
enabled: yes
Example: Conditional Task with Loop
- name: "Install packages on Debian systems"
apt:
name: "{{ item }}"
state: present
loop:
- "nginx"
- "mysql-server"
when: ansible_os_family == "Debian"
4. Setting Role Defaults
| Property | Values | Description |
|---|---|---|
| ansible_role_defaults | dict |
Defines default values for variables that can be overridden in playbooks or other roles. |
Example: Setting Role Defaults
---
- name: Example Play using Role Defaults
hosts: all
vars:
ansible_role_defaults:
myrole:
server_port: 8080
log_level: info
roles:
- myrole
Note: Role defaults are merged with the role's
defaults/main.yml file, and can be overridden by playbook variables or other roles.
5. Setting Role Variables
| Variable Type | Scope | Example | Notes |
|---|---|---|---|
| role_defaults | Role-level | |
Set default values for variables within a role |
| vars | Role-level | |
Define variables specific to the role |
| vars_files | Role-level | |
Include external variable files for role configuration |
| defaults | Role-level | |
Define default values that can be overridden by inventory or playbook |
Example: Setting Role Variables in defaults/main.yml
---
# defaults/main.yml
app_name: "myapp"
app_port: 8080
app_user: "appuser"
app_group: "appgroup"
Example: Using Role Variables in tasks/main.yml
---
# tasks/main.yml
- name: Create app user
ansible.builtin.user:
name: "{{ app_user }}"
group: "{{ app_group }}"
- name: Start application
ansible.builtin.systemd:
name: "{{ app_name }}.service"
state: started
enabled: yes
Note: Variables defined in
defaults/main.yml can be overridden by variables set at the inventory or playbook level, following Ansible's variable precedence rules.
6. Creating Role Handlers
| Property | Description | Example |
|---|---|---|
| handlers | List of handlers defined in the role | |
Example: Basic Handler Definition
handlers:
- name: restart web server
systemd:
name: apache2
state: restarted
Example: Handler with Variable
handlers:
- name: restart {{ service_name }}
systemd:
name: "{{ service_name }}"
state: restarted
Note: Handlers are executed at the end of a play, after all tasks have completed.
Handler Best Practices
- Use handlers for actions that should only run once per play, even if triggered multiple times
- Handlers are typically used for restarting services or reloading configurations
- Define handlers in
handlers/main.ymlwithin your role directory
7. Managing Role Files
| File Type | Description | Location | Notes |
|---|---|---|---|
| main.yml | Main playbook file | roles/<role_name>/tasks/main.yml | Entry point for tasks in a role |
| vars.yml | Variable definitions | roles/<role_name>/vars/main.yml | Defines default variables for the role |
| defaults.yml | Default variable values | roles/<role_name>/defaults/main.yml | Provides default values for variables |
| handlers.yml | Event handlers | roles/<role_name>/handlers/main.yml | Defines handlers that can be called by tasks |
| meta.yml | Role metadata | roles/<role_name>/meta/main.yml | Defines dependencies and other metadata |
| templates/ | Template files | roles/<role_name>/templates/ | Contains Jinja2 template files |
| files/ | Static files | roles/<role_name>/files/ | Stores static files to be copied to hosts |
| library/ | Custom modules | roles/<role_name>/library/ | Contains custom Ansible modules |
Example: Using templates in a role
- name: Render template
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
Example: Including variables in a role
- name: Set variable in role
set_fact:
nginx_port: "{{ nginx_port | default(80) }}"
Note: Role files must be structured in a specific directory layout to be recognized by Ansible.
8. Managing Role Templates
| Property | Description | Example |
|---|---|---|
| template.src | Source file path relative to the role's templates/ directory |
config.j2 |
| template.dest | Destination path on the target host | /etc/myapp/config.conf |
| template.vars | Variables to pass into the template | { 'port': 8080, 'host': 'localhost' } |
Example: Using a Jinja2 Template in a Role
- name: Render config file from template
template:
src: config.j2
dest: /etc/myapp/config.conf
vars:
port: 8080
host: localhost
Note: Template files must be placed in the
templates/ directory of your Ansible role.
Template Variables
hostvars- Variables for specific hostsgroup_names- Names of groups the host belongs toinventory_hostname- Hostname as defined in inventory
9. Setting Role Dependencies
| Property | Description | Example |
|---|---|---|
| dependencies | List of roles that must be executed before the current role | |
Example: Role Dependencies Configuration
---
- name: Install and configure web application
hosts: webservers
roles:
- role: webapp
dependencies:
- role: common
- role: nginx
Note: Dependencies are processed in the order listed and can include tags for conditional execution.
10. Using Roles in Playbooks
| Property | Description | Example |
|---|---|---|
| roles | List of roles to include in the playbook | roles:- common- webserver |
| role | Single role to include in the playbook | roles:- name: common |
Example: Including a Role with Variables
---
- hosts: web
roles:
- name: webserver
vars:
http_port: 8080
11. Passing Variables to Roles
| Variable Type | Source | Usage | Notes |
|---|---|---|---|
| role_defaults | defaults/main.yml |
Set default values for role variables | Overrides any other variable sources |
| role_vars | vars/main.yml |
Define variables specific to the role | Available in all tasks within the role |
| role_params | tasks/main.yml |
Pass variables to tasks using vars |
Can override defaults or vars |
| host_vars | host_vars/<hostname>.yml |
Set variables for specific hosts | Higher precedence than role vars |
| group_vars | group_vars/<groupname>.yml |
Set variables for groups of hosts | Higher precedence than role vars |
Example: Passing Variables to a Role
- name: Configure web server
hosts: webservers
roles:
- role: web_server
vars:
web_port: 8080
ssl_enabled: true
Note: Variable precedence in Ansible follows a specific order. Host variables take precedence over role defaults, and task variables override all others.
12. Controlling Role Execution
| Control Option | Description | Usage |
|---|---|---|
| when | Conditionally execute a task or role based on a boolean expression | |
| delegate_to | Run a task on a different host than the one specified in the play | |
| run_once | Execute the task only once, on the first host in the inventory | |
| serial | Control how many hosts to run the task on at once | |
| max_fail_percentage | Maximum percentage of hosts that can fail before the play stops | |
Example: Using when with role execution
- hosts: all
roles:
- role: webserver
when: "ansible_facts.os_family == 'RedHat'"
Note: The
when condition can be used at any level in the playbook structure, including within roles.
Warning: Be cautious with
run_once as it may not behave as expected in complex scenarios involving multiple plays or groups.