Ansible循环执行assert检查时出现'item'未定义错误的求助
问题描述
我有一个Ansible Role,用来验证系统上安装的RPM包,任务代码如下:
- name: "[Misc - Validator] Load up user config for testing" command: yum list installed register: yum_listing - name: "[Misc - Validator] Check for values" assert: that: - "{{item.check}} in {{item.file}}.stdout_lines" loop: - { check: rsyncd, file: yum_listing } success_msg: "Misc RPMs installed" fail_msg: "Misc RPMs missing"
但在Ansible 2.12版本中执行时,出现了如下错误:
TASK [tds_validation : [Misc - Validator] Check for values] *******************************************************************
fatal: [testhost-host01.example.net]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined\n\nThe error appears to be in '/etc/ansible/roles/tds_validation/tasks/validators/tds_misc.yml': line 6, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: "[Misc - Validator] Check for values"\n ^ here\n"}
这只是一个简单示例,我希望能扩展这个循环,加入更多检查项,同时支持检查多个不同的寄存器内容,预期执行结果要么是OK要么是Changed状态。
问题原因
出现这个错误的核心原因是任务的缩进不符合Ansible的YAML语法规范:你把loop、success_msg、fail_msg和assert模块放在了同级缩进,但实际上这些选项都应该是assert模块的子参数,需要缩进在assert:下方。
因为缩进错误,Ansible无法将loop和assert任务关联起来,自然就识别不到item变量了。
修正后的代码
调整缩进,把loop、success_msg、fail_msg都放到assert模块的层级下,同时为了避免变量解析的潜在问题,建议把that里的表达式改成不加双大括号的形式(Ansible会自动解析变量):
- name: "[Misc - Validator] Load up user config for testing" command: yum list installed register: yum_listing # 这里可以添加更多register任务,比如检查其他命令输出 - name: "[Misc - Validator] Get another command output" command: some-other-command register: other_output - name: "[Misc - Validator] Check for values" assert: that: - item.check in vars[item.file].stdout_lines success_msg: "Misc RPMs installed" fail_msg: "Misc RPMs missing: {{ item.check }}" loop: - { check: rsyncd, file: yum_listing } # 可以添加更多检查项,关联不同的register - { check: some-package, file: yum_listing } - { check: expected-string, file: other_output }
关键说明:
- 缩进修正:所有属于
assert模块的参数(that、success_msg、fail_msg、loop)都要缩进在assert:下方,确保Ansible能正确识别任务结构。 - 变量引用优化:用
vars[item.file]来动态引用寄存器变量,这样当你需要检查多个不同的register时,只需要在loop里添加对应的file值即可,比直接写{{item.file}}.stdout_lines更可靠,避免解析歧义。 - 扩展检查项:只需要在
loop列表里添加新的字典项,就能轻松扩展更多检查,无论是同一个register还是不同的register都能支持。
执行效果
修正后执行任务,当所有检查项都满足时,会输出成功信息;如果有任意一项不满足,会明确提示缺失的检查内容,方便定位问题。
备注:内容来源于stack exchange,提问作者Systemgeek

