Creating roles

Creating Reusable Code

Chapter 5

Concepts

  • what is a  role

  • when to create a role

  • how to create a role

  • Notifications and Handlers

  • Pre and Post Tasks

  • nesting of roles using include

why roles

Address Complexity
Reusability and Sharing
Modular Code

complexity

---
  - name: Base Configurations for ALL hosts
    hosts: prod:!app2
    become: true
    tasks:
      - name: create admin user
        user: name=admin state=present uid=5001

      - name: remove dojo
        user: name=dojo  state=absent

      - name: install tree
        package:  name=tree  state=present

      - name: install ntp
        package:  name=ntp   state=present

      - name: start ntp service
        service: name=ntpd state=started enabled=yes

  - name: App Server Configurations
    hosts: app
    become: true
    tasks:
      - name: create app user
        user: name=app state=present uid=5003

      - name: install git
        package:  name=git  state=present
      

playbook.yml

  • hosts definitions, properties, tasks all in one place
  • specific to one environment, can not be shared
  • difficult to reuse 
  • can quickly get out of control with increasing number of applications

modular approach

---
  - name: Base Configurations for ALL hosts
    hosts: all
    become: true
    tasks:
      - name: create admin user
        user: name=admin state=present uid=5001

      - name: remove dojo
        user: name=dojo  state=absent

      - name: install tree
        yum:  name=tree  state=present

      - name: install ntp
        yum:  name=ntp   state=present

      - name: start ntp service
        service: name=ntpd state=started enabled=yes

- name: App Server Configurations
  hosts: app
  become: true
  tasks:
    - name: create app user
      user: name=app state=present uid=5003

    - name: install git
      yum:  name=git  state=present

roles

base

apache

php

playbook.yml

Strategy : Move code related to each application/feture to its own place, call it a role

simplification

roles

base

apache

---
  - name: Base Configurations for ALL hosts
    hosts: all
    become: true
    roles:
     - base

- name: App Server Configurations
  hosts: app
  become: true
  roles:
     - apache
     - php

php

playbook.yml

  • playbook is simplified
  • modular code 
  • reusable and sharable

before

---
  - name: Base Configurations for ALL hosts
    hosts: all
    become: true
    tasks:
      - name: create admin user
        user: name=admin state=present uid=5001

      - name: remove dojo
        user: name=dojo  state=absent

      - name: install tree
        yum:  name=tree  state=present

      - name: install ntp
        yum:  name=ntp   state=present

      - name: start ntp service
        service: name=ntpd state=started enabled=yes

- name: App Server Configurations
  hosts: app
  become: true
  tasks:
    - name: create app user
      user: name=app state=present uid=5003

    - name: install git
      yum:  name=git  state=present

---
  - name: Base Configurations for ALL hosts
    hosts: all
    become: true
    roles:
     - base

- name: App Server Configurations
  hosts: app
  become: true
  roles:
     - apache
     - php

after

what

A Role is a package which contains tasks which take action along with supporting entities such as handlers, properties, files, tests and metadata

What is a Role ?

Anatomy of a role

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

actions to take , using modules

default properties/vars

role specific vars

static files to be copied to nodes

files generated dynamically

actions to take on events

ansible tests

role meta data

when

1    :    1

Role

App

Feature

When to create a  a Role ?

code organization strategies

Lets look at the strategies to organize the code better

code organization strategies

load balancers

app servers

db servers

apache

php

wp

layers = inventory groups

code organization strategies

apache

php

wp

roles

roles

create roles for each app

haproxy

postgres

roles

code organization strategies

apache

php

wp

play

play

play

create plays for each inventory group/layer

code organization strategies

apache

php

wp

play

play

play

combine  plays into a  site wide playbook

site.yml

+

+

=

how

manual

There are two ways to create roles

Using 

ansible-galaxy

Roles can be created by simply creating directories and files in  certain order

A utility which lets you generate role scaffolding

ansible galaxy

https://galaxy.ansible.com/

ansible galaxy

a library of community contributed roles

servers as a source of reference to learn best practices

no need to reinvent the wheel. Resue and share roles

# ansible-galaxy init --init-path roles/ apache
- apache was created successfully
[root@ansible chap5]# tree roles/apache/
roles/apache/
├── 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

Creating Roles with Galaxy

ansible-galaxy init --init-path roles/ apache
ansible-galaxy --help
# ansible-galaxy --help
Usage: ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...

Options:
  -h, --help     show this help message and exit
  -v, --verbose  verbose mode (-vvv for more, -vvvv to enable connection
                 debugging)
  --version      show program's version number and exit

seeking help

creating apache role

ge

Creating apache Role

ge

  • install apache2 package
    
  • centrally manage apache2.conf   and copy it to all nodes  
  • start apache2 service
    
  • whenever apache configs are updated, relevant service should be  automatically restarted
Create a role for installing and configuration apache web server on Ubuntu platform which will,

Problem Statement

ge

cd  chap6

mkdir roles

ansible-galaxy init --offline --init-path=roles  apache

Lets begin by creating a scaffolding (directory structure) for apache role

validating

# ansible-galaxy init --init-path roles/ apache
- apache was created successfully
[root@ansible chap5]# tree roles/apache/
roles/apache/
├── 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

ge

tree roles/

mapping ACTIONS to MODULES

install apache2
copy configs
and html docs
start apache2 service

actions

modules

package
service
copy

Lets now come up with the actions that we would take to achieve desired state, and start mapping it to ansible modules

writing tasks

ge

  • We need to start defining actions and its desired state  using  tasks 
  • tasks directory in roles comes with main.yml as a default task file
  • all actions can be defined in main.yml
  • however, we will create individual tasks for each action for fine grained control
  • and include it from main.yml

roles

apache

tasks

main.yml

install.yml

config.yml

service.yml

File: roles/apache/tasks/install.yml
---
  - name: install apache web server
    yum:
      name: apache2
      state: present

Installing a package

ge

File: roles/apache/tasks/service.yml
---
  - name: start apache webserver
    service:
      name: apache2
      state: started
      enabled: true

starting a service

ge

File: roles/apache/tasks/main.yml
---
# tasks file for apache
  - import_tasks: install.yml
  - import_tasks: service.yml

writing main task

ge

  • when you call a role from playbook, it includes only main.yml task file
  • if you create additional task files, the only way to have those called is by including in main.yml 
  • lets include install.yml and service.yml in main.yml for apache role
File: app.yml
---
  - hosts: app
    become: true
    roles:
      - apache

creating  playbook for app

ge

  • As per our strategy, we are going to create a playbook for each layer
  • lets begin by writing app.yml for app servers 
  • app.yml maps app servers to apply apache role
  • apache role will in turns point to main.yml 
  • main.yml will then execute all included tasks from install.yml and start.yml

roles

apache

tasks

main.yml

install.yml

service.yml

root@control:/workspace/chap6# ansible-playbook app.yml                                         
                                                                                                
PLAY [app] *********************************************************************                
                                                                                                
TASK [setup] *******************************************************************                
ok: [app1]                                                                                      
ok: [app2]                                                                                      
                                                                                                
TASK [apache : Install Apache...] **********************************************                
changed: [app1]                                                                                 
changed: [app2]                                                                                 
                                                                                                
TASK [apache : Starting Apache...] *********************************************                
changed: [app2]                                                                                 
changed: [app1]                                                                                 
                                                                                                
PLAY RECAP *********************************************************************                
app1                       : ok=3    changed=2    unreachable=0    failed=0                     
app2                       : ok=3    changed=2    unreachable=0    failed=0            
  ansible-playbook app.yml 

Apply playbook for app

ge

root@control:/workspace/chap6# ansible app -b -a "service apache2 status"                            
app2 | SUCCESS | rc=0 >>                                                                        
apache2 (pid  3565) is running...                                                                 
                                                                                                
app1 | SUCCESS | rc=0 >>                                                                        
apache2 (pid  3616) is running...                                                                 
                                
ansible app -b -a "which apache2"    

Validate

ge

root@control:/workspace/chap6# ansible app -b -a "which apache2"                                     
app2 | SUCCESS | rc=0 >>                                                                        
/usr/sbin/httpd                                                                                 
                                                                                                
app1 | SUCCESS | rc=0 >>                                                                        
/usr/sbin/httpd                                                                                 
                 
ansible app -b -a "service apache2 status"    

roles

apache

tasks

main.yml

install.yml

service.yml

files

httpd.conf

  config.yml

  • in addition to installing and starting services, we also need to copy configuration file for apache
  • to manage centrally,  files are stored in its own dedicated files  directory inside roles
  • in addition, tasks to copy the  files from inside roles to appropriate destination need to be created. Lets write  config.yml  to do this 
  • which will then be added to main.yml just like other two task files we created earlier

managing files

add files

ge

To simplify your work, sample  apache2.conf  is provided below

download and copy content of above file to roles/apache/files/apache2.conf

write tasks to copy files

ge

Lets now create config.yml to 

---
  - name: copy over httpd configs
    copy:
      src: apache2.conf
      dest: /etc/apache2/apache2.conf
      owner: root
      group: root
      mode: 0644

path: roles/apache/tasks/config.yml

restarting service on config change

ge

Config File

port = 80

port = 8080

Service

restart

notify

handler

adding a handler 

ge

roles

apache

tasks

main.yml

install.yml

start.yml

files

httpd.conf

index.html

  config.yml

handlers

main.yml

  • just like tasks and files, handlers have their own dedicated directory
  • inside which you may already find main.yml. You could add handler to restart apache here
  • handler will get triggered only when notified

adding a handler 

ge

---
# handlers file for apache
  - name: Restart apache service
    service: name=apache2 state=restarted

path: roles/apache/handlers/main.yml

adding notification 

ge

To notification, update config.yml  

---
  - name: copy over apache2 configs
    copy:
      src: apache2.conf
      dest: /etc/apache2/apache2.conf
      owner: root
      group: root
      mode: 0644
    notify: Restart apache service

path: roles/apache/tasks/config.yml

run playbook

ge

root@control:/workspace/chap6# ansible-playbook app.yml                        
                                                                               
PLAY [app:!app2] **************************************************************
*                                                                              
                                                                               
TASK [setup] ******************************************************************
*                                                                              
ok: [app1]                                                                     
                                                                               
TASK [apache : Install Apache...] *********************************************
*                                                                              
ok: [app1]                                                                     
                                                                               
TASK [apache : Starting Apache...] ********************************************
*                                                                              
ok: [app1]                                                                     
                                                                               
PLAY RECAP ********************************************************************
*                                                                              
app1                       : ok=3    changed=0    unreachable=0    failed=0    
                                                                              
ansible-playbook app.yml
  • Were the files copied ? 
  • Was the service restarted as a result of config file updates ?
  • Create a php role
  • add tasks to install php,
    libapache2-mod-php and php-mysql packages 
Exercise: Role to install PHP
  • copy following contents to /var/www/html/info.php
<?php
  phpinfo();  
?>
  • Send a notification to restart apache after installing the packages and copying the file
  • validate by visiting http://IPADDRESS:80/info.php
  • Create a Systems Role for common tasks
  • Move all tasks  in the systems.yml to this role. 
    
  • Define role nesting with dependencies/meta-data
  • Create Site Wide Playbook
Exercise : Systems Role and Sitewide Playbook

1

  • Update apache2.conf and change some configuration parameters.
  • Validate the service restarts on configuration updates by applying the sitewide playbook.
Exercise  : Update Apache Configs 

2021 Ansible Section 6: Roles

By School of Devops

2021 Ansible Section 6: Roles

Creating Reusable Code

  • 734