3.5 插件 Plugins 扩展


3.5 插件 Plugins 扩展

本节摘要:插件是引擎每个环节的可替换零件:连接、策略、回调、过滤、查找、清单、动作等类型各管一段。本节建立插件类型的全景索引,讲清两大高频类型——查找与过滤——的日常用法,并给出"何时该写自定义插件"的判断标准。模块是任务的原子,插件是引擎的关节,两者别混。

先分清插件与模块

新手最容易把插件与模块混为一谈。区分方法一句话:模块在目标机上执行、产出 changed 判定,出现在 tasks 列表里;插件在控制机上工作、改变引擎某环节的行为,通常不出现在任务列表里。template 模块背后干活的是模板插件,清单文件背后解析的是清单插件,你从没在 tasks 里写过它们,但每次运行都在消费它们。

插件类型全景

按生命线的位置排布七类主力插件。连接插件决定"怎么到目标机"(ssh、local、docker、httpapi);清单插件决定"目标机列表从哪来"(ini、yaml、各云厂商动态清单);策略插件决定"任务跨主机怎么推进"(linear、free,第 2.2 节已见面);回调插件决定"结果如何呈现与外送"(默认控制台输出、profile_tasks 计时、对接消息系统的通知类);过滤与查找插件决定"模板表达式能做什么"(default、dict2items、file 查找、env 读取);动作插件是模块的执行骨架(普通用户少直接接触);缓存插件决定"事实收集结果存哪"(第 6 章性能优化会启用 redis 或 jsonfile 缓存)。

这张全景图的实际用途是定位问题:输出格式不对找回调,跨主机取数不顺找查找,执行节奏不符合预期找策略——每一类症状都指向确定的插件类型。

查找插件:控制机的数据入口

lookup 在任务执行时于控制机侧取数,是剧本消费外部信息的正规通道。四个高频成员:

tasks: - name: 读取环境变量(缺省兜底) ansible.builtin.debug: msg: "构建号 {{ lookup('ansible.builtin.env', 'BUILD_ID') | default('dev') }}" - name: 把本地授权文件读进变量 ansible.builtin.set_fact: license_text: "{{ lookup('ansible.builtin.file', '/etc/stardust/license.txt') }}" - name: CSV 批量开号:每次循环取一行字段 ansible.builtin.user: name: "{{ item.name }}" uid: "{{ item.uid }}" loop: "{{ query('ansible.builtin.csvfile', 'name uid', 'file=team.csv', 'col=0') }}" - name: 引用加密库里的数据库口令(配合 Vault) ansible.builtin.set_fact: db_pass: "{{ lookup('ansible.builtin.file', 'secrets/db.txt') }}"

lookup 返回字符串,query 返回列表(多值场景用 query 更顺手,它是对 lookup 的列表化包装)。上面第四例是 lookup 与 Vault 的经典组合:加密文件在仓库里是密文,lookup 读取时解密,敏感值全程不落明文——第 4.3 节展开完整的加密体系。

过滤与测试:表达式的左右手

过滤插件上一节已经大量使用(default、dict2items、ternary 都是过滤插件家族的成员),这里补上它的孪生兄弟——测试(tests):过滤器做值的加工,测试做条件的判断,用在 when 里。

- name: 过滤器与测试的配合 ansible.builtin.assert: that: - app_version is defined # 测试:是否定义 - app_version is match(r'\d+\.\d+\.\d+') # 测试:正则匹配 - replicas | int is even # 过滤后测试:偶数

assert 模块加测试的组合是剧本防御的顶配:发布剧本开头把所有前置假设写成断言(版本格式、必填变量、目标组非空),不满足立刻停——错误前移到第一秒,比跑到一半失败便宜得多。

自定义插件的时机与写法

什么时候该写自定义插件而不是继续堆 YAML?三个信号:同一套过滤逻辑在三个以上模板里复制粘贴(写过滤插件);要对接内部系统的通知或审计(写回调插件);机器列表来自内部 CMDB 的私有 API(写清单插件或用现有清单插件的配置面)。

自定义过滤插件是三者里最容易的入门款,一个 Python 文件放对目录即生效:

# filter_plugins/stardust.py —— 项目目录下的 filter_plugins 文件夹 def env_label(name, region): """把服务名与区域拼成规范的标签""" return "{}-{}".format(region, name.replace("_", "-")) class FilterModule(object): def filters(self): return {"env_label": env_label}
- name: 在模板与 when 里直接使用自定义过滤器 ansible.builtin.debug: msg: "部署标签 {{ 'order_service' | env_label('cn-north') }}" # 输出:部署标签 cn-north-order-service

写插件的纪律是"只写被复用三次以上的逻辑":插件的维护成本高于剧本,一次性需求留在剧本里就好。

图 3-5:插件类型与生命线站点的对应

图 3-5:插件类型与生命线站点的对应

插件层的使用度建议

团队实践的合理深度分三档:日常档,用现成插件(查找、过滤、云清单)加配置即可;进阶档,沉淀一两个自定义过滤插件与计时回调配置;架构档,对接 CMDB 与审计系统时写清单与回调插件。绝大多数团队长期停留在前两档,这完全正常——插件体系的定位是给引擎"留门",不是让每个团队都来造零件。## 一个过滤插件从需求到上线的完整走查

把自定义插件的开发过程走一遍完整示例,需求来自真实场景:团队要求所有主机名在配置里以"区域-环境-服务"格式出现,而清单里三个字段分散存放,模板里到处拼字符串。第一步,判断时机:拼串逻辑已出现在五个模板里,命中"复用三次以上"标准,该写插件。第二步,实现与测试:函数本体十行(区域、环境、服务名三参数拼接加合法性校验),配套写一个 pytest 单测覆盖空值与非法字符两个边界。第三步,接入:过滤插件放进项目的 filter_plugins 目录即刻生效,五个模板改为调用统一过滤器。第四步,沉淀:单测进流水线,插件的参数说明写进 README。全程半天以内,收益是五处拼串逻辑归一。这个走查想展示的是插件开发的"轻":过滤插件的门槛远比想象低,Python 函数加一个注册类就是全部骨架。真正的门槛在时机判断与测试配套——写插件不难,写出值得维护的插件才需要纪律。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U