Introduction
The ansible pre and post task are just like any other task but the former will execute before any roles or tasks in the playbook and the latter will execute as the last task in the Play. It lets you control the playbook execution. Let’s go over a few scenarios to understand more about pre and post task.
Ansible Pre Task Use Cases
1. Let’s assume you are building a server and as the first step, you need to configure repositories. You can add this as pre task.
2. Let’s assume you are creating a CI/CD pipeline with ansible. Every CI pipeline starts with pulling the source code from the repository as the first step. You can configure the checkout part as pre task.
3. Let’s assume you are starting maintenance for a bunch of servers and as the first step you wish to send an automated email alert to support teams. You can configure a pre task to send an email.
Ansible Post Task Use Cases
1. Any housekeeping activities like log cleanup, artifacts cleanup, etc can be created as a post task.
2. Automated email alert can be configured as post task.
These are just some sample use cases and all you have to understand at this moment is, pre task will be executed as the first task in the play, and post task will be executed as the last task in the play.
I will be demonstrating the examples with a four node ansible lab setup running on the docker container. If you need to know about the lab setup take a look at the below article.
https://devrunops.com/ansible-lab-setup/
How To Use Ansible Pre Task(pre_tasks)
To create a pre_tasks you have to use the “pre_tasks” directive. You can create a single task or group of tasks under the pre_tasks directive. The tasks under the “pre_tasks” directive will be executed in the order it is defined.
Let’s say you have a newly built ubuntu server that needs to be configured. Before installing any package let’s create a pre task to update all the installed packages to the latest version.
The following playbook contains two tasks under the pre_tasks directive and one regular task under the “tasks” directive. The first pre task will update the package index and the second pre task will upgrade all the packages to the latest version. The regular task will install the htop package.
---
- name: Pre & Post task testing
hosts: localhost connection: local
gather_facts: False
pre_tasks:
- name: Update apt cache
ansible.builtin.apt:
update_cache: True
- name: Upgrade all packages
ansible.builtin.apt:
name: "*"
state: latest
tasks:
- name: Install htop
ansible.builtin.apt:
pkg: htop
state: present
Execute the playbook.
# syntax check
$ ansible-playbook --syntax-check playbook.yml
# Execute playbook
$ ansible-playbook playbook.yml -K -b
In the below output, you can see the pre task is executed in the order it is defined post which the regular task ran.
PLAY [Pre & Post task testing] *********************************************************************************************
TASK [Update apt cache] ****************************************************************************************************
ok: [localhost]
TASK [Upgrade all packages] ************************************************************************************************
changed: [localhost]
TASK [Install htop] ********************************************************************************************************
changed: [localhost]
PLAY RECAP *****************************************************************************************************************
localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
There are some cases where the pre task will not be executed first when you run the playbook. One such case is when vars_prompt is used to get the user input. If you wish to know how vars_prompt works then refer to the following article.
https://devrunops.com/ansible_user_input
How To Use Ansible Pre Task(post_tasks)
The tasks defined in the post_tasks directive will be executed as the last step in the play. The tasks under the post_tasks directive will be executed in the defined order just like pre_tasks. Let’s create a post task that will send an email to notify the maintenance completion.
I have already configured my gmail by creating app passwords and using the gmail to send emails to a different domain.
---
- name: Post task testing
hosts: localhost
connection: local
tasks:
- name: Just a dummy task simulating maintenance
ansible.builtin.debug:
msg: "Ongoing Maintenance Activity"
post_tasks:
- name: Email notification
community.general.mail:
host: smtp.gmail.com
port: 587
username: [email protected]
password: xxxxxxxxxxx
to: [email protected]
subject: UPGRADE NOTIFICATION
body: |
UPGRADE COMPLETED SUCCESSFULLY
STATS
=====
SYSTEM : UBUNTU
UPGRADE : YES
TOTAL PACKAGE : 72
When I run the playbook, post task will send out an email to the configured email. Here I have hardcoded some messages in the email body just for demonstration purposes.
TASK [Just a dummy task simulating maintenance] ****************************************************************************
ok: [localhost] => {
"msg": "Ongoing Maintenance Activity"
}
TASK [Email notification] **************************************************************************************************
ok: [localhost]
Ansible Pre & Post Task Alternative
Pre and post task give you the ability to control the task execution flow. You can also create the normal tasks and make them execute in the order you wish to execute them. Ansible by default reads the file from top to bottom and executes the task in the order it is defined.
Below is the same playbook that I used in the pre_task section but all the tasks are now grouped under the tasks directive.
---
- name: Pre & Post task testing
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Update apt cache
ansible.builtin.apt:
update_cache: True
- name: Upgrade all packages
ansible.builtin.apt:
name: "*"
state: latest
- name: Install htop
ansible.builtin.apt:
pkg: htop
state: present
Extending Ansible Pre & Post Task Features
Tasks defined under the pre and post task directive are like regular tasks. You can apply features like imports, loops, conditional statements, tags, etc.
I have taken the above playbook and made the following changes.
- Created a role and bootstrap and moved the pre task under the roles/tasks/pre_repo.yml
- Instead of localhost, the task will now execute against the “all” target. The conditional statement is added to check and execute the tasks only on the ubuntu machine.
- Tag is added to further control the flow.
- name: Converted playbook
hosts: all
gather_facts: false
become: true
pre_tasks:
- import_tasks: roles/bootstrap/tasks/Pre_repo.yml
when: ansible_distribution | lower == "ubuntu"
tags: bootstrap
Wrap Up
In this article we have seen what is pre and post task in ansible and how to use it in different scenarios. Finally, we have also seen how to use pre task with imports, conditions, and tags.