断言是把隐患提前
断言的本质是在动手前把假设摊开:磁盘够不够、变量有没有被正确覆盖、清单里的主机是不是预期的环境、上一步的输出是否符合预期。它本身不改变任何状态,因此天然幂等,反复执行只有 ok。代价是断言写得不合适会把正常情况判成失败,所以每条断言都必须对应一个真实的前置条件。
基本信息
| 模块 | ansible.builtin.assert 做条件断言,ansible.builtin.fail 主动中止 |
|---|---|
| 求值位置 | 条件在控制节点求值,引用的是已完成采集的事实与已注册的变量 |
| 常用参数 | that 为条件列表,fail_msg 与 success_msg 自定义提示,quiet 减少成功输出 |
| 配套项 | any_errors_fatal 让失败立即中止整批主机 |
| 前置依赖 | 引用事实前必须确认该事实已采集,否则变量未定义直接报错 |
| 幂等性 | 断言不做修改,不会产生 changed |
典型使用场景
- 容量前置检查:磁盘剩余空间低于阈值时立即中止,不进入安装流程
- 变量完整性:关键参数未定义或取值仍为占位符时立刻失败
- 清单正确性:断言主机名与预期环境后缀匹配,防止拿错清单
- 结果校验:断言上一步命令输出的关键字段,而不是只看退出码
- 环境一致性:断言目标机的发行版与预期一致,避免跨系统误操作
- 收尾验收:变更后断言服务端口可达、配置文件校验通过
断言写法
断言写法
- name: 前置检查:空间与参数
ansible.builtin.assert:
that:
- ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first > min_free_bytes
- app_version is defined and app_version != 'PLACEHOLDER'
fail_msg: "前置条件不满足:可用空间不足或版本参数未填写"
success_msg: "前置检查通过"
quiet: true
- name: 结果校验:不只看退出码
ansible.builtin.shell: /usr/local/bin/app --check-config
register: cfg_check
changed_when: false
- name: 断言输出包含期望关键字
ansible.builtin.assert:
that:
- cfg_check.rc == 0
- "'OK' in cfg_check.stdout"
fail_msg: "配置校验未通过:{{ cfg_check.stdout }}"
- name: 主动中止(用于逻辑上不应继续的情况)
ansible.builtin.fail:
msg: "检测到未支持的系统家族 {{ ansible_os_family }},已中止"
when: ansible_os_family not in ['Debian', 'RedHat']断言类型与写法要点
| 类型 | 位置 | 要点 |
|---|---|---|
| 前置条件 | 变更动作之前 | 失败要给出可操作的提示,说明缺什么 |
| 结果校验 | 变更动作之后 | 校验业务字段而非只看退出码 |
| 环境自检 | 剧本开头 | 防止清单或目标机与预期不符 |
| 容量与版本 | 安装前 | 阈值用变量表达,便于按环境调整 |
| 兜底分支 | 条件分支末尾 | 未覆盖的情况主动失败,不要静默跳过 |
断言失败信息值得花时间写:它出现在失败输出与通知里,是接警人唯一能看到的上下文。写清“哪台主机、哪个参数、期望什么”,而不是只丢一句“条件不满足”。
断言过多会制造脆性:把临时状态、精确版本号、与业务无关的输出都写成断言,环境稍有变化就整体失败,团队随后倾向于绕过检查。只断言真正影响正确性的条件。
与幂等的关系
断言本身不写入任何东西,所以它不会破坏“连跑两次第二次无变更”的性质。真正的风险在断言引用的数据:如果依赖的是命令输出而该命令被跳过,或者依赖缓存里的事实而事实已过期,断言就会基于旧值放行或误拦。把断言建立在稳定、可解释的数据来源上,比堆更多断言更重要。