Bookmark this page

Guided Exercise: Acting on Webhook Events

Configure and test an Ansible Rulebook that triggers when it receives a webhook event.

Outcomes

  • Install the ansible-rulebook package and the ansible.eda content collection.

  • Create one Ansible Rulebook that triggers when it receives a webhook event and prints payload data from the webhook.

  • Create another Ansible Rulebook that triggers when it receives a webhook event and appends payload data to a log file.

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-webhook

Instructions

  1. On the workstation machine, change to the /home/student/intro-webhook project directory:

    [student@workstation ~]$ cd ~/intro-webhook
    [student@workstation intro-webhook]$
  2. Install the ansible-rulebook package and its dependencies:

    [student@workstation intro-webhook]$ sudo dnf install ansible-rulebook
    [sudo] password for student: student
    ..output omitted...
    Is this ok [y/N]: y
    ..output omitted...
  3. Configure the Ansible project in the /home/student/intro-webhook directory so that the ansible-galaxy command retrieves collections from the classroom's private automation hub. Enable access to the rh-certified and validated repositories.

    1. Use either VS Code or a command-line tool to examine the ansible.cfg file in the project directory. Notice that the [galaxy] section has configurations for both the rh-certified and validated repositories, but the configurations are missing the API token.

      [defaults]
      collections_paths = ./collections:/usr/share/ansible/collections
      
      [galaxy]
      server_list = validated, rh-certified
      
      [galaxy_server.validated]
      url=https://hub.lab.example.com/api/galaxy/content/validated/
      token=<put your token here>
      
      [galaxy_server.rh-certified]
      url=https://hub.lab.example.com/api/galaxy/content/rh-certified/
      token=<put your token here>
    2. Use a web browser to navigate to the private automation hub at https://hub.lab.example.com, and then log in as student using redhat123 as the password.

    3. If necessary, click the main menu icon at the upper left of the page to display the main menu.

    4. Navigate to CollectionsAPI token and then click Load token. Copy the API token.

    5. Using the copied token, update both token lines in the ansible.cfg file. Your token is different from the token displayed in this example. Save and close the file when done:

      ...output omitted...
      [galaxy_server.validated]
      url=https://hub.lab.example.com/api/galaxy/content/validated/
      token=d008a313bfee27f882e6f49f337b41c1fff2ab79
      
      [galaxy_server.rh-certified]
      url=https://hub.lab.example.com/api/galaxy/content/rh-certified/
      token=d008a313bfee27f882e6f49f337b41c1fff2ab79
  4. Install the ansible.eda content collection into the collections directory in the project directory.

    1. Install the ansible.eda content collection:

      [student@workstation intro-webhook]$ ansible-galaxy collection install \
      ansible.eda -p collections/
      ...output omitted...
      ansible.eda:1.4.5 was installed successfully
    2. List the installed collections available to the /home/student/intro-webhook directory:

      [student@workstation intro-webhook]$ ansible-galaxy collection list
      
      # /home/student/intro-webhook/collections/ansible_collections
      Collection               Version
      ------------------------ -------
      ansible.eda              1.4.5
      ...output omitted...
  5. Create and run the webhook_print.yml rulebook.

    1. Create the webhook_print.yml rulebook with the following contents:

      ---
      - name: Listen for events on a webhook
        hosts: workstation.lab.example.com
      
        sources:
          - name: Match events posted to port 5000
            ansible.eda.webhook:
              host: 0.0.0.0
              port: 5000
      
        rules:
          - name: Print output of event.payload
            condition: event.payload is defined
            action:
              run_module:
                name: ansible.builtin.debug
                module_args:
                  msg: "{{ event.payload }}"

      This rulebook uses the ansible.eda.webhook event source that creates a webhook that listens on TCP port 5000. The rulebook contains a rule that prints the event.payload variable using the ansible.builtin.debug module if the event.payload condition is defined.

    2. Examine the inventory file. This inventory file only contains the workstation.lab.example.com host.

      workstation.lab.example.com
    3. Use the ansible-rulebook command to run the webhook_print.yml rulebook. Specify the inventory file with the -i option:

      [student@workstation intro-webhook]$ ansible-rulebook -r webhook_print.yml \
      -i inventory

      Leave this command running in the terminal.

  6. Open a second terminal and use the curl command to send data to the running rulebook, and then examine the output in the first terminal.

    1. Open a second terminal and use the following curl command to send data to the running rulebook:

      [student@workstation ~]$ curl \
      --header "Content-Type: application/json" \
      --request POST \
      --data '{"log_status": true, "message": "test123"}' \
      workstation.lab.example.com:5000

      This curl command sends a header with the Content-Type key set to application/json. This states that the data being sent is in the JSON format. The command sets the request method to POST, and sends the log_status and message keys with their associated values as JSON-formatted data to the workstation.lab.example.com host on TCP port 5000.

      Note

      The curl command is run from the workstation machine, and consequently does not require opening a port in the firewall for the nonprivileged TCP port 5000.

    2. In the first terminal where the rulebook is running, monitor the output of the rulebook:

      ...output omitted...
      PLAY [wrapper] *****************************************************************
      
      TASK [Module wrapper] **********************************************************
      ok: [workstation.lab.example.com] => {
          "msg": {
              "log_status": true,
              "message": "test123"
          }
      }
      
      TASK [save result] *************************************************************
      ok: [workstation.lab.example.com]
      
      PLAY RECAP *********************************************************************
      workstation.lab.example.com : ok=2    changed=0    unreachable=0    failed=0 ...

      The curl command triggered the rulebook and the ansible.builtin.debug module printed the event.payload variable, which contains the log_status and message keys with their associated values.

    3. Close the second terminal and press Ctrl+C in the first terminal to stop the running rulebook.

  7. Create, run, and trigger the webhook_write.yml rulebook. The rulebook uses the ansible.eda.webhook source and listens on TCP port 5000. The rulebook defines a condition in a rule where if the event.payload.log_status Boolean is set to true, then the rule uses the run_playbook action to run the provided webhook_log.yml playbook. The run_playbook action uses the extra_vars option to pass the event.payload.message variable to the playbook as the message variable.

    1. Examine the provided webhook_log.yml playbook:

      ---
      - name: Write webhook messages to log file
        hosts: workstation.lab.example.com
        gather_facts: true
        become: true
        become_user: student
        vars:
          timestamp: "{{ ansible_facts['date_time']['iso8601'] }}"
        tasks:
          - name: Append the incoming POST message to the log file
            ansible.builtin.lineinfile:
              path: /home/student/intro-webhook/webhook.log
              line: "{{ timestamp }} {{ message }}"
              create: true
              mode: "0644"

      Notice that the message variable is not defined in the playbook.

    2. Create the webhook_write.yml rulebook with the following content:

      ---
      - name: Listen for events on a webhook
        hosts: workstation.lab.example.com
      
        sources:
          - name: Match events posted to port 5000
            ansible.eda.webhook:
              host: 0.0.0.0
              port: 5000
      
        rules:
          - name: Print payload message to log file
            condition: event.payload.log_status == true
            action:
              run_playbook:
                name: webhook_log.yml
                extra_vars:
                  message: "{{ event.payload.message }}"
    3. Run the webhook_write.yml rulebook:

      [student@workstation intro-webhook]$ ansible-rulebook \
      -r webhook_write.yml -i inventory

      Leave this command running in the terminal.

    4. Open a second terminal and use the following three curl commands to send data to the running rulebook:

      [student@workstation ~]$ curl \
      --header "Content-Type: application/json" \
      --request POST \
      --data '{"log_status": true, "message": "message 001"}' \
      workstation.lab.example.com:5000

      Important

      The log_status Boolean in the second curl command is set to false, which does not match the condition in the rulebook.

      [student@workstation ~]$ curl \
      --header "Content-Type: application/json" \
      --request POST \
      --data '{"log_status": false, "message": "message 002"}' \
      workstation.lab.example.com:5000
      [student@workstation ~]$ curl \
      --header "Content-Type: application/json" \
      --request POST \
      --data '{"log_status": true, "message": "message 003"}' \
      workstation.lab.example.com:5000
    5. In the first terminal where the rulebook is running, monitor the output of the rulebook:

      PLAY [Write webhook messages to log file] **************************************
      
      TASK [Gathering Facts] *********************************************************
      ok: [workstation.lab.example.com]
      
      TASK [Append the incoming POST message to the log] *****************************
      changed: [workstation.lab.example.com]
      
      PLAY RECAP *********************************************************************
      workstation.lab.example.com : ok=2    changed=1    unreachable=0    failed=0 ...
      
      PLAY [Write webhook messages to log file] **************************************
      
      TASK [Gathering Facts] *********************************************************
      ok: [workstation.lab.example.com]
      
      TASK [Append the incoming POST message to the log] *****************************
      changed: [workstation.lab.example.com]
      
      PLAY RECAP *********************************************************************
      workstation.lab.example.com : ok=2    changed=1    unreachable=0    failed=0 ...

      The rulebook ran the webhook_log.yml playbook twice as expected because one of the three curl commands set the log_status key to false.

    6. Close the second terminal and press Ctrl+C in the first terminal to stop the running rulebook.

    7. Examine the webhook.log file that the webhook_log.yml playbook created:

      [student@workstation intro-webhook]$ cat webhook.log
      2024-01-24T20:13:07Z message 001
      2024-01-24T20:14:45Z message 003

      The content of the log file matches the expectations based on the condition in the webhook_write.yml 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-webhook

Revision: do274-2.4-65daa25