Configure and test an Ansible Rulebook that triggers when it receives certain results from the URL Check plug-in.
Outcomes
Create an Ansible Rulebook that triggers when it receives the status from a web server.
Use the ansible-rulebook command with the --print-events option to print events to stdout.
Create rules that trigger actions based on multiple conditions by using the URL check plug-in.
As the student user on the workstation machine, use the lab command to prepare your environment for this exercise, and to ensure that all required resources are available:
[student@workstation ~]$ lab start intro-url
Instructions
On the workstation machine, change to the /home/student/intro-url project directory.
Examine its contents to become familiar with the project files.
Change to the /home/student/intro-url project directory:
[student@workstation ~]$ cd ~/intro-url
[student@workstation intro-url]$Examine the contents of the inventory file.
Note that it contains a single host.
servera.lab.example.com
Examine the contents of the website_down_index.yml playbook.
This playbook shows a message about the state of the website and restores the index.html file.
---
- name: Restoring website content
hosts: servera.lab.example.com
remote_user: devops
become: true
gather_facts: false
tasks:
- name: Display a message
ansible.builtin.debug:
msg: "Website is down!"
- name: Replace the index.html file
ansible.builtin.copy:
remote_src: true
src: /tmp/index.html
dest: /var/www/html/
owner: apache
group: apache
mode: '0644'Examine the contents of the website_down_service.yml playbook.
This playbook shows a message about the state of the website, and starts the httpd service.
---
- name: Restoring apache service
hosts: servera.lab.example.com
remote_user: devops
become: true
gather_facts: false
tasks:
- name: Display a message
ansible.builtin.debug:
msg: "Website is down!"
- name: Start apache service
ansible.builtin.service:
name: httpd
state: startedThe lab command installed the ansible.eda collection into the collections/ directory.
Verify that the ansible.eda collection is available, and then find and examine the url_check.py file that corresponds to the URL check event source plug-in.
List the installed collections in the collections/ directory.
[student@workstation intro-url]$ansible-galaxy collection list -p collections/# /home/student/intro-url/collections/ansible_collections Collection Version ------------------------ -------ansible.eda 1.4.5...output omitted...
Use the tree command to list the directories in the collections/ansible_collections/ansible/ directory.
Identify the directory that corresponds to the event source plug-ins for the ansible.eda collection.
[student@workstation intro-url]$tree -d collections/ansible_collections/ansible/└── eda ├── extensions │ └── eda │ ├── plugins │ │ ├── event_filter │ │ └──event_source│ └── rulebooks ...output omitted...
The event_source directory has the event source plug-ins for the ansible.eda collection.
Use the tree command to list the files in the already identified event source plug-ins directory.
Identify the file that corresponds to the URL check event source plug-in.
[student@workstation intro-url]$tree \collections/ansible_collections/ansible/eda/extensions/eda/plugins/event_source/...output omitted... ├── tick.py ├──url_check.py└── webhook.py 0 directories, 16 files
The url_check.py file corresponds to the URL check event source plug-in.
Examine the url_check.py file.
The first lines include a commentary with the description of the event source plug-in, the accepted arguments, and an example of how to use the event source plug-in.
"""url_check.py.
An ansible-rulebook event source plugin that polls a set of URLs and sends
events with their status.
Arguments:
---------
urls - a list of urls to poll
delay - the number of seconds to wait between polling
verify_ssl - verify SSL certificate
Example:
-------
- name: check web server
ansible.eda.url_check:
urls:
- http://44.201.5.56:8000/docs
delay: 10
"""
...output omitted...Based on the example in the url_check.py file, create a rulebook named url_check.yml with only one ruleset.
The ruleset in the rulebook runs against the servera.lab.example.com machine.
The ruleset has one source that uses the URL check event source plug-in to poll the http://servera.lab.example.com/index.html URL, and waits 10 seconds between polling.
The ruleset has two rules for the source.
One rule displays a message when your web server is up and the other rule triggers the website_down_index.html playbook when your web server is down.
Create a rulebook named url_check.yml.
In the rulebook, add a ruleset named Listen for URL events.
Set the hosts keyword to servera.lab.example.com and the gather_facts keyword to false.
--- - name: Listen for URL events hosts: servera.lab.example.com gather_facts: false
Add a source named Match events from webserver.
Use ansible.eda.url_check as the event source plug-in.
Set the urls argument to a one-element list with the string http://servera.lab.example.com/index.html as the list item.
Set the delay argument to 10.
--- - name: Listen for URL events hosts: servera.lab.example.com gather_facts: falsesources:- name: Match events from webserveransible.eda.url_check:urls:- http://servera.lab.example.com/index.htmldelay: 10
Add a rule named Webserver is up.
Use the debug action to display a message indicating that the website is up and running when the event.url_check.status key is set to up.
---
- name: Listen for URL events
hosts: servera.lab.example.com
gather_facts: false
sources:
- name: Match events from webserver
ansible.eda.url_check:
urls:
- http://servera.lab.example.com/index.html
delay: 10
rules:
- name: Webserver is up
condition: event.url_check.status == "up"
action:
debug:
msg: The website is up and runningAdd a second rule to the ruleset named Webserver is down.
Use the run_playbook action to run the website_down_index.yml playbook when the event.url_check.status key has a value of down.
---
- name: Listen for URL events
hosts: servera.lab.example.com
gather_facts: false
sources:
- name: Match events from webserver
ansible.eda.url_check:
urls:
- http://servera.lab.example.com/index.html
delay: 10
rules:
- name: Webserver is up
condition: event.url_check.status == "up"
action:
debug:
msg: The website is up and running
- name: Webserver is down
condition: event.url_check.status == "down"
action:
run_playbook:
name: website_down_index.ymlTest the url_check.yml rulebook to verify that the defined rules trigger on the expected conditions.
Use the ansible-rulebook command to run the url_check.yml rulebook.
Specify the inventory file with the -i option.
[student@workstation intro-url]$ ansible-rulebook -r url_check.yml -i inventoryAfter a few seconds, the rulebook triggers the debug action with the configured message, and continues showing that message every 10 seconds (every time the Webserver is up rule uses ansible.eda.url_check to poll the URL).
Leave this command running in the terminal.
** 2024-03-12 17:28:28.302747 [debug] *****************************************
The website is up and running
*******************************************************************************
** 2024-03-12 17:28:38.318724 [debug] *****************************************
The website is up and running
*******************************************************************************
...output omitted...Open a second terminal and connect to servera as the student user:
[student@workstation ~]$ ssh servera
...output omitted...
[student@servera ~]$On the servera machine, remove the /var/www/html/index.html file by using the sudo command.
Use student as the sudo password.
[student@servera ~]$sudo rm /var/www/html/index.html[sudo] password for student:student
Come back to the first terminal.
The rulebook detects the down event on your web server and triggers the website_down_index.yml playbook, which restores the index.html file.
PLAY [Restoring website content] ***********************************************
TASK [Display a message] *******************************************************
ok: [servera.lab.example.com] => {
"msg": "Website is down!"
}
TASK [Replace the index.html file] *********************************************
changed: [servera.lab.example.com]
PLAY RECAP *********************************************************************
servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 ...
...output omitted...In the next poll, your website status is up, so the rulebook triggers the Webserver is up rule and displays the message The website is up and running:
...output omitted...
** 2024-03-12 17:29:28.394510 [debug] *****************************************
The website is up and running
*******************************************************************************Press Ctrl+C in the first terminal to stop the running rulebook.
Run the rulebook again but this time print events to stdout. By printing events to stdout you can identify keys that help you to establish specific conditions for simple failures.
Identify the event keys when your website is up and running, when your website does not contain an index.html file, and when the Apache service is stopped.
Use the ansible-rulebook command to run the url_check.yml rulebook.
Specify the --print-events option to print events to stdout and the -i option to indicate the inventory file.
[student@workstation intro-url]$ansible-rulebook -r url_check.yml -i inventory \--print-events{ 'meta': { 'received_at': '2024-01-31T23:50:02.656783Z', 'source': { 'name': 'Match events from webserver', 'type': 'ansible.eda.url_check'}, 'uuid': '0c6685c2-3132-4e40-8d8d-f6bb03fa0ae6'}, 'url_check': { 'status': 'up', 'status_code': 200, 'url': 'http://servera.lab.example.com/index.html'}} ...output omitted...
Notice that the event.url_check.status key has a value of up and the event.url_check.status_code key has a value of 200.
In the second terminal, remove the /var/www/html/index.html file:
[student@servera ~]$ sudo rm /var/www/html/index.htmlCome back to the first terminal.
The rulebook detects the down event on your web server.
Notice that the event.url_check.status key has a value of down and the event.url_check.status_code key has a value of 404.
[student@workstation intro-url]$ansible-rulebook -r url_check.yml -i inventory \--print-events{ 'meta': { 'received_at': '2024-02-01T00:02:46.597188Z', 'source': { 'name': 'Match events from webserver', 'type': 'ansible.eda.url_check'}, 'uuid': '647b749b-65ca-4af7-916f-04ac1deeff6e'}, 'url_check': { 'status': 'down', 'status_code': 404, 'url': 'http://servera.lab.example.com/index.html'}} ...output omitted...
In the second terminal, stop the Apache service:
[student@servera ~]$ sudo systemctl stop httpdCome back to the first terminal.
The rulebook detects the down event on your web server, and this time there is an error message given by the event.url_check.error_msg key.
{ 'meta': { 'received_at': '2024-02-01T16:50:34.770915Z',
'source': { 'name': 'Match events from webserver',
'type': 'ansible.eda.url_check'},
'uuid': 'f801318e-0c0d-4a4b-8902-a148a4f0e929'},
'url_check': { 'error_msg': 'Cannot connect to host '
'servera.lab.example.com:80 ssl:default '
"[Connect call failed ('172.25.250.9', 80)]",
'status': 'down',
'url': 'http://servera.lab.example.com/index.html'}}
...output omitted...Although the Webserver is down rule triggers the website_down_index.html playbook, this playbook does not fix the problem.
Start the Apache service in the second terminal:
[student@servera ~]$ sudo systemctl start httpdPress Ctrl+C in the first terminal to stop the running rulebook.
Edit the url_check.yml rulebook.
Modify the Web Server is down rule by adding a second condition with 404 as the value for the status_code event key.
Add a new rule for the same source that triggers the website_down_service.html playbook when your web server matches the down status condition because of the stopped Apache service.
Verify the rules work as expected.
Edit the url_check.yml rulebook.
Modify the Web Server is down rule to include the condition for the event.url_check.status_code key.
Optionally, update the name of the rule to include the cause for the failure.
...output omitted... - name: Webserver is down(index.html not found)condition:>event.url_check.status == "down"and event.url_check.status_code == 404action: run_playbook: name: website_down_index.yml
You can use the greater-than sign to write a long line as multiple lines in a YAML file to make it easier to read.
In the preceding rulebook, the condition for the rule is wrapped over multiple lines by using the greater-than sign after the condition parameter.
Add another rule to the ruleset named Webserver is down (service stopped).
Use the run_playbook action to run the website_down_service.yml playbook when the event.url_check.status key has a value of down and the event.url_check.error_msg key contains the message "Cannot connect to host".
...output omitted... - name: Webserver is down (index.html not found) condition: > event.url_check.status == "down" and event.url_check.status_code == 404 action: run_playbook: name: website_down_index.yml- name: Webserver is down (service stopped)condition: >event.url_check.status == "down"and event.url_check.error_msg is search("Cannot connect to host")action:run_playbook:name: website_down_service.yml
The conditions for this exercise are sufficient to distinguish between the cases of a missing index.html file and a stopped Apache service.
In your production systems you can increase the number of conditions to match the specific situation to solve by using Event-Driven Ansible.
In the first terminal, use the ansible-rulebook command to run the url_check.yml rulebook:
[student@workstation intro-url]$ ansible-rulebook -r url_check.yml -i inventoryIn the second terminal, remove the /var/www/html/index.html file:
[student@servera ~]$sudo rm /var/www/html/index.html[sudo] password for student:student
Come back to the first terminal. The rulebook works as expected.
PLAY [Restoring website content] ***********************************************
TASK [Display a message] *******************************************************
ok: [servera.lab.example.com] => {
"msg": "Website is down!"
}
TASK [Replace the index.html file] *********************************************
changed: [servera.lab.example.com]
PLAY RECAP *********************************************************************
servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 ...
** 2024-03-12 17:34:33.472062 [debug] *****************************************
The website is up and running
*******************************************************************************
...output omitted...In the second terminal, stop the Apache service:
[student@servera ~]$sudo systemctl stop httpd[sudo] password for student:student
Come back to the first terminal. The rulebook works as expected.
PLAY [Restoring apache service] ************************************************
TASK [Display a message] *******************************************************
ok: [servera.lab.example.com] => {
"msg": "Website is down!"
}
TASK [Start apache service] ****************************************************
changed: [servera.lab.example.com]
PLAY RECAP *********************************************************************
servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 ...
** 2024-03-12 17:34:53.493524 [debug] *****************************************
The website is up and running
*******************************************************************************
...output omitted...Close the second terminal and press Ctrl+C in the first terminal to stop the running rulebook.