如何在Ansible单个when子句中检查循环任务所有迭代的执行结果
解决Ansible循环任务全跳过的条件判断问题
我明白你遇到的问题了——Jinja2确实不支持Python那种列表推导式的写法,但我们可以用Ansible内置的Jinja2过滤器来实现相同的逻辑,而且写法更简洁!
最优解决方案:使用map + all过滤器
Jinja2有内置的all过滤器,结合map提取每个循环结果的skipped属性,就能轻松判断所有迭代是否都被跳过:
- command: "svn commit {{dest}}/{{client}} --username user --password password --non-interactive -m 'Configuration for {{client}}'" when: > svn_add is defined and not (svn_add.results | map(attribute='skipped') | all)
代码解释:
svn_add is defined:先确保svn_add变量存在(避免前面的svn_add任务因条件不满足被跳过导致变量未定义的错误)svn_add.results | map(attribute='skipped'):遍历循环任务的所有结果,提取每个结果的skipped属性值(得到一个由True/False组成的迭代器)| all:检查迭代器里的所有值是否都是True(即所有迭代都被跳过)not (...):取反,意思是“不是所有迭代都被跳过”——也就是至少有一个svn add任务执行了,这时候才触发svn commit
其他替代方案
如果你更喜欢直观的长度判断,也可以用selectattr或rejectattr过滤器:
方案1:筛选未被跳过的结果,判断长度是否大于0
when: > svn_add is defined and (svn_add.results | rejectattr('skipped') | list | length > 0)
rejectattr('skipped'):排除所有被跳过的结果| list | length > 0:如果剩下的结果数量大于0,说明有任务执行过
方案2:统计被跳过的结果数量是否等于总迭代数
when: > svn_add is defined and not (svn_add.results | selectattr('skipped') | list | length == svn_add.results | length)
selectattr('skipped'):筛选出所有被跳过的结果- 比较其数量是否等于总迭代数,取反后就是“不是全部被跳过”
补充说明
如果你还需要保留原来的svn_add is changed条件(判断是否有任务实际执行了变更),可以把两个条件结合起来:
when: > svn_add is defined and svn_add is changed and not (svn_add.results | map(attribute='skipped') | all)
内容的提问来源于stack exchange,提问作者Nicola Musatti
相关产品推荐
相关产品推荐

