10. Roles

10.1. About Roles

  • roles organize content like tasks, handlers, templates and files

  • a way to encapsulate tasks and properties for reuse

  • the directory name is also the rolename

  • the path, where Ansible searchs for roles is configurable roles_path

  • the default role path is roles

  • two main purposes for roles

    • run once
    • parameterized

Hint

If you write the same tasks in multiple playbooks -> create a role.

10.2. Directory structure

  • The directory structure of roles is defined
  • Ansible loads the main.yml file of the directories defaults, handlers, meta, tasks and vars
  • the folders are optional, you don’t have to define all the directories
.
├── README.md                 <- Role description like usage, summary, variables, etc.
├── defaults                  <- Default lower priority variables, easy override by group_vars, etc.
│   └── main.yml
├── files                     <- Files picked up by copy/script module
│   └── docker-apt-key.gpg
│   └── foo.sh
├── handlers                   <- Handler defintions for notify tasks
│   └── main.yml
├── meta                       <- Meta definiontions like dependencies
│   └── main.yml
├── tasks                      <- Task files for this role
│   ├── main.yml
│   └── redhat.yml
├── templates                  <- Files picked up by template module
│   ├── debian
│   │   └── docker.conf.j2
│   └── redhat
│       ├── docker.conf.j2
│       └── docker.repo.j2
└── vars                      <- Role variables, not made for override
    ├── Debian.yml
    └── RedHat.yml

Hint

You can use the init option of ansible-galaxy to initialize a role structure for a new role: ansible-galaxy init rolename

10.3. Create the first role

  • Create your role folder apache2
  • Create a sub-folder called tasks
  • Create a file
  • Start the YAML ---
  • Add your first task
  • Save the file as main.yml
# main.yml
---
- name: install apache2
  apt:
    name: apache2
    state: latest

Hint

Create your role step-by-step, not all tasks at once.

10.3.1. Integrate Roles in Playbooks

  • Create a new playbook
  • Use roles: instead of tasks:
  • Add your rolename as list item
  • Save the file as apache2-role.yml
  • Run the playbook ansible-playbook apache2-role.yml
# file: apache2-role.yml
---
- hosts: web1.pascal.lab
  roles:
    - apache2

10.4. Handlers

  • is a special task and the name is important and has to be unique
  • triggered / notified after a change of a task
  • will run at the end of a play, but only once
# file: tasks/main.yml
- name: configure apache
  template:
    src: template.j2
    dest=/etc/foo.conf
  notify:
    - restart apache
# file: handlers/main.yml
---
- name: restart apache
  service:
    name: apache
    state: restarted

Hint

If a handler is triggered, but another task fails, the handler will not run! See Flush Handlers

Important

Notify handlers are always run in the same order they are defined, not in the order listed in the notify-statement!

10.4.1. Listen on handlers

Since Ansible 2.2, handlers can also listen to generic topics, and tasks can notify those topics. The handler can be used alone or together in the group.

# combine the handler memcached and apache as "restart web services"
    handlers:
        - name: restart memcached
          service: name=memcached state=restarted
          listen: "restart web services"

        - name: restart apache
          service: name=apache state=restarted
          listen: "restart web services"

    tasks:
        - name: restart everything
          command: echo "this task will restart the web services"
          notify:
            "restart web services"
            #- restart apache
            #- restart memcached

10.4.2. Flush Handlers

  • if you need to flush all handler commands immediately, use meta: flush_handlers
- name: exectue now all triggered handlers
  meta: flush_handlers

10.5. Role Dependencies

  • you can define a role dependency
  • defined in meta/main.yml
  • contains a list of roles and optional parameters
  • will run before the original role
# file: meta/main.yml - short form
---
dependencies:
  - ntp

# file: meta/main.yml - needed with aditional arguments
---
dependencies:
  - role: ntp
  • conditionals can also be used for dependencies
# file: meta/main.yml
---
dependencies:
  - role: ntp
    when: ansible_os_family == "Debian"

Important

By default - if another role also lists a role dependency it will not be run again. To change this behaviour check out allow_duplicates: yes.

10.6. Run Order

  • Any pre_tasks defined in the play.
  • Any handlers triggered so far will be run.
  • Each role listed in roles will execute in turn. Any role dependencies defined in the roles meta/main.yml will be run first, subject to tag filtering and conditionals.
  • Any tasks defined in the play.
  • Any handlers triggered so far will be run.
  • Any post_tasks defined in the play.
  • Any handlers triggered so far will be run.

10.7. +Role Variables

Requirement: Variable chapter

10.7.1. Role Defaults

  • Role default variables allow you to set default variables
  • defaults/main.yml file in your role directory
  • variables will have the lowest priority and can be easily overridden

Hint

It’s recommended to prefix your role variables with <rolename>_<variablename>.

Important

Use default variables to ensure the reuse of a role without specify additional variables.

10.7.2. Role Variables

  • To ensure a role variable is absolutely used in that role and not overwritten
  • vars/main.yml file in your role directory

10.8. +Parameterized Roles

Requirement: Variable chapter

  • you can pass a value as a parameter to the role
  • the parameter will overwrite a default value
  • it’s not mandatory to have a default value!
# example in a playbook
---
- hosts: webservers
  roles:
    - role: app_instance
      dir: /opt/app1
      app_port: 8080
    - role: app_instance
      dir: /opt/app2
      app_port: 8081