首页/系统与基础设施/自动化运维速查/自定义过滤器插件的开发方法
Ansible 核心70 条

自定义过滤器插件的开发方法

过滤器插件扩展 Jinja2 表达式的加工能力,放在项目 filter_plugins/ 或集合 plugins/filter/ 下,通过类方法注册名字到函数,在模板与 playbook 表达式中以竖线调用。应保持纯函数、入口校验、名字加前缀避免与内置冲突。

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​‌​‌​‌‌‌​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌​‌​‌‌​​‌‌​​‌‌​‌​​‌​‌‌​‌‌​​​‌‌‌​‌​​​‌‌​​‌​‌​‌‌‌​​‌​​​‌​‌‌​‌​‌‌‌​​​​​‌‌​‌‌​​​‌‌‌​‌​‌​‌‌​​‌‌‌​‌‌​‌​​‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌‌​‌‌​​‌‌​​‌​‌​‌‌​‌‌​​​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​‌‌​‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌‌​‌​​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

过滤器插件是什么

过滤器是 Jinja2 表达式里用竖线调用的函数,模板渲染与 playbook 中的变量表达式都会用到它们。当内置过滤器不够用时(例如要按公司规范格式化资产编号、解析自定义时间串、做特定的地址计算),就写一个过滤器插件。它运行在控制节点,纯函数式地取一个值返回一个值,不接触目标机。

基本信息

放置位置项目或角色下的 filter_plugins/ 目录,集合则放 plugins/filter/
注册方式插件文件里定义类并提供 filters 方法,返回“名字 → 可调用对象”的映射
同类扩展test 插件扩展的是“is”判断,写法与过滤器类似
调用位置模板文件与 playbook 变量表达式,写法都是值加竖线加过滤器名
错误处理抛专用异常类型,让报错信息能定位到过滤器而不是模板行
共享代码与模块共用的工具函数放 module_utils,避免两套实现

典型使用场景

  • 统一命名规范:把主机名、资产编号转换成公司约定的展示格式
  • 结构化数据的再加工:从嵌套字典里取出需要的键并拼成配置行
  • 自定义校验:把“是否合法网段”这类判断做成过滤器在模板里复用
  • 兼容历史格式:旧系统配置文件有特殊字段格式,用过滤器在渲染时转换
  • 减少模板判断:把多分支的取值逻辑收敛到过滤器内部,模板保持简洁
  • 跨项目复用:把通用过滤器按集合打包,多个仓库共同引用

写法与调用

写法与调用
# 结构
# filter_plugins/app_filters.py     项目内临时使用
# plugins/filter/app_filters.py    按集合打包(推荐)
#
# 文件内三件事:
# 1) 定义普通函数实现逻辑,保持纯函数:同输入必得同输出
# 2) 参数校验放在函数入口,非法输入抛专用异常类型
# 3) 定义注册类与 filters 方法,把名字映射到函数
#
# 模板中调用(名字与注册名一致)
# {{ inventory_hostname | app_display_name }}
# {{ app_list | app_join_configs(', ') }}
#
# playbook 表达式里同样可用
# vars:
#   label: "{{ ansible_host | app_display_name }}"
#
# 校验:模板渲染任务在检查模式下跑一次,看渲染结果是否符合预期。

与其它扩展方式的取舍

做法优点代价
写成过滤器插件模板与表达式里都能复用,写法统一逻辑只处理数据,无法访问目标机
写成模块能改目标机状态需要一次远程执行,不适合纯数据加工
模板内联判断不用新增文件模板迅速变复杂,多处重复同一逻辑
写成 lookup 插件可以读取外部数据源有副作用或需要网络时判断更复杂
打包进集合可版本化、可分发、带文档需要维护集合结构与发布流程
过滤器名要与内置名字区分开,自定义集合的过滤器通常带命名空间前缀调用。名字撞车时会静默改变原有行为,排查成本很高,用前缀是最省事的规避方式。
过滤器运行在控制节点,能读到控制节点上的环境与文件。不要在其中做时间依赖、随机数、外部命令调用这类有副作用的行为:它会被模板多次渲染调用,结果不可预测,也会让检查模式失去意义。

开发与验证习惯

先写函数、用几条边界输入验证输出,再注册成过滤器,最后放入模板使用。边界至少覆盖:空值、非预期类型、超长输入。把这几条写成小测试留在仓库里,后续新人改动逻辑时能立刻发现回归,比依赖模板渲染结果目测更可靠。

易错点

  • 过滤器名与内置过滤器重名,静默覆盖原有行为,老模板输出发生变化
  • 把访问目标机或调用外部命令的逻辑写进过滤器,模板多次渲染导致结果不可预测
  • 入口不做参数校验,遇到空值或类型不符时抛出难以定位到具体过滤器的错误
  • 把多分支逻辑全塞进模板表达式,模板可读性崩溃且无法单独测试
  • 过滤器与模块各写一套相同的工具函数,行为逐渐分叉

数据来源与参考

  • Ansible 官方文档 Developing plugins: filter plugins
  • Jinja2 官方文档 Filters 与自定义过滤器
  • Ansible 官方文档 集合插件目录结构

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/automation/custom-filter-plugin-development.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​‌​‌​‌‌‌​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌​‌​‌‌​​‌‌​​‌‌​‌​​‌​‌‌​‌‌​​​‌‌‌​‌​​​‌‌​​‌​‌​‌‌‌​​‌​​​‌​‌‌​‌​‌‌‌​​​​​‌‌​‌‌​​​‌‌‌​‌​‌​‌‌​​‌‌‌​‌‌​‌​​‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌‌​‌‌​​‌‌​​‌​‌​‌‌​‌‌​​​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​‌‌​‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌‌​‌​​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​