Ansible递归解析树形字典时dict2items获取未定义值的问题排查
Ansible递归解析树形字典时dict2items获取未定义值的问题排查
嘿,我看了你的问题和代码,很快就发现了两个关键问题导致了这个错误,咱们一步步来拆解:
错误根源分析
1. 正则匹配的测试器用错了!
你写的when: item.key is regex('/$')完全不符合你的需求。Ansible里的is regex测试器是用来判断一个字符串是不是合法的正则表达式,而不是判断字符串是否匹配某个正则。比如'alpha'本身是合法的正则(普通字符串),所以这个条件会对所有item返回true,包括alpha这种不以/结尾的项!
这就导致当处理alpha时,你会把它的value(也就是数字1)传递给下一层的tree变量,而下一层任务里的tree | dict2items要求输入必须是字典,自然就会报错——虽然你的错误信息显示是Undefined,但本质是因为传递了非字典值,加上递归时的变量作用域冲突,才出现了这个看似奇怪的报错。
2. 递归时loop变量的作用域冲突
你在递归调用时一直用item作为loop变量名,Ansible的loop变量是任务级局部的,但多层递归时还是可能出现意想不到的变量覆盖问题,加剧了错误的出现。
修正后的代码
咱们来修改你的proceed_branch.yaml,解决这两个问题:
- debug: msg: "{{ tree }}" - debug: msg: "Got {{ item.key }} = {{ item.value }}" loop: "{{ tree | dict2items }}" when: not item.key ends with '/' - include_tasks: proceed_branch.yaml vars: tree: "{{ branch_item.value }}" loop: "{{ tree | dict2items }}" loop_control: loop_var: branch_item when: branch_item.key ends with '/' and branch_item.value is mapping
修正点说明
- 正确判断结尾字符:把
is regex('/$')改成ends with '/',这是最直观且高效的判断字符串以/结尾的方式,完全符合你的需求。 - 重命名loop变量:用
loop_control: loop_var: branch_item把loop变量改成branch_item,避免和上层的item变量冲突,递归时更清晰。 - 增加字典类型校验:加上
branch_item.value is mapping的判断,确保只有当value是字典(也就是还有子分支)的时候才递归调用,避免传递非字典值导致的报错。
同时,你的playbook里的hosts写法可以稍微调整得更规范一点:
- hosts: localhost tasks: - include_tasks: proceed_branch.yaml vars: tree: alpha: 1 foo/: bravo: 2 bar/: charlie: 3 baz/: delta: 4
这样修改后,就能得到你期望的递归执行结果:依次处理每个非目录项,然后递归进入每个以/结尾的分支,直到所有层级都处理完毕。
备注:内容来源于stack exchange,提问作者Volodymyr Melnyk
相关产品推荐
相关产品推荐

