Ansible对扁平化数据结构使用until循环条件不生效问题
问题根因
- 你提取到的状态是数组类型(示例输出为
["FAILED", "FAILED"]),直接用数组 in [字符串, 字符串]的逻辑不成立,你实际需要判断数组内所有元素是否都属于终止状态集合['SUCCESS', 'FAILED'] - 第一次循环执行时,
restart_status还未完成赋值,部分接口返回的字段可能为None,导致flatten操作尝试迭代None抛出类型错误 until条件和with_items共用时,默认的变量填充顺序会导致条件判断早于部分请求结果返回,存在逻辑歧义
修复方案
方案1:调整until条件(保留原有任务结构)
直接修改until判断逻辑,增加默认空值处理,同时用all判断所有状态都属于终止集合:
- name: Fetching recycle status uri: url: "http://{{ restarter }}/status?job_id={{ item }}" method: GET body_format: json headers: Accept: 'application/json' return_content: yes register: restart_status with_items: - 14502414 - 14552415 # 增加default([])处理空值,优化json_query写法,用all判断所有状态都在终止集合内 until: restart_status.results | default([]) | json_query('[*].json[].status') | map('in', ['SUCCESS', 'FAILED']) | list is all # 可按需调整重试次数和间隔 retries: 20 delay: 5
这里优化了json_query写法,不需要两次查询+flatten,直接用[*].json[].status就能提取所有状态的平层数组。
方案2:拆分循环(逻辑更清晰,推荐)
如果要避免loop和until共用的逻辑歧义,可以把每个job的查询单独拆成嵌套任务:
- name: Poll each job status include_tasks: poll_job.yml loop: - 14502414 - 14552415 loop_control: loop_var: job_id
单独的poll_job.yml内容:
- name: Fetch status for job {{ job_id }} uri: url: "http://{{ restarter }}/status?job_id={{ job_id }}" method: GET body_format: json headers: Accept: 'application/json' return_content: yes register: single_job_status until: (single_job_status.json | default([]) | first).status in ['SUCCESS', 'FAILED'] retries: 20 delay: 5
额外说明
你之前的报错'NoneType' object is not iterable就是因为没有加default([])处理空值,第一次请求返回异常、json字段为空时就会触发。
内容的提问来源于stack exchange,提问作者sdhir
相关产品推荐
相关产品推荐

