Hello!
So what is a role in Ansible? Roles are a logical organization of Ansible code. For example, you can create a role that will install a MySQL database, put it in a separate repository, and make it publicly available or shared with other teams, and everyone should be able to use it
Create a Role
So how to create a role? You can create all the necessary files and folders manually or use the command ansible-galaxy role init ROLE_NAME
.
ansible-galaxy role init roles/httpd
- Role roles/httpd was created successfully
I specify roles/httpd for ansible to create the roles
folder. If roles/ is not specified, the role will be created in the folder where the command was executed.
$ tree roles
roles
└── httpd
├── README.md
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
9 directories, 8 files
What is inside the roles/httpd folder?
- defaults - here are the parameters that have the lowest priority, that is, the default values of the parameters that can then be overwritten.
- files - static files required for the role
- handlers - handlers, this is code that is always executed at the very end, under certain conditions. For example, restart the service if the configuration file has changed.
- meta - meta-information about the role. Title, version, author, etc
- tasks - here are the tasks that will be performed by Ansible
- templates - a place for files that will be dynamically generated using jinja2
- tests - tests
- vars - parameters that have a higher priority than the default
The main folder in which we will work tasks. Our role will install httpd, so in main.yml we will add the code that will install httpd depending on the OS.
- name: Install apache on Redhat
ansible.builtin.yum:
name: httpd
state: latest
become: yes
when: ansible_facts['os_family'] == "RedHat"
- name: Install apache on Debian
ansible.builtin.apt:
name: apache2
state: latest
become: yes
when: ansible_facts['os_family'] == "Debian"
After running the playbook, the httpd package will be installed but not started. To start it and enable automatic start after OS restart, we will use the service module
- name: Start service httpd, if not started
ansible.builtin.service:
name: apache2
state: started
enabled: yes
become: yes
when: ansible_facts['os_family'] == "Debian"
- name: Start service httpd, if not started
ansible.builtin.service:
name: httpd
state: started
enabled: yes
become: yes
when: ansible_facts['os_family'] == "RedHat"
Now ansible will start the httpd service on the server. Let’s add the index.html page using a template. To do this, I will create an index.html.j2 file with the following content in the templates folder
<b>Hello {{ user_name }}!</b>
Where {{ user_name }}
is an ansible parameter that will be inserted into the generated file. But for this, you need to create a parameter. I will create it in defaults/main.yml.
user_name: Maksym
And finally, there is a task that will generate the file. I will add it to tasks/main.yml.
- name: Generate index.html
template:
src: index.html.j2
dest: /var/www/html/index.html
become: true
We can also use handlers. For example, if you want httpd to restart every time index.html is updated. To do this, I will add the following to handlers/main.yml
- name: Restart service httpd Debian
ansible.builtin.service:
name: apache2
state: restarted
become: yes
when: ansible_facts['os_family'] == "Debian"
- name: Restart service httpd Redhat
ansible.builtin.service:
name: httpd
state: restarted
become: yes
when: ansible_facts['os_family'] == "RedHat"
This is similar to the code that start httpd in the tasks folder. But this code will be called only when someone notifies handlers to run, and in our case, it will be called by creating index.html. In the code where we create index.html, we need to add a handler call.
- name: Generate index.html
template:
src: index.html.j2
dest: /var/www/html/index.html
become: true
notify:
- Restart service httpd Debian
- Restart service httpd Redhat
Here I am calling two handlers, but only one will actually be executed depending on the OS.
Now the role can be used. To do this, in our main main.yml we can specify the role which we are going to use. But without roles/ in the name.
---
- name: Configure webserver
hosts: web
gather_facts: true
roles:
- httpd
main.yml located outside of roles folders. This is what the final file structure looks like
$ tree ansible
ansible
├── inventory
├── main.yml
└── roles
└── httpd
├── README.md
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
│ └── index.html.j2
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
10 directories, 11 files
And the result
$ ansible-playbook -i inventory main.yml
PLAY [Configure webserver] *************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************
ok: [44.201.242.83]
TASK [httpd : Install apache on redhat] ************************************************************************************
changed: [44.201.242.83]
TASK [httpd : Start httpd] *************************************************************************************************
changed: [44.201.242.83]
TASK [httpd : Generate index.html] *****************************************************************************************
changed: [44.201.242.83]
RUNNING HANDLER [httpd : Restart httpd] ************************************************************************************
changed: [44.201.242.83]
PLAY RECAP *****************************************************************************************************************
44.201.242.83 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Ansible galaxy
The Ansible community has many great roles created. You can find them at ansible galaxy. For example, after entering httpd
in the search, I found a role that installs httpd. Here you can read the role documentation and instructions on how to download it.
This would normally be ansible-galaxy install ROLE_NAME
$ ansible-galaxy install buluma.httpd
Starting galaxy role install process
- downloading role 'httpd', owned by buluma
- downloading role from https://github.com/buluma/ansible-role-httpd/archive/1.0.9.tar.gz
- extracting buluma.httpd to /home/maksym/.ansible/roles/buluma.httpd
- buluma.httpd (1.0.9) was installed successfully
Now I can specify this role in main.yml
---
- name: Configure webserver
hosts: web
gather_facts: true
become: true
roles:
- buluma.httpd
ansible-playbook -i inventory main.yml
PLAY [Configure webserver] *************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************
ok: [44.201.242.83]
TASK [buluma.httpd : Test if httpd_servername is set correctly] ************************************************************
ok: [44.201.242.83 -> localhost]
TASK [buluma.httpd : Test if httpd_port is set correctly] ******************************************************************
ok: [44.201.242.83 -> localhost]
TASK [buluma.httpd : Test if https_ssl_enable is set correctly] ************************************************************
ok: [44.201.242.83 -> localhost]
TASK [buluma.httpd : Test if httpd_ssl_servername is set correctly] ********************************************************
ok: [44.201.242.83 -> localhost]
TASK [buluma.httpd : Test if httpd_ssl_port is set correctly] **************************************************************
ok: [44.201.242.83 -> localhost]
TASK [buluma.httpd : Test if httpd_locations is set correctly] *************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if item in httpd_locations is set correctly] *****************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if httpd_vhosts is set correctly] ****************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if item in httpd_vhosts is set correctly] ********************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if item.create_docroot in httpd_vhosts is set correctly] *****************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if item.serveralias in httpd_vhosts is set correctly] ********************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if httpd_directories is set correctly] ***********************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if item.name in httpd_directories is set correctly] **********************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if item.options in httpd_directories is set correctly] *******************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if item.allow_override in httpd_directories is set correctly] ************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Test if httpd_remove_example is set correctly] ********************************************************
ok: [44.201.242.83 -> localhost]
TASK [buluma.httpd : Install apache httpd] *********************************************************************************
ok: [44.201.242.83]
TASK [buluma.httpd : Modify selinux settings] ******************************************************************************
skipping: [44.201.242.83] => (item=httpd_can_network_connect)
TASK [buluma.httpd : Allow connections to custom port] *********************************************************************
skipping: [44.201.242.83] => (item=80)
skipping: [44.201.242.83] => (item=443)
TASK [buluma.httpd : Configure httpd] **************************************************************************************
changed: [44.201.242.83]
TASK [buluma.httpd : Install ssl packages] *********************************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Place configuration] **********************************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Configure redirect from http to https] ****************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Enable modules] ***************************************************************************************
skipping: [44.201.242.83] => (item=proxy)
skipping: [44.201.242.83] => (item=proxy_http)
TASK [buluma.httpd : Configure locations] **********************************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Create docroot] ***************************************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Configure vhosts] *************************************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Configure ports] **************************************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Create directories] ***********************************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Configure directories] ********************************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Flush handlers] ***************************************************************************************
RUNNING HANDLER [buluma.httpd : Test httpd configuration validity] *********************************************************
ok: [44.201.242.83]
RUNNING HANDLER [buluma.httpd : Restart httpd] *****************************************************************************
changed: [44.201.242.83]
TASK [buluma.httpd : Removing default html] ********************************************************************************
skipping: [44.201.242.83]
TASK [buluma.httpd : Start and enable httpd] *******************************************************************************
ok: [44.201.242.83]
PLAY RECAP *****************************************************************************************************************
44.201.242.83 : ok=12 changed=2 unreachable=0 failed=0 skipped=23 rescued=0 ignored=0