Bookmark this page

Guided Exercise: Acting on Results from the URL Check Plug-in

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

  1. On the workstation machine, change to the /home/student/intro-url project directory. Examine its contents to become familiar with the project files.

    1. Change to the /home/student/intro-url project directory:

      [student@workstation ~]$ cd ~/intro-url
      [student@workstation intro-url]$
    2. Examine the contents of the inventory file. Note that it contains a single host.

      servera.lab.example.com
    3. 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'
    4. 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: started
  2. The 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.

    1. 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...
    2. 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.

    3. 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.

    4. 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...
  3. 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.

    1. 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
    2. 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: false
      
        sources:
          - name: Match events from webserver
            ansible.eda.url_check:
              urls:
                - http://servera.lab.example.com/index.html
              delay: 10
    3. 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 running
    4. Add 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.yml
  4. Test the url_check.yml rulebook to verify that the defined rules trigger on the expected conditions.

    1. 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 inventory
    2. After 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...
    3. Open a second terminal and connect to servera as the student user:

      [student@workstation ~]$ ssh servera
      ...output omitted...
      [student@servera ~]$
    4. 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
    5. 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...
    6. 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
      *******************************************************************************
    7. Press Ctrl+C in the first terminal to stop the running rulebook.

  5. 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.

    1. 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.

    2. In the second terminal, remove the /var/www/html/index.html file:

      [student@servera ~]$ sudo rm /var/www/html/index.html
    3. Come 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...
    4. In the second terminal, stop the Apache service:

      [student@servera ~]$ sudo systemctl stop httpd
    5. Come 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...

      Important

      Although the Webserver is down rule triggers the website_down_index.html playbook, this playbook does not fix the problem.

    6. Start the Apache service in the second terminal:

      [student@servera ~]$ sudo systemctl start httpd
    7. Press Ctrl+C in the first terminal to stop the running rulebook.

  6. 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.

    1. 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 == 404
            action:
              run_playbook:
                name: website_down_index.yml

      Important

      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.

    2. 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

      Note

      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.

    3. 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 inventory
    4. In 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
    5. 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...
    6. In the second terminal, stop the Apache service:

      [student@servera ~]$ sudo systemctl stop httpd
      [sudo] password for student: student
    7. 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...
    8. Close the second terminal and press Ctrl+C in the first terminal to stop the running rulebook.

Finish

On the workstation machine, use the lab command to complete this exercise. This step is important to ensure that resources from previous exercises do not impact upcoming exercises.

[student@workstation ~]$ lab finish intro-url

Revision: do274-2.4-65daa25