Ansible 弃用机制详解4 个版本的弃用周期与 Display.deprecated / AnsibleModule.deprecate 实践【免费下载链接】ansibleAnsible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain. Automate everything from code deployment to network configuration to cloud management, in a language that approaches plain English, using SSH, with no agents to install on remote systems. https://docs.ansible.com.项目地址: https://gitcode.com/GitHub_Trending/ans/ansible本文围绕 Ansible 仓库中的向后兼容与弃用Deprecation政策展开先讲清楚“弃用 4 个版本后才移除”的版本节奏如何计算再结合仓库源码剖析Display.deprecated与AnsibleModule.deprecate两个标记 API 的真实签名、消息格式化逻辑以及警告去重与任务级捕获机制。读完之后你将知道如何在贡献代码时正确标注一个即将被移除的功能并理解用户侧看到的[DEPRECATION WARNING]消息是怎么一步步生成的。为什么向后兼容优先context/deprecation.md 开篇只有一句话但它是整个政策的总纲Backward compatibility is prioritized over most other concerns.向后兼容性优先于绝大多数其他考量。Ansible 是一个面向生产环境的自动化平台Playbook、Role 和模块往往在团队与组织间长期复用。一旦某个接口说删就删所有依赖它的用户都会被静默打断。因此仓库采用了一个明确的、可预测的弃用周期先给用户充足的迁移窗口期再执行移除。理解这个周期是正确使用下文两个 API 的前提。弃用周期deprecation 2 个过渡版本 removal文档给出的规则是弃用周期为4 个版本deprecation 2 releases removal标记弃用 2 个中间发布 移除。移除版本的计算方式当前版本 3。当前版本以 lib/ansible/release.py 中的__version__为准。文档中的示例在 2.19 标记弃用意味着在 2.22 移除。也就是说一个功能从“还能正常使用但开始报警告”到“彻底消失”中间有 3 个完整版本的缓冲期。用一个简表来描述时间线版本以 release.py 当前版本 C 计状态用户可见行为Cdeprecation 版本标记弃用运行触发该功能的 Playbook 时打印[DEPRECATION WARNING]功能仍可用C1、C2过渡版本过渡期持续打印弃用警告功能仍可用C3removal 版本移除触发该功能直接报错消息变为“was removed”以当前仓库快照验证这条规则lib/ansible/release.py 中__version__ 2.22.0.dev0即当前开发版本为 2.22按“3”规则现在标记弃用的功能应写移除版本2.25。这也解释了为什么仓库源码中能看到大量version2.23、version2.24之类的弃用调用——它们是前几个版本标记、尚未到达移除点的功能。标记弃用代码的两个官方入口文档“Deprecating code”一节的原话是UseDisplay.deprecatedorAnsibleModule.deprecatewith the removal version.使用Display.deprecated或AnsibleModule.deprecate并带上移除版本。两个 API 分别对应 Ansible 的两类代码场景必须“with the removal version”——即version参数填的是移除版本而不是当前版本这正是上一条“3”规则落到代码里的写法。控制器侧Display.deprecatedDisplay.deprecated定义在 lib/ansible/utils/display.py完整签名为def deprecated( self, msg: str, version: str | None None, removed: bool False, date: str | None None, collection_name: str | None None, *, deprecator: _messages.PluginInfo | None None, help_text: str | None None, obj: t.Any None, ) - None:关键参数说明来自源码 docstring 与实现msg面向用户的弃用说明应说明“什么变了、应该改成什么”。version/date二者只能给其一不能同时给date若使用必须是YYYY-MM-DD格式针对以日期为节奏发布的外部集合。removedTrue表示该功能已到移除点此时消息前缀从[DEPRECATION WARNING]:变为[DEPRECATED]:并且不是打警告而是直接抛出AnsibleError——即“警告”升级为硬错误见 display.py 的实现。help_text给用户的具体迁移指引如替代写法、替代参数名。obj触发弃用的源码对象用于在错误上下文中标注来源位置。collection_name/deprecator大多数调用方无需提供确需指定时二者只给一个内部由_deprecator.get_best_deprecator归一化。仓库中一个真实的调用例子在模板引擎的条件表达式处理里lib/ansible/_internal/_templating/_engine.pyif conditional in (None, ): # deprecated backward-compatible behavior; None/empty input conditionals are always True if _TemplateConfig.allow_broken_conditionals: _display.deprecated( msgEmpty conditional expression was evaluated as True., help_textself._BROKEN_CONDITIONAL_ALLOWED_FRAGMENT, objconditional, version2.23, ) return True raise AnsibleBrokenConditionalError(Empty conditional expressions are not allowed., objconditional)这段代码完整演示了文档要求的全部要素msg说明行为、help_text给出替代方案、obj指向触发源、version2.23是移除版本当前 2.22 基础上 3 以内。同时可以看到典型的“弃用期 移除点”双分支写法过渡期内打弃用警告并保留旧行为移除后同一位置抛出正式异常。模块侧AnsibleModule.deprecate当弃用的代码运行在远端被打包成模块执行的 Python 代码时控制器侧的Display不可用文档因此给出第二个入口AnsibleModule.deprecate定义在 lib/ansible/module_utils/basic.pydef deprecate( self, msg: str, version: str | None None, date: str | None None, collection_name: str | None None, *, deprecator: _messages.PluginInfo | None None, help_text: str | None None, ) - None: Record a deprecation warning to be returned with the module result. ... Specify version or date, but not both. If date is a string, it must be in the form YYYY-MM-DD. 与控制器侧的差异在于模块是“执行完把 JSON 结果发回”的模型没有实时终端可写所以 docstring 明确说明其语义是“Record a deprecation warning to be returned with the module result”——把警告记录进模块结果随结果一起传回控制器最终由回调层展示。参数规则与Display.deprecated一致version与date二选一、日期格式YYYY-MM-DD、version填移除版本。弃用消息的内部处理链知道两个入口之后再看这些警告在 Ansible 内部如何被格式化与分发能解释用户在终端看到的每一段文字。1. 前缀与措辞的拼装。lib/ansible/_internal/_display_utils.py 的get_deprecation_message_with_plugin_info负责生成最终文案未移除时前缀为[DEPRECATION WARNING]:已移除时为[DEPRECATED]:时间片段按“有date→ in a release after date有version→ version version都没有 → in a future release”的规则生成如果removedTrue措辞从 “This feature will be removed” 切换为 “This feature was removed”。函数还会根据deprecator信息把消息归属到具体的集合与插件例如module xxx in collection ansible.builtinbuiltin 集合统一显示为 “ansible-core”。2. 移除点即报错。如前文所述Display._deprecated_with_plugin_info在removedTrue分支中直接raise AnsibleError(formatted_msg)保证移除版本中旧功能一触即错而不是继续静默工作。3. 展示期去重。display.py 中的_deduplicate在“打印时”才对消息做去重同一警告在一个运行内重复触发时只在终端打印一次但注释特别说明去重发生在很晚的阶段“Duplicates included in task results will always be visible to registered variables and callbacks”——注册变量和回调中看到的重复警告不受去重影响避免丢失警告与具体任务的对应关系。4. 任务级延迟捕获。lib/ansible/_internal/_display_utils.py 定义了DeferredWarningContext在该上下文内调用Display.warning()/Display.deprecated()时警告不会被立即打印而是被捕获并附加到任务结果上区分get_warnings()与get_deprecation_warnings()两类由当前激活的显示回调统一呈现给用户。这是“警告必须能被register到的结果看到、也能被任务归属”这一设计目标的具体实现。给贡献者的落地清单综合 context/deprecation.md 的政策与上述源码实现在 Ansible 中标记一个功能弃用时应做到算对移除版本读 lib/ansible/release.py 的__version__移除版本 当前版本 3写version参数时填这个值不要填当前版本。选对入口控制器侧代码解析、执行器、模板引擎等用Display.deprecated模块内代码会在远端执行的lib/ansible/modules/或module_utils用AnsibleModule.deprecate。写清 msg 与 help_textmsg说清被弃用的行为help_text给出替代做法version与date只提供一个。为移除版本准备分支参考 _engine.py 的条件表达式处理 的写法过渡期走弃用警告移除点抛出正式异常或彻底删除旧行为。注意警告的去重与捕获边界终端打印会去重但任务结果、注册变量与回调中仍会保留完整警告不要把“终端只出现一次”当作“只发生了一次”的证据。这套“4 版本周期 两个标记 API 展示期去重/任务级捕获”的组合构成了 Ansible 在快速演进的代码库中仍然能给出稳定迁移路径的机制基础。【免费下载链接】ansibleAnsible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain. Automate everything from code deployment to network configuration to cloud management, in a language that approaches plain English, using SSH, with no agents to install on remote systems. https://docs.ansible.com.项目地址: https://gitcode.com/GitHub_Trending/ans/ansible创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考