Create ansible role from scratch | Ansible roles example


Written By - admin
Advertisement

In this article we will create ansible role from scratch using ansible galaxy init. In our earlier article I gave you an overview on ansible role directory structure. Now we will use that directory structure to deploy a playbook with some ansible roles example.

 

Let us go step by step in this ansible roles tutorial to create ansible playbook roles from scratch. I will share two ansible role examples in this article

  1. Update /etc/motd using ansible playbook roles
  2. Configure virtual hosting for apache server using ansible playbook roles

 

Ansible will by default look for roles in the following directories

  • Current project directory
  • ~/.ansible/roles
  • /etc/ansible/roles
  • /usr/share/ansible/roles

 

Install Ansible and set up the environment

Since I have already installed and configured Ansible on my CentOS 8 environment, I will not repeat the same here.

 

Create project

Once we have our Ansible environment ready, next create a project. I will create a new project base to demonstrate ansible roles example:

[ansible@controller ~]$ mkdir base

 

Example 1: Ansible roles example to update /etc/motd

Step 1: Create ansible role - motd

[ansible@controller ~]$ mkdir roles
[ansible@controller ~]$ cd roles

Next use ansible-galaxy init command to create ansible role. We will create motd role:

[ansible@controller roles]$ ansible-galaxy init motd
- motd was created successfully

Create ansible role command was successful. You can use tree command to list the ansible role directory structure for motd:

[ansible@controller roles]$ tree motd
motd
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

8 directories, 8 files

As you see all the directories which we discussed in our last article for ansible role are created

Advertisement

 

Step 2: Create ansible tasks

Now we know we want to update /etc/motd file using ansible playbook roles so we must create tasks so we will use the main.yml file present inside tasks folder

[ansible@controller motd]$ cat tasks/main.yml
---
# tasks file for motd
- name: copy motd file
  template:
     src: templates/motd.j2
     dest: /etc/motd
     owner: root
     group: root
     mode: 0444

We have defined the template path and destination detail to update /etc/motd

 

Step 3: Create ansible template

Next we will create the template content which will be used to update /etc/motd in our ansible roles examples. I will create a new template file under templates directory using some variables:

[ansible@controller motd]$ cat templates/motd.j2
Welcome to {{ ansible_hostname }}

This file was created on {{ ansible_date_time.date }}
Go away if you have no business being here

Contact {{ system_manager }} if anything is wrong

 

Step 4: Create ansible variables

We will use defaults folder to define custom variables which is used in our template file templates/motd.j2.

[ansible@controller motd]$ cat defaults/main.yml
---
# defaults file for motd
system_manager: admin@golinuxcloud.com

 

Step 5 : Remove unwanted directories (Optional)

This step is completely optional. In this ansible roles example we will not use other directories so we are deleting them. After deleting the additional directories you can use tree command to list the directory structure of motd roles

[ansible@controller motd]$ rm -rf handlers tests vars
[ansible@controller motd]$ tree
.
├── defaults
│   └── main.yml
├── files
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
└── templates
    └── motd.j2

5 directories, 5 files

 

Step 6: Create ansible role playbook

Now after you create ansible role structure, we need a playbook file which will deploy the role to our managed hosts. I will create my playbook file motd-role.yml under base project directory.

[ansible@controller base]$ cat motd-role.yml
---
- name: use motd role playbook
  hosts: server1.example.com
  user: ansible
  become: true

  roles:
    - role: motd
      system_manager: admin@golinuxcloud.com

As you see I have only provided the roles information and no other tasks are specified in the playbook file.

 

Step 7: Deploy ansible playbook roles

After we create ansible role from scratch and playbook file, we will next deploy our ansible playbook roles to execute the motd role on our managed host.

[ansible@controller base]$ ansible-playbook motd-role.yml

PLAY [use motd role playbook] ***********************************************************************************

TASK [Gathering Facts] ******************************************************************************************
ok: [server1.example.com]

TASK [motd : copy motd file] ************************************************************************************
changed: [server1.example.com]

PLAY RECAP ******************************************************************************************************
server1.example.com        : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

In the ansible roles example our ansible deployment was successful.

 

Step 8: Verification

After ansible playbook deployment, verify the task status on your managed host which for us is server1.example.com

[root@server1 ~]# cat /etc/motd
Welcome to server1

This file was created on 2020-02-01
Go away if you have no business being here

Contact admin@golinuxcloud.com if anything is wrong

So the content from our motd file is updated properly on server1 at /etc.motd.

 

Example 2: Configure Virtual Hosting with Ansible Role

This is our second ansible roles example. This play will be operated on server2.example.com and we are going to use "vhost" role for the operation.

 

Step 1: Create Ansible Role - vhost

We will use our existing ~/base/roles/<rolename> project to create ansible roles directory structure using "vhost" role

[ansible@controller base]$ cd roles/

To create ansible role vhost use ansible-galaxy init <rolename> command as shown below:

[ansible@controller roles]$ ansible-galaxy init vhost
- vhost was created successfully

You can use tree command to check the structure of the vhost directory:

[ansible@controller roles]$ tree
.
└── vhost
    ├── defaults
    │   └── main.yml
    ├── files
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   └── main.yml
    ├── templates
    ├── tests
    │   ├── inventory
    │   └── test.yml
    └── vars
        └── main.yml

9 directories, 8 files

 

Step 2: Create ansible tasks

  • In the main.yml inside tasks folder we define the tasks to be performed
  • Install httpd using yum module
  • Start and enable the httpd service using the service module
  • Next source the vhost.conf.j2 file to destination using template module available under templates directory
[ansible@controller base]$ cat roles/vhost/tasks/main.yml
---
# tasks file for vhost
- name: install http
  yum:
    name: httpd
    state: latest
- name: start and enable httpd
  service:
    name: httpd
    state: started
    enabled: true
- name: install vhost config file
  template:
    src: vhost.conf.j2
    dest: /etc/httpd/conf.d/vhost.conf
    owner: root
    group: root
    mode: 0644

 

Step 3: Create ansible handlers

In roles we separate tasks with ansible handlers. So in this ansible roles example in handlers/main.yml we instruct ansible to restart httpd once the tasks are done

[ansible@controller base]$ cat roles/vhost/handlers/main.yml
---
# handlers file for vhost

- name: restart_httpd
  service:
     name: httpd
     state: restarted

 

Step 4: Create ansible template

Below is our virtual host configuration using variables under templates folder. The variables will be auto filled on destination names.

[ansible@controller base]$ cat roles/vhost/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>        

 

Step 5: Remove unwanted directories (Optional)

Now similar to our ansible roles example for motd, we will remove our unwanted directories.

[ansible@controller vhost]$ rm -rf defaults files tests vars

Next you can use tree command to list the remaining directories of vhost role.

[ansible@controller vhost]$ tree
.
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
└── templates

4 directories, 4 files

 

Step 6: Create post execution tasks

Also we have added post_tasks to copy index.html from localhost to destination on managed host (server2.example.com) under /var/www/html/<hostname>/
So we will create an index.html on the localhost which we want to be copied to the destination with our playbook:

[ansible@controller base]$ mkdir -p files/html

[ansible@controller base]$ echo "Welcome to this host" >> files/html/index.html

[ansible@controller base]$ cat files/html/index.html
Welcome to this host

 

Step 7: Create ansible role playbook

Now after you create ansible role structure, we need a playbook file which will deploy the role to our managed hosts. I will create apache-vhost.yml playbook file under the base project directory.

[ansible@controller base]$ cat apache-vhost.yml
---
- name: create apache vhost
  hosts: server2.example.com ## Execute on this host only
  become: true ## Perform tasks as root user

  roles:
     - vhost

  post_tasks:
     - name: install contents from local file
       copy:
         src: files/html/
         dest: "/var/www/vhosts/{{ ansible_hostname }}"
       changed_when: true  ## This is to forcefully mark a change
       notify: restart_httpd  ## Execute the handler with the name restart_httpd

 

Step 8: Deploy ansible playbook roles

After we create ansible role from scratch and playbook file, we will next deploy our ansible playbook roles to execute the vhost role on our managed host.

[ansible@controller base]$ ansible-playbook apache-vhost.yml

PLAY [create apache vhost] **************************************************************************************

TASK [Gathering Facts] ******************************************************************************************
ok: [server2.example.com]

TASK [vhost : install http] *************************************************************************************
ok: [server2.example.com]

TASK [vhost : start and enable httpd] ***************************************************************************
ok: [server2.example.com]

TASK [vhost : install vhost config file] ************************************************************************
changed: [server2.example.com]

TASK [install contents from local file] *************************************************************************
changed: [server2.example.com]

RUNNING HANDLER [vhost : restart_httpd] *************************************************************************
changed: [server2.example.com]

PLAY RECAP ******************************************************************************************************
server2.example.com        : ok=6    changed=4    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0

So looks like our ansible playbook roles has successfully executed. We can verify the same by running ansible ad-hoc commands

NOTE:

You may face issues where the handlers are not executed as part of ansible roles. Ansible will notify handler only when task is in changed state – this is on purpose to prevent unnecessary handlers execution (e.g. service restarts) on subsequent playbook runs. To fix this you can either use notify as I have used in this example or use -include: <path/of/handler/main.yml> to manually execute the file.

 

Step 9: Verification

To check if httpd service is active on our managed host server2.example.com

[ansible@controller base]$ ansible server2.example.com -a 'systemctl is-active httpd'
server2.example.com | CHANGED | rc=0 >>
active

As we see the service active, we can also check the output of vhost.conf which we had populated. Execute the below command using the controller node

[ansible@controller base]$ ansible server2.example.com -a 'cat /etc/httpd/conf.d/vhost.conf'
server2.example.com | CHANGED | rc=0 >>
# Ansible managed

<VirtualHost *:80>
        ServerAdmin webmaster@server2.example.com
        ServerName server2.example.com
        ErrorLog logs/server2-error.log
        CustomLog logs/server2-common.log common
        DocumentRoot /var/www/vhosts/server2/

        <Directory /var/www/vhosts/server2>        
                Options +Indexes +FollowSymlinks +Includes
                Order allow,deny
                Allow from all
        </Directory>
</VirtualHost>        

 

What’s Next

Next in our Ansible Tutorial we will learn about Ansible Vaults

 

References:
Red Hat Certified Engineer (RHCE) EX294: Red Hat Ansible Automation

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

6 thoughts on “Create ansible role from scratch | Ansible roles example”

  1. In your playbook there is no handler restart task was executed , I think you missed the notify after the copy, Please check once

    Reply
    • Thank you for highlighting this, I may have overlooked the output. I have updated the article with additional NOTE

      Reply

Leave a Comment