Skip to main content

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.

Example: tasks/main.yml

- name: Install Apache
  apt:
    name: apache2
    state: present

Example: meta/main.yml

dependencies:
  - { role: common, tags: ['common'] }

3. Defining Role Tasks

Task Description Parameters Example
name Human-readable description of the task string
- name: "Install Apache"
  apt:
    name: apache2
    state: present
action Module to execute (e.g., copy, file, yum) string
- name: "Create directory"
  file:
    path: /var/www/html
    state: directory
when Conditional expression to control task execution string
- name: "Install package only on Ubuntu"
  apt:
    name: nginx
    state: present
  when: ansible_distribution == "Ubuntu"
loop Iterate over a list or set of items list
- name: "Create users"
  user:
    name: "{{ item }}"
    state: present
  loop:
    - "john"
    - "alice"
notify Triggers a handler after task completion string
- name: "Restart service"
  systemd:
    name: nginx
    state: restarted
  notify: "restart web server"

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
role_defaults:
  ansible.builtin.set_fact:
    my_var: "default_value"
Set default values for variables within a role
vars Role-level
vars:
  app_port: 8080
  app_host: "localhost"
Define variables specific to the role
vars_files Role-level
vars_files:
  - vars/app_config.yml
  - vars/database.yml
Include external variable files for role configuration
defaults Role-level
defaults:
  service_name: "nginx"
  service_port: 80
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
handlers:
  - name: restart nginx
    systemd:
      name: nginx
      state: restarted

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.yml within 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 hosts
  • group_names - Names of groups the host belongs to
  • inventory_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
[
  {
    "role": "common"
  },
  {
    "role": "nginx",
    "tags": ["web"]
  }
]

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 in a Playbook

---
- hosts: all
  roles:
    - common
    - webserver

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

Example: Using Role Defaults

# defaults/main.yml in web_server role
web_port: 80
ssl_enabled: false

Example: Using Host Variables

# host_vars/web01.yml
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
- name: "Run task only if variable is set"
  command: echo "Hello"
  when: ansible_facts.os_family == "RedHat"
delegate_to Run a task on a different host than the one specified in the play
- name: "Run on localhost"
  command: whoami
  delegate_to: localhost
run_once Execute the task only once, on the first host in the inventory
- name: "Run once on first host"
  command: /usr/bin/setup.sh
  run_once: true
serial Control how many hosts to run the task on at once
- name: "Run serially"
  hosts: webservers
  serial: 2
max_fail_percentage Maximum percentage of hosts that can fail before the play stops
- name: "Allow up to 50% failures"
  hosts: all
  max_fail_percentage: 50

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.

Was this article helpful?