PolarSPARC

Introduction to Ansible - Part 4


Bhaskar S 07/14/2018


Overview

In Part 3 of the series, we continued to explore additional features of Ansible Playbooks, including error handling.

In this final part, we wrap the series by exploring roles in Ansible. A role organizes an Ansible playbook into a well-defined structure consisting of various directories and files.

This allows for the simplification and reuse of the various parts of an Ansible playbook.

Hands-on with Ansible Roles

Ansible roles have names. For our example, we will use the name ngsqpy. The directory and file structure for the role will reside in the directory called roles/ngsqpy.

To initialize an Ansible role, we will use the ansible-galaxy command.

To create the directory and file structure for the role ngsqpy, execute the following commands:

$ cd /home/alice/Ansible

$ mkdir roles

$ cd /home/alice/Ansible/roles

$ ansible-galaxy init ngsqpy

The following would be a typical output:

Output.1

- ngsqpy was created successfully

Now, execute the following command to list the directory and file structure for the role ngsqpy:

$ ls -lR

The following would be a typical output:

Output.2

drwxrwxr-x 10 alice alice 4096 Jul 14 16:14 ngsqpy

./ngsqpy:
total 36
drwxrwxr-x 2 alice alice 4096 Jul 14 16:14 defaults
drwxrwxr-x 2 alice alice 4096 Jul 14 16:14 files
drwxrwxr-x 2 alice alice 4096 Jul 14 16:14 handlers
drwxrwxr-x 2 alice alice 4096 Jul 14 16:14 meta
-rw-rw-r-- 1 alice alice 1328 Jul 14 16:14 README.md
drwxrwxr-x 2 alice alice 4096 Jul 14 16:14 tasks
drwxrwxr-x 2 alice alice 4096 Jul 14 16:14 templates
drwxrwxr-x 2 alice alice 4096 Jul 14 16:14 tests
drwxrwxr-x 2 alice alice 4096 Jul 14 16:14 vars

./ngsqpy/defaults:
total 4
-rw-rw-r-- 1 alice alice 30 Jul 14 16:14 main.yml

./ngsqpy/files:
total 0

./ngsqpy/handlers:
total 4
-rw-rw-r-- 1 alice alice 30 Jul 14 16:14 main.yml

./ngsqpy/meta:
total 4
-rw-rw-r-- 1 alice alice 1777 Jul 14 16:14 main.yml

./ngsqpy/tasks:
total 4
-rw-rw-r-- 1 alice alice 27 Jul 14 16:14 main.yml

./ngsqpy/templates:
total 0

./ngsqpy/tests:
total 8
-rw-rw-r-- 1 alice alice 11 Jul 14 16:14 inventory
-rw-rw-r-- 1 alice alice 64 Jul 14 16:14 test.yml

./ngsqpy/vars:
total 4
-rw-rw-r-- 1 alice alice 26 Jul 14 16:14 main.yml

Those with curious eyes may notice all the yaml files with the extension .yml, which is perfectly fine.

The roles/ngsqpy/README.md will contain the description for this Ansible playbook.

The roles/ngsqpy/meta/main.yml file is used to define the meta data such as, the author, date, version, dependencies, etc., for this Ansible playbook.

The roles/ngsqpy/defaults/main.yml file is used to define variables that can be overridden for this Ansible playbook.

The roles/ngsqpy/vars/main.yml file is used to define variables that *SHOULD NOT* be overridden for this Ansible playbook.

The roles/ngsqpy/tasks/main.yml file is used to define all the tasks to be executed for this Ansible playbook.

The roles/ngsqpy/handlers/main.yml file is used to define all the handler tasks to be executed for this Ansible playbook.

The directory roles/ngsqpy/files holds all the files that need to be uploaded to the target host(s) for this Ansible playbook.

The directory roles/ngsqpy/templates holds all the template files with variables that need to be uploaded to the target host(s) for this Ansible playbook.

First, create and save a simple html file called index.html in the directory roles/ngsqpy/files with the following contents:

index.html
<html>
    <head><title>Welcome to NGINX (via Ansible Roles)</title></head>
    <body>
        <h3 align='center'>
            <font color='blue'>Welcome to NGINX (via Ansible Roles)</font>
        </h3>
    </body>
</html>

Second, create and save a playbook file called playbook-8.yaml with the following contents in the directory /home/alice/Ansible:

playbook-8.yaml
---
- name: Setup nginx, sqlite, and python-sqlite
  hosts: "{{ target_host }}"
  become: yes
  roles:
  - ngsqpy

Notice the use of the roles clause in the above playbook. It takes a list of role names, but in our case we just have one, namely, ngsqpy.

Third, modify and save the file roles/ngsqpy/meta/main.yml with the following:

roles/ngsqpy/meta/main.yml
---
galaxy_info:
  author: Bhaskar S
  description: Playbook to install nginx, sqlite, and python-sqlite
  company: polarsparc.com

  license: GPLv2

  min_ansible_version: 1.2

  #
  # platforms is a list of platforms, and each platform has a name and a list of versions.
  #
  platforms:
  - name: Debian

  galaxy_tags: []

dependencies: []

Fourth, modify and save the file roles/ngsqpy/defaults/main.yml with the following:

roles/ngsqpy/defaults/main.yml
---
# defaults file for ngsqpy

target_host: host2

Fifth, modify and save the file roles/ngsqpy/vars/main.yml with the following:

roles/ngsqpy/vars/main.yml
---
# vars file for ngsqpy

custom_html: "index.html"

Sixth, modify and save the file roles/ngsqpy/tasks/main.yml with the following:

roles/ngsqpy/tasks/main.yml
---
# tasks file for ngsqpy

- name: Install nginx
  apt: name=nginx state=present
  when: ansible_os_family == "Debian"
    
- name: Start nginx
  service: name=nginx enabled=yes state=started
  notify: restart nginx

- name: Customize nginx index.html
  copy:
    src={{ custom_html }}
    dest=/var/www/html/index.html
    mode=0644
  notify: restart nginx

- name: Install debian packages
  apt: name={{ item }} state=present
  when: ansible_os_family == "Debian"
  with_items:
  - sqlite
  - python-sqlite

Finally, modify and save the file roles/ngsqpy/handlers/main.yml with the following:

roles/ngsqpy/handlers/main.yml
---
# handlers file for ngsqpy

- name: restart nginx
  service: name=nginx state=restarted

To check the validity of the above playbook playbook-8.yaml, execute the following command:

$ ansible-playbook playbook-8.yaml --syntax-check

The following would be a typical output:

Output.3

playbook: playbook-8.yaml

To test the above playbook playbook-8.yaml, execute the following command:

$ ansible-playbook playbook-8.yaml

The following would be a typical output:

Output.4

PLAY [Setup nginx, sqlite, and python-sqlite] **************************************************************************************

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

TASK [ngsqpy : Install nginx] ******************************************************************************************************
ok: [192.168.100.12]

TASK [ngsqpy : Start nginx] ********************************************************************************************************
ok: [192.168.100.12]

TASK [ngsqpy : Customize nginx index.html] *****************************************************************************************
changed: [192.168.100.12]

TASK [ngsqpy : Install debian packages] ********************************************************************************************
changed: [192.168.100.12] => (item=[u'sqlite', u'python-sqlite'])

RUNNING HANDLER [ngsqpy : restart nginx] *******************************************************************************************
changed: [192.168.100.12]

PLAY RECAP *************************************************************************************************************************
192.168.100.12             : ok=6    changed=3    unreachable=0    failed=0

Open a browser and access the URL http://192.168.100.12. The following is an illustration:

Ansible Browser (2)
Browser (2)

We have barely scratched the surface of Ansible and yet we get a sense of its power.

References

Introduction to Ansible - Part 3

Introduction to Ansible - Part 2

Introduction to Ansible - Part 1

Official Ansible Documentation



© PolarSPARC