Ansible Rulebooks contain rulesets, which are comprised of hosts, sources, and rules. The following example is a simple rulebook that contains one ruleset with a single event source and a single rule:
--- - name: Listen for events on a webhookhosts: localhost
sources:
- ansible.eda.webhook:
host: 0.0.0.0 port: 5000 rules:
- name: Update prod servers
condition: event.payload.message == "force-update"
action:
run_playbook:
name: playbook.yml
The name of the ruleset. Each ruleset must have a unique name in the rulebook. This is similar to the name of a play in an Ansible Playbook. | |
In an Ansible Rulebook, the | |
The | |
The event source plug-in to use, followed by directives that configure it.
Although not necessary, you might add the | |
The | |
The name of the rule. Each rule in a ruleset must have a name that is unique in the ruleset. This is similar to the name of a task in a play. (A better comparison might be to the name of a handler in a play.) | |
The | |
The | |
The action to take.
In this example, the |
Rules support a number of actions. The following table shows some examples of supported actions.
| Action | Description |
|---|---|
run_playbook
| Runs an Ansible Playbook on the local file system |
run_job_template
| Runs a job template on an automation controller |
run_workflow_template
| Runs a workflow job template on an automation controller |
run_module
| Runs a single module (similar to an Ansible ad hoc command) |
post_event
| Sends an event to the running ruleset in the rule engine |
print_event
| Writes the event to stdout |
debug
| Writes debugging information to stdout |
Examples of how to use some of these actions follow later in this section.
A complete list of actions with additional documentation is available at https://ansible.readthedocs.io/projects/rulebook/en/stable/actions.html.
You need to configure the rule engine with the URL and authentication credentials for your automation controller if you use the run_job_template or run_workflow_template actions.
For example, you might change the preceding Ansible Rulebook to run a job template named Update packages on prod servers in the Production organization on your automation controller:
---
- name: Listen for events on a webhook
hosts: host.lab.example.com
sources:
- ansible.eda.webhook:
host: 0.0.0.0
port: 5000
rules:
- name: Update prod servers
condition: event.payload.message == "force-update"
action:
run_job_template:
name: Update packages on prod servers
organization: Production 
The action is to run a job template on the automation controller. | |
The name of the job template. | |
The name of the organization on the automation controller to which the job template belongs. |
The URL and authentication token for the automation controller must be configured in the rule engine.
If you are using the ansible-rulebook command as your rule engine, it has environment variables or the --controller-url and --controller-token command-line options for this purpose.
How to use the ansible-rulebook command to test rulebooks is covered in more detail at the end of this section.
If you install the ansible.eda Ansible Content Collection, then you can access its files in the collections/ansible_collections/ansible/eda directory.
The event source plug-ins provided by this Ansible Content Collection are in the extensions/eda/plugins/event_source directory.
The plug-ins are Python text files that might contain supplementary documentation on how to use these event sources.
In addition, the extensions/eda/rulebooks subdirectory of the Ansible Content Collection contains sample Ansible Rulebooks.
You can use them as examples to help create your own rulebooks.
[user@host eda]$ ls -1 extensions/eda/rulebooks/
demo_controller_rulebook.yml
git-hook-deploy-rules.yml
git-hook-test-rules.yml
github-ci-cd-rules.yml
hello_events.yml
journald_events.yml
kafka-test-rules.yml
local-test-rules.yml
process_down.ymlIn the following subsections, examples of Ansible Rulebooks that use three event sources are examined in more detail:
ansible.eda.webhook, which provides a webhook to which you can send events
ansible.eda.journald, which processes events sent to the local journald log service
ansible.eda.url_check, which polls content at a particular URL and monitors its status
You can use the ansible.eda.webhook event source to create a webhook to which a remote service can send events that Event-Driven Ansible then acts upon.
The extensions/eda/rulebooks/git-hook-deploy-rules.yml rulebook provides an example that runs a playbook and prints to stdout when an incoming request to the webhook contains specific content:
---
- name: Local Deploy Git Hook Rules
hosts: all
sources:
- ansible.eda.webhook:
port: 5001
rules:
- name: run tests 1
condition: event.payload.repo == "{{repo}}"
action:
run_playbook:
name: ansible.eda.continuous_integration
var_root: payload
post_events: true
- name: print output
condition: event.output is defined
action:
print_event:
var_root: output
...This sample rulebook creates a socket on TCP port 5001 to listen to incoming web requests, and contains two rules.
The first rule is called | |
The rule has a condition that is met if the value of the NoteVariables cannot be defined in rulebooks. They must be provided by using the | |
If the condition is met, then the action is to run the | |
The | |
The | |
The | |
The second rule called | |
If the condition is met, then the action is to run the |
When you create a webhook in an Ansible Rulebook, it opens the TCP port but does not adjust the system firewall.
You must ensure that firewalld is configured to permit traffic to that network service to pass through the firewall.
In addition, TCP ports 1 through 1023 are privileged ports. If a rulebook is run by a non-root user and the port specified in the rulebook is in the privileged port range, then the rulebook fails to run.
Only one port can bind to an IP address at a time. If a rulebook is running and listening on a specific port, then a second rulebook must listen on a different port or a different IP address.
The following table lists the mandatory arguments for the ansible.eda.webhook event source plug-in.
| Argument | Description |
|---|---|
host
| The hostname to listen to; defaults to 0.0.0.0 (all interfaces) |
port
| The TCP port to listen to; defaults to 5000
|
Additional arguments are available to configure a TLS certificate or client authentication for the webhook.
| Argument | Description |
|---|---|
token
| An optional authentication token expected from client |
certfile
| The optional path to a certificate file to enable TLS support |
keyfile
| The optional path to a key file to be used together with certfile
|
password
| The optional password to be used when loading the certificate chain |
hmac_secret
| The optional HMAC secret used to verify the payload from the client |
hmac_algo
| The optional HMAC algorithm used to calculate the payload hash.
Defaults to sha256
|
hmac_header
| The optional HMAC header sent by the client with the payload signature, the default is x-hub-signature-256
|
hmac_format
| The optional HMAC signature format; supported formats are hex (the default) and base64. |
The following example rulebook uses the ansible.eda.webhook event source plug-in:
---
- name: Listen for events on a webhook
hosts: all
sources:
- name: Match events posted to port 5000
ansible.eda.webhook:
host: 192.168.5.10
port: 5000
rules:
- name: Run actions if the webhook has a payload
condition: event.payload is defined
actions:
- run_module:
name: ansible.builtin.debug
module_args:
msg: "Webhook received"
- run_playbook:
name: log_write.yml
extra_vars:
message: "Message 001"Event-Driven Ansible can use the ansible.eda.journald event source plug-in to react to log events recorded by the local system journal.
The extensions/eda/rulebooks/journald_events.yml rulebook provides an example of printing messages related to sudo events:
---
- name: Journald events
hosts: all
sources:
- name: Match all messages
ansible.eda.journald:
match: "ALL"
rules:
- name: Print sudo journald event message
condition: event.journald._comm == 'sudo'
action:
print_event:
pretty: true
var_root:
journald.message: journald.message
...This rulebook tests all journal messages and then has a rule that displays the message for any event that matches the sudo command.
Rather than processing all journal events, you might only process specific journal events.
The top of the extensions/eda/plugins/event_source/journald.py file displays examples of other matching criteria:
...output omitted... Examples: -------- - name: Return severity 6 messages ansible.eda.journald: match: "PRIORITY=6" - name: Return messages when sudo is used ansible.eda.journald: match: "_EXE=/usr/bin/sudo" ...output omitted...
The systemd.journal-fields(7) man page contains information about the journal fields that you can match on.
The journalctl command with the -o verbose option displays log entries with all fields.
You might use this information to help construct rulebook conditions.
For example, the following command displays all journal fields for log entries related to the SSHD service:
[user@host ~]$ sudo journalctl _SYSTEMD_UNIT=sshd.service -o verbose
Mon 2024-01-22 13:41:33.974742 UTC [s=e9ee3399119d415eafd57bbc7b04fc83;i=219;b=da5b9bb0c9cc461da9d89ae42be98731;m=c7c33f;t=60f88f>
PRIORITY=6
_BOOT_ID=da5b9bb0c9cc461da9d89ae42be98731
_MACHINE_ID=8317e4e5bd33466ebe75abdc86a14055
_HOSTNAME=workstation
_RUNTIME_SCOPE=system
_UID=0
_GID=0
_SYSTEMD_SLICE=system.slice
_CAP_EFFECTIVE=1ffffffffff
_TRANSPORT=syslog
SYSLOG_FACILITY=10
SYSLOG_TIMESTAMP=Jan 22 13:41:33
SYSLOG_IDENTIFIER=sshd
SYSLOG_PID=1355
MESSAGE=Server listening on 0.0.0.0 port 22.
...output omitted...When used in a condition for a rule, the ansible.eda.journald event source plug-in converts the journal key names to lowercase.
For example, if you want to check the value of the SYSLOG_IDENTIFIER journal key, then your condition must check the value of the event.journald.syslog_identifier event key.
The following sample rulebook prints journal events that match the workstation host where the sshd service was either reloaded or restarted:
---
- name: Journald events
hosts: all
sources:
- name: Match SSHD messages
ansible.eda.journald:
match: "_SYSTEMD_UNIT=sshd.service"
rules:
- name: Print SSHD SIGHUP and signal 15 events
condition: >
((event.journald.message == 'Received SIGHUP; restarting.') or
(event.journald.message == 'Received signal 15; terminating.') and
(event.journald._hostname == 'workstation'))
action:
print_event:
pretty: trueThis example is one way of matching
| |
Use the greater-than sign to split a condition over multiple lines.
You can use the |
Event-Driven Ansible can react to the status of a URL by using the ansible.eda.url_check event source plug-in.
The extensions/eda/rulebooks/ directory does not contain an example rulebook for this event source, but the extensions/eda/plugins/event_source/url_check.py plug-in file contains code similar to the following example near the top of the file:
...output omitted... - name: check web server ansible.eda.url_check: urls: - http://192.0.2.56:8000/docs delay: 10 ...output omitted...
The previous example polls http://192.0.2.56:8000/docs every 10 seconds and sends the status of the URL as an event.
The event returns the status, status_code, and url keys with their corresponding values.
The following rulebook uses the ansible.eda.url_check event source plug-in:
---
- name: Listen for URL events
hosts: all
sources:
- name: Match events from web application
ansible.eda.url_check:
urls:
- http://webapp.example.lab.com
delay: 60
rules:
- name: Web application is up
condition: event.url_check.status == "up"
action:
run_module:
name: ansible.builtin.debug
module_args:
msg: "Web application is up"
- name: Web application error
condition: event.url_check.status_code == 500
action:
run_playbook:
name: redeploy_webapp.yml
- name: Web application is down
condition: event.url_check.status == "down"
action:
run_playbook:
name: restart_services.ymlIn this example the | |
In the first rule, if the | |
In the second rule, if the | |
In the third rule, if the |
You can use the ansible-rulebook command to test rulebooks.
The following example demonstrates the basic syntax for using the ansible-rulebook command:
[user@host ~]$ ansible-rulebook -i example_inventory -r example_rulebook.ymlThe following table shows some arguments available to the ansible-rulebook command.
| Argument | Description |
|---|---|
-r RULEBOOK or --rulebook RULEBOOK
| Specifies the rulebook to run. |
-e VARS or --vars VARS
| Specifies a variable file to pass to the rulebook. |
-E ENV_VARS or --env-vars ENV_VARS
| A comma-separated list of variables to import from your environment. |
-v or --verbose
| Print more debug messages. Use -vv to print even more verbosely. |
-S SOURCE_DIR
| Add a source directory. You might use this if you intend to use a custom event source plug-in. |
-i INVENTORY or --inventory INVENTORY
| Specify the inventory file or directory to use. |
--print-events
| Print events to stdout. |
When you run a rulebook with the ansible-rulebook command, the process runs until you press Ctrl+C in the terminal or until it is otherwise interrupted.
The following example runs the webhook_example.yml rulebook and uses the hosts in the specified inventory file:
[user@host ~]$ ansible-rulebook -i inventory -r webhook_example.ymlUnless there are errors in the rulebook, running the preceding command produces no output until a rule's condition matches and triggers an action.
The following example demonstrates output that you might see when a rule matches and its action causes ansible-rulebook to run a playbook:
[user@host ~]$ ansible-rulebook -i inventory -r webhook_example.yml
PLAY [Take action from a webhook event] ****************************************
TASK [Gathering Facts] *********************************************************
ok: [servera]
ok: [serverb]
TASK [A task in a playbook] ****************************************************
changed: [servera]
changed: [serverb]
PLAY RECAP *********************************************************************
servera : ok=2 changed=1 unreachable=0 failed=0 ...
serverb : ok=2 changed=1 unreachable=0 failed=0 ...The --print-events argument can be used with the ansible-rulebook command to print the result of any events in your rulebook to stdout.
This can be especially useful if you are unsure what the resulting data is or what the formatting looks like in the events from your rulebook.
The following example shows the output when the ansible-rulebook command is run using the --print-events argument, and a webhook event causes a rule to run an action:
[user@host ~]$ansible-rulebook -i inventory -r webhook_example.yml --print-events{ 'meta': { 'endpoint': '', 'headers': { 'Accept': '/', 'Content-Length': '56', 'Content-Type': 'application/json', 'Host': 'rulebook-host:5000', 'User-Agent': 'curl/7.76.1'}, 'received_at': '2024-02-01T22:07:23.720101Z', 'source': { 'name': 'Match events posted to port 5000', 'type': 'ansible.eda.webhook'}, 'uuid': 'e641ca23-b585-4ad1-9a6c-7f21527be5b7'}, 'payload': {'this_is_a_key_from_json': 'this is a value from json'}} PLAY [wrapper] ***************************************************************** ...output_omitted...
In the previous example the event was printed before the action was run.
This shows that the event.payload key contains the this_is_a_key_from_json key with the this is a value from json value.