Ansible: Roles

Ansible_Logo

Roles is a feature provided by Ansible were once a standardized directory structure is created, you can automatically load related vars, files, tasks, handlers, and other Ansible artifacts. Using roles we have opportunities to reuse code from playbooks that you wrote previously. We can copy a role from project to project by copying the directory, then calling the role within a play. Also, a well planned role can take variables from the playbook that is calling the role. It is a collection of YAML task files and supporting items arranged in a specific structure.

Below is an example of know directory structure of role:

ansible-roles

 

In the above directory structure, the files subdirectory contains fixed content files and the templates subdirectory contains templates such as one in Jinja format, etc that the role can deploy.

You can create the directory structure and files needed for a new role by using standard Linux
commands, or alternatively we can use command-line utilities such as ansible-galaxy to automate the process of new role
creation.

The value associated with any variable presentin a role’s defaults directory is overwritten if that same
variable is defined:

• In an inventory file
• In a playbook

The main.yml file in meta subdirectory in a role directory structure specifies information about the author, license, compatibility, and dependencies for the module.

Role dependencies enables a role to include other roles as dependencies.

Ansible Galaxy is a free site for downloading all kinds of community-developed Ansible roles, and can thus speed-up your automation projects.

The ansible-galaxy client tool allows you to download roles from Ansible Galaxy and provides an excellent default framework for creating your own roles.

The below comment creates a role for myhost

[root@centos9vm ~]# ansible-galaxy init roles/myvhost

[root@centos9vm ~]# ls -l myvhost/

==== ==
total 4
drwxr-xr-x. 2 root root 22 Apr 17 14:21 defaults
drwxr-xr-x. 2 root root 6 Apr 17 14:21 files
drwxr-xr-x. 2 root root 22 Apr 22 17:40 handlers
drwxr-xr-x. 2 root root 22 Apr 17 14:21 meta
-rw-r–r–. 1 root root 1328 Apr 17 14:21 README.md
drwxr-xr-x. 2 root root 22 Apr 22 22:33 tasks
drwxr-xr-x. 2 root root 27 Apr 22 21:59 templates
drwxr-xr-x. 2 root root 39 Apr 17 14:21 tests
drwxr-xr-x. 2 root root 22 Apr 17 14:21 vars

==== =

Let us create a yml file that creates 3 task under the myvhost/tasks folder. One is to install httpd, another to start httpd, and creates a config file in the managed node using template.

[root@centos9vm roles]# cat myvhost/tasks/main.yml

==== ===
– – –
# tasks file for myvhost
– name: Ensure httpd is installed
   ansible.builtin.dnf:
      name: httpd
      state: latest

– name: Start httpd service
   ansible.builtin.service:
      name: httpd
      state: started
      enabled: true

– name: vhost file is installed
   ansible.builtin.template:
      src: vhost.conf.j2
      dest: /etc/httpd/conf.d/vhost.conf
      owner: root
      group: root
      mode: 0644
   notify: Restart httpd

=== ===

If we notice in the above file, we have a task to use “vhost.conf.j2“, but have not provided a full path of the jinja file. As we are using roles, ansible will search for the file in the “template” directory created.

[root@centos9vm roles]# cat myvhost/templates/vhost.conf.j2

===== ====
# {{ ansible_managed }}

<VirtualHost *:80>
ServerAdmin webmaster@{{ ansible_fqdn }}
ServerName {{ ansible_fqdn }}
ErrorLog logs/{{ ansible_hostname }}-error.log
CustomLog logs/{{ ansible_hostname }}-common.log common
DocumentRoot /var/www/vhosts/{{ ansible_hostname }}/
<Directory /var/www/vhosts/{{ ansible_hostname }}/>
Options +Indexes +FollowSymlinks +Includes
Order allow,deny
Allow from all
</Directory>
</VirtualHost>

===== ===

As we can notice in the first yml file “myvhost/tasks/main.yml” the last task calls a handler named “Restart httpd“. The expectancy is that role will search for the handlers in the “handlers” directory.

[root@centos9vm roles]# cat myvhost/handlers/main.yml

===== ====
– – –
# handlers file for myvhost

– name: Restart httpd
   ansible.builtin.service:
   name: httpd
   state: restarted

===== ===

Now let us tie and execute all these using role feature, by creating a playbook.

[root@centos9vm roles]# cat use-vhost-role.yml

==== === ==
– – –
– name: Use vhost role playbook
   hosts: 192.168.48.129
   pre_tasks:
      – name: pre_tasks message
         ansible.builtin.debug:
            msg: ‘Ensure web server configuration.’

   roles:
      – myvhost

   post_tasks:

   – name: post_tasks message
      ansible.builtin.debug:
         msg: ‘Web server is configured.’

=== === ==

If we notice above the roles block calls myhost role, which in turn will execute tasks from “tasks” folder in the directory structure.

Now let us run the playbook and see the results.

[root@centos9vm ~]# ansible-navigator run -m stdout use-vhost-role.yml

==== ======

PLAY [Use vhost role playbook] *************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.48.129]

TASK [pre_tasks message] *******************************************************
ok: [192.168.48.129] => {
“msg”: “Ensure web server configuration.”
}

TASK [myvhost : Ensure httpd is installed] *************************************
changed: [192.168.48.129]

TASK [myvhost : Start httpd service] *******************************************
changed: [192.168.48.129]

TASK [myvhost : vhost file is installed] ***************************************
changed: [192.168.48.129]

RUNNING HANDLER [myvhost : Restart httpd] **************************************
changed: [192.168.48.129]

TASK [HTML content is included] ************************************************
ok: [192.168.48.129]

TASK [post_tasks message] ******************************************************
ok: [192.168.48.129] => {
“msg”: “Web server is configured.”
}

PLAY RECAP *********************************************************************
192.168.48.129 : ok=8 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Roles from External Content Sources

We can deploy roles if needed from external content sources such as from Git repositories or Ansible Galaxy.

role may be pulled from a git repository, or even downloaded as a tar achieve downloadable from some source.

A public library of Ansible content is available at https://galaxy.ansible.com[Ansible Galaxy]. It is written by several Ansible administrators and users. The ansible-galaxy is used to download and use these roles.

If you have a playbook that must have specific roles installed, you can create “requirements.yml” file in the roles folder in the project directory that specifies which roles are needed. In this case the ansible-galaxy command should be run before you run ansible-navigator to install those roles in your project’s roles directory.

Few examples of “requirements.yml” are as follows:

[root@centos9vm ~]# cat roles/requirements.yml

===== ==

– – –
– src: https://git.example.com/someuser/someuser.myrole
   scm: git
   version: “1.5.0”

==== ==

[root@centos9vm ~]# ansible-galaxy role install -r roles/requirements.yml -p roles

===== ==
Starting galaxy role install process
– downloading role from https://git.example.com/someuser/someuser.myrole
– extracting myrole to /home/user/project/roles/someuser.myrole
– someuser.myrole (1.5.0) was installed successfully

==== ===

Examples of “requirements.yml” to download tar files are as follows:

=== ===

– src: file:///opt/local/roles/tarrole.tar
   name: tarrole

– src: https://www.example.com/role-archive/someuser.otherrole.tar
   name: someuser.otherrole

==== ===

The command to list the roles downloaded from Ansible Galaxy is as follows:

[root@centos9vm pre-exam]# ansible-galaxy list

==== ===
# /usr/share/ansible/roles
– linux-system-roles.fapolicyd, (unknown version)
– linux-system-roles.firewall, (unknown version)
– linux-system-roles.gfs2, (unknown version)
– linux-system-roles.ha_cluster, (unknown version)

.
.
.

======

If any dowloaded and installed role is stores in a specific folder, then you can run the command with -p switch as below:

[root@centos9vm role-galaxy]# ansible-galaxy list -p system-storage/

===== =
# /root/role-galaxy/system-storage
– rhel-system-roles.storage, (unknown version)
# /usr/share/ansible/roles
– linux-system-roles.fapolicyd, (unknown version)
– linux-system-roles.firewall, (unknown version)
– linux-system-roles.gfs2, (unknown version)
– linux-syst

Searching Roles from Ansibe-Galaxy
======*******======

We can search for roles from Ansible Galaxy using the following command.

[root@centos9vm ~]# ansible-galaxy search ‘storage’

======= ==

Found 42 roles matching your search:

Name Description
—- ———–
Akrog.storage Storage management and consumption
ashleykleynhans.ovirt_storage_domain Ansible role to get a list of oVirt storage domains through the oVirt REST API, and return the name of the sto>
linux-system-roles.storage Configure volumes and filesystems
.
.
.

======= ===

Information regarding a role can be found using the following command:

[root@centos9vm ~]# ansible-galaxy info linux-system-roles.storage
====== ====

Role: linux-system-roles.storage
description: Configure volumes and filesystems
commit: bd70d66ac8188db09b183e7e9b0f86eec8412b10
====== ====

The above role can be downloaded using the requirements.yml file

[root@centos9vm ~]# cat pre-exam/roles/requirements.yml

====== ==
– – –
– src: linux-system-roles.storage

==== ===

[root@centos9vm ~]# ls pre-exam/roles/

[root@centos9vm ~]# ansible-galaxy role install -r roles/requirements.yml -p pre-exam/roles/

====
Starting galaxy role install process
– downloading role ‘storage’, owned by linux-system-roles
– downloading role from https://github
====

[root@centos9vm ~]# ls -lA pre-exam/roles/
total 8
drwxr-xr-x. 12 root root 4096 Jun 24 02:53 linux-system-roles.storage
-rw-r–r–. 1 root root 38 Jun 24 02:53 requirements.yml
==== ===