事件源插件
事件来自事件源。事件驱动的自动化使用插件系统支持许多事件源。事件源插件可以存储在本地,但最好通过集合分发。
Ansible.eda 是包含我们初始事件源插件集的集合。这些包括
- alertmanager
通过来自 alertmanager 的 Webhook 接收事件
- azure_service_bus
从 Azure 服务接收事件
- kafka
通过 Kafka 主题接收事件
- url_check
轮询一组 URL 并发送其状态的事件
- watchdog
监视文件系统并在文件状态更改时发送事件
- webhook
提供一个 Webhook 并接收来自它的事件
- tick
生成具有不断增加的索引 i 的事件,永不结束 主要用于开发和测试
- file
最初从 YAML 文件加载事实,并在任何文件更改时重新加载 主要用于开发和测试
- range
在范围内生成具有递增索引 i 的事件 主要用于开发和测试
如何开发自定义插件
您可以使用 Python 构建自己的事件源插件。插件是一个单独的 Python 文件,但在我们开始之前,让我们先看看一些最佳实践和模式
最佳实践和模式
在考虑新的源插件时,您将针对三种基本模式进行开发
- 事件总线插件
这些插件侦听来自源的事件流,其中连接由插件本身建立。例如
kafka
和aws_sqs_queue
插件。这是最理想和可靠的模式。数据的持久性和可靠性由事件源负责,数据的可用性可以遵循事件源及其自身内部配置的模式。
- 抓取插件
这些插件连接到源并从源抓取数据,通常在经过一定时间后。例如
url_check
和watchdog
插件。这些插件可能是可靠的,但可能需要提取逻辑来处理重复。如果在数据可用时抓取程序未运行,则也可能会丢失数据。
- 回调插件
这些插件提供一个回调端点,当数据可用时,事件源可以调用该端点。例如
webhook
和alertmanager
插件。这些插件的可靠性最低,因为它们依赖于事件源来调用回调端点,并且对数据丢失非常敏感。如果事件源不可用或回调端点不可用,则可能没有其他机会接收数据。
这些可能还需要其他入口策略和防火墙规则才能正常运行并进行正确配置。
强烈建议采用前两种模式之一,并且仅在没有其他解决方案的情况下才考虑回调插件。
在决定是否构建专用插件时,您可以考虑将数据源配置为将数据发送到已经存在更通用插件的系统。例如,如果您有一个可以将数据发送到 Kafka 主题的系统,那么您可以使用 kafka
插件接收数据。有许多连接器用于将系统绑定到其他消息总线,这是一种利用现有插件的好方法。
插件模板
让我们看一下一个非常基本的示例,您可以将其用作生成其他插件的模板
"""
template.py
An ansible-rulebook event source plugin template.
Arguments:
- delay: seconds to wait between events
Examples:
sources:
- template:
delay: 1
"""
import asyncio
from typing import Any, Dict
async def main(queue: asyncio.Queue, args: Dict[str, Any]):
delay = args.get("delay", 0)
while True:
await queue.put(dict(template=dict(msg="hello world")))
await asyncio.sleep(delay)
if __name__ == "__main__":
class MockQueue:
async def put(self, event):
print(event)
mock_arguments = dict()
asyncio.run(main(MockQueue(), mock_arguments))
插件入口点
插件 Python 文件必须包含一个与以下完全相同的入口点函数
async def main(queue: asyncio.Queue, args: Dict[str, Any]):
这是一个异步函数。第一个参数是一个 asyncio 队列,ansible-rulebook CLI 将使用它。其余参数是自定义定义的。它们必须与规则手册的 source 部分中的参数匹配。例如,模板插件需要一个名为 delay
的参数。在规则手册中,source 部分如下所示
- name: example
hosts: all
sources:
- template:
delay: 5
每个 source 必须包含一个键,该键是插件的名称。它的嵌套键必须与主函数期望的参数名称匹配。插件的名称是 Python 文件名。如果插件来自集合,则插件名称是 FQCN,它是集合名称连接 Python 文件名,并以句点分隔,例如 ansible.eda.range
。
在主函数中,您可以实现连接到外部事件源、检索事件并将它们放入提供的 asyncio 队列中的代码。放入队列中的事件数据必须是字典。您可以插入 meta
键,该键指向另一个包含主机列表的字典。这些主机将限制 Ansible playbook 可以在哪里运行。一个简单的示例如下所示:{"i": 2, "meta": {hosts: "localhost"}}
。 hosts
可以是逗号分隔的字符串或主机名列表。
由于插件可以完全访问由 ansible-rulebbok 使用的无界队列,因此我们谨慎建议始终使用 asyncio.Queue.put
方法放置事件,因为它是非阻塞调用。为了释放 CPU 周期以供事件循环处理事件,我们建议在 put
方法后立即使用 asyncio.sleep(0)
。
注意
ansible-rulebook 旨在成为一个长期运行的进程,并随着时间的推移对事件做出反应。如果**任何源**的 main
函数退出,则 ansible-rulebook 进程将终止。通常,您可能希望实现一个持续运行并无限期等待事件的循环。
注意
规则手册可以通过 shutdown
操作包含其自身的逻辑来完成进程。如果您的插件需要在进程终止前执行某些清理操作,则必须捕获 asyncio.CancelledError
异常。
分发插件
对于本地测试,插件源文件可以保存在 ansible-rulebook CLI 中 -S
参数指定的文件夹下。分发和安装插件的推荐方法是通过集合。在这种情况下,插件源文件应放在 extensions/eda/plugins/event_source
文件夹下,并由 FQCN 引用。以下规则手册示例说明了如何引用由 ansible.eda
集合提供的 range 插件
- name: example2
hosts: localhost
sources:
- name: range
ansible.eda.range:
limit: 5
自定义插件所需的任何依赖项包都应安装在 ansible-rulebook CLI 环境中,无论插件是本地的还是来自集合的。
文档插件
强烈建议您在源文件顶部添加注释。请描述事件源插件的目的。列出所有必需或可选参数。还要添加一个示例,说明如何在规则手册中配置插件。