IT 3110: System Automation

Ansible roles

Roles

Roles are ways of automatically loading certain vars_files, tasks, and handlers based on a known file structure. Grouping content by roles also allows easy sharing of roles with other users.

Essentially, this could be used to split a monolithic playbook into more manageable pieces.

Role Creation

An easy way to create the directory structure is

  • ansible-galaxy init <rolename>

Role Directories

My directory structure looks something like this:

    nfs
    ├── defaults
    │   └── main.yml
    ├── files
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   └── main.yml
    ├── templates
    ├── tests
    │   ├── inventory
    │   └── test.yml
    └── vars
        └── main.yml

Role Directories

  • tasks - contains the main list of tasks to be executed by the role.
  • handlers - contains handlers, which may be used by this role or even anywhere outside this role.
  • library - modules that could be used
  • defaults - default variables for the role
  • vars - other variables for the role
  • files - contains files which can be deployed via this role.
  • templates - contains templates which can be deployed via this role.
  • meta - defines some meta data for this role.

Role Tasks

You can add other YAML files in some directories. For example, you can place platform-specific tasks in separate files and refer to them in the tasks/main.yml file:

    # roles/example/tasks/main.yml
    - name: Install the correct web server for RHEL
      import_tasks: redhat.yml
      when: ansible_facts['os_family']|lower == 'redhat'
    
    - name: Install the correct web server for Debian
      import_tasks: debian.yml
      when: ansible_facts['os_family']|lower == 'debian'
    
    # roles/example/tasks/redhat.yml
    - name: Install web server
      ansible.builtin.yum:
        name: "httpd"
        state: present
    
    # roles/example/tasks/debian.yml
    - name: Install web server
      ansible.builtin.apt:
        name: "apache2"
        state: present

Role

By default, ansible looks for roles in 2 locations:

  • in a directory called roles, relative to the playbook file
  • in /etc/ansible/roles

Could also call with a fully-qualified path. (i.e. /opt/ansible/roles/common )

Role Execution

There are two ways to invoke roles. Classic way:

    ---
    - hosts: webservers
      roles:
         - common
         - webservers

Role Execution

Another way to invoke a role:

    ---
    
    - hosts: webservers
      tasks:
      - ansible.builtin.debug:
          msg: "before we run our role"
      - include_role: #or import_role
          name: example

Role Execution

Ansible only executes each role once, even if you define it multiple times, unless the parameters defined on the role are different for each definition. For example, Ansible only runs the role foo once in a play like this:

    ---
    - hosts: webservers
      roles:
        - foo
        - bar
        - foo

Role Execution

If you want the role to run more than once:

  • pass in different parameters in each role definition

      ---
      - hosts: webservers
        roles:
          - { role: foo, vars: { message: "first" } }
          - { role: foo, vars: { message: "second" } }
    

Role Execution

Another way to have the same role run twice.

    # playbook.yml
    ---
    - hosts: webservers
      roles:
        - foo
        - foo
    
    # roles/foo/meta/main.yml
    ---
    allow_duplicates: true