{"id":27165028,"url":"https://github.com/mocdaniel/lab-event-driven-ansible","last_synced_at":"2026-01-21T04:03:09.890Z","repository":{"id":216661672,"uuid":"741976064","full_name":"mocdaniel/lab-event-driven-ansible","owner":"mocdaniel","description":null,"archived":false,"fork":false,"pushed_at":"2024-01-15T18:02:11.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T02:51:13.417Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mocdaniel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-11T14:00:27.000Z","updated_at":"2024-01-11T14:00:27.000Z","dependencies_parsed_at":"2025-04-09T02:50:52.307Z","dependency_job_id":"66306274-00e7-4510-9338-9cc138524d5b","html_url":"https://github.com/mocdaniel/lab-event-driven-ansible","commit_stats":null,"previous_names":["mocdaniel/lab-event-driven-ansible"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mocdaniel/lab-event-driven-ansible","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mocdaniel%2Flab-event-driven-ansible","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mocdaniel%2Flab-event-driven-ansible/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mocdaniel%2Flab-event-driven-ansible/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mocdaniel%2Flab-event-driven-ansible/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mocdaniel","download_url":"https://codeload.github.com/mocdaniel/lab-event-driven-ansible/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mocdaniel%2Flab-event-driven-ansible/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28625926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T02:47:06.670Z","status":"ssl_error","status_checked_at":"2026-01-21T02:45:44.886Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-09T02:50:49.441Z","updated_at":"2026-01-21T04:03:09.873Z","avatar_url":"https://github.com/mocdaniel.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Event-Driven Ansible Lab\n\nThis is a lab designed to demonstrate Ansible and how Event-Driven Ansible (**EDA**) builds on top of its capabilities.\n\nThe setup is done with Ansible, too. It will install **Ansible, EDA, Prometheus**, and **Alertmanager** on a VM to demonstrate some of the capabilities of EDA.\n\n## Prerequisites\n\nTo follow along with this lab in its entirety, you will need three VMs:\n\n\u003e [!NOTE]\n\u003e If you want to skip Ansible basics and go straight to EDA, you'll need just the `eda-controller.example.com` VM and can skip the others.\n\n| VM name            | OS          |\n|--------------------|-------------|\n| eda-controller.example.com | CentOS/Rocky 8.9 |\n| company.example.com        | CentOS/Rocky 8.9 |\n| webshop.example.com       | Ubuntu 22.04     |\n\n**You'll need to be able to SSH to each of these VMs as root using SSH keys.**\n\n## Lab Setup\n\n### Clone the repository and create a Python virtual environment\n\n```bash\ngit clone https://github.com/mocdaniel/lab-event-driven-ansible.git\ncd lab-event-driven-ansible\npython3 -m venv .venv\nsource .venv/bin/activate\n```\n\n### Install Ansible and other dependencies\n\n```bash\npip install -r requirements.txt\n```\n\n### Create the inventory file\n\n```yaml\n---\n# hosts.yml\nwebservers:\n  hosts:\n    webshop.example.com:\n      ansible_host: \u003cip-address\u003e\n      webserver: apache2\n    company.example.com:\n      ansible_host: \u003cip-address\u003e\n      webserver: httpd\neda_controller:\n  hosts:\n    eda-controller.example.com:\n      ansible_host: \u003cip-address\u003e\n```\n\n### Install Needed Roles and Collections\n    \n```bash\nansible-galaxy install -r requirements.yml\n```\n\n### Run the Setup Playbook\n\nAfter you created the inventory file and filled in the IP addresses, you can run the setup playbook:\n\n```bash\nansible-playbook playbooks/setup.yml\n```\n\n\u003e [!CAUTION]\n\u003e Due to a known bug with Python on MacOS, you need to run `export NO_PROXY=\"*\"` on MacOS before running the playbook\n\n---\n\n## Demos\n\n### Lab 1: Ansible Basics\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAnsible from the CLI via ansible\u003c/summary\u003e\n\n#### Ansible from the CLI via `ansible`\n\nThe first example installs a webserver on all hosts in the `webservers` group. The installed webserver is defined as a **host variable** in the inventory file `hosts.yml` (*see above*).\n\n```console\nansible \\\n   webservers  \\\n  -m package   \\\n  -a 'name=\"{{ webserver }}\"' \\\n  --one-line\n```\n\nAfterwards, we can start the webserver on all hosts in the `webservers` group.\n\n```console\nansible \\\n   webservers  \\\n  -m service   \\\n  -a 'name=\"{{ webserver }}\" state=started' \\\n  --one-line\n```\n\nGo on and check if the web servers are running on the respective hosts.\n\n\u003e [!HINT]\n\u003e Ansible is **idempotent** - try running the commands again and see how the output differs.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAnsible from the CLI via ansible-playbook\u003c/summary\u003e\n\n#### Ansible from the CLI via `ansible-playbook`\n\nThe second example utilizes the following **playbook** to **gather** and **display information** for all hosts in the `webservers` group, utilizing the **example** role from the lab repository.\n\n```yaml\n---\n- name: Example role\n  hosts: webservers\n  gather_facts: false\n  vars:\n    greeting: \"Hello World!\"\n  pre_tasks:\n    - name: Say Hello\n      ansible.builtin.debug:\n        msg: \"{{ greeting }}\"\n  roles:\n    - role: example\n  post_tasks:\n    - name: Say goodbye\n      ansible.builtin.debug:\n        msg: Goodbye!\n```\n\n```console\nansible-playbook \\\n    playbooks/example.yml\n```\n\n\u003c/details\u003e\n\n### Lab 2: Event-Driven Ansible\n\n\u003cdetails\u003e\n\n\u003csummary\u003eReceive Generic Events via Webhook\u003c/summary\u003e\n\n#### Receive Generic Events via Webhook\n\nIf you followed the setup instructions for the EDA lab, you should already have a running EDA instance on the `eda-controller.example.com` VM.\n\nIf you navigate to `/etc/edacontroller/rulebook.yml` on the VM, you'll see the following rulebook:\n\n```yaml\n---\n- name: Listen to webhook events\n  hosts: all\n  sources:\n    - ansible.eda.webhook:\n        host: 0.0.0.0\n        port: 5000\n  rules:\n    - name: Debug event output\n      condition: 1 == 1\n      action:\n        debug:\n          msg: \"{{ event }}\"\n\n- name: Listen to Alertmanager alerts\n  hosts: all\n  sources:\n    - ansible.eda.alertmanager:\n        host: 0.0.0.0\n        port: 9000\n        data_alerts_path: alerts\n        data_host_path: labels.instance\n        data_path_separator: .\n  rules:\n    - name: Restart MySQL server\n      condition: event.alert.labels.alertname == 'MySQL not running' and event.alert.status == 'firing'\n      action:\n        run_module:\n          name: ansible.builtin.service\n          module_args:\n            name: mysql\n            state: restarted\n    - name: Debug event output\n      condition: 1 == 1\n      action:\n        debug:\n          msg: \"{{ event }}\"\n\n```\n\nFor this part of the lab, the **first rule** is the one we're interested in: It listens to a generic webhook on port `5000` and prints the event's **metadata** to its logs.\n\nTo test this, we can use the `curl` command to send a `POST` request to the webhook `/endpoint` from the VM itself:\n\n```console\ncurl \\\n  -X POST \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"foo\": \"bar\"}' \\\n  http://localhost:5000/endpoint\n```\n\nIf you now check the logs of the EDA controller, you should see the following output:\n\n```console\njournalctl -fu eda-controller\n\nJan 11 16:35:29 eda-controller ansible-rulebook[56882]: {'payload': {'foo': 'bar'}, 'meta': {'endpoint': 'endpoint',\n'headers': {'Host': 'localhost:5000', 'User-Agent': 'curl/7.76.1', 'Accept': '*/*', 'Content-Length': '21',\n'Content-Type': 'application/x-www-form-urlencoded'}, 'source': {'name': 'ansible.eda.webhook', 'type': 'ansible.eda.webhook'},\n'received_at': '2024-01-11T15:35:29.798401Z', 'uuid': '6ebf8dd2-60a2-455a-9383-97b81f535366'}}\n```\n\nA rule that always evaluates to `true` is not very useful, so let's change the rule to only print the the value of `foo` if the `foo` key is present in the event's payload, and `no foo :(` otherwise:\n\n```yaml\n---\n- name: Listen to webhook events\n  hosts: all\n  sources:\n    - ansible.eda.webhook:\n        host: 0.0.0.0\n        port: 5000\n  rules:\n    - name: Foo\n      condition: event.payload.foo is defined\n      action:\n        debug:\n          msg: \"{{ event.payload.foo }}\"\n    - name: No foo\n      condition: 1 == 1\n      action:\n        debug:\n          msg: \"no foo :(\"\n```\n\nSend the same `curl` request again and check the logs, you should see a line saying `bar` now.\n\nLet's also try a `curl` request with a different payload:\n\n```console\ncurl \\\n  -X POST \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"bar\": \"baz\"}' \\\n  http://localhost:5000/endpoint\n```\n\nThis time, the output should be `no foo :(`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eRestarting Services Automatically with EDA\u003c/summary\u003e\n\n#### Restarting Services Automatically with EDA\n\nThe last lab is more of a demo - it shows how you can use EDA to automatically react on events observed by **Prometheus** and **Alertmanager**.\n\nFor this demo, the second **ruleset** in our rulebook is the one we're interested in:\n\n```yaml\n- name: Listen to Alertmanager alerts\n  hosts: all\n  sources:\n    - ansible.eda.alertmanager:\n        host: 0.0.0.0\n        port: 9000\n        data_alerts_path: alerts\n        data_host_path: labels.instance\n        data_path_separator: .\n  rules:\n    - name: Restart MySQL server\n      condition: event.alert.labels.alertname == 'MySQL not running' and event.alert.status == 'firing'\n      action:\n        run_playbook:\n          name: ./playbook.yml\n    - name: Debug event output\n      condition: 1 == 1\n      action:\n        debug:\n          msg: \"{{ event }}\"\n```\n\nWith this rule, we can restart our MySQL server if it's not running! But how do we get the event to trigger? With **Prometheus** and **Alertmanager**!\n\nWhen you ran the setup playbook, it installed **Prometheus** and **Alertmanager** on the `eda-controller.example.com` VM. You can access the **Prometheus** UI at `http://\u003ceda-controller-ip\u003e:9090` and the **Alertmanager** UI at `http://\u003ceda-controller-ip\u003e:9093`.\n\nIt also installed a **Prometheus exporter** for the **MySQL** database that runs on the server.\n\nWith this setup, we can now shut down our MySQL server and see what happens - make sure to watch the output of the EDA controller's logs:\n\n```console\nsystemctl stop mysql\njournalctl -fu edacontroller\n```\n\n\nWithin 30-90 seconds, you should see EDA running our **playbook** and restarting the MySQL server. You can track that process by watching the Prometheus/Alertmanager UIs for firing alerts.\n\nOnce you see the playbook being executed in the logs, you can check the MySQL state once more:\n\n```console\nsystemctl status mysql\n```\n\nMySQL should be up and running again!\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmocdaniel%2Flab-event-driven-ansible","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmocdaniel%2Flab-event-driven-ansible","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmocdaniel%2Flab-event-driven-ansible/lists"}