Ansible Tower/AAP API分页查询及时间匹配问题求助
问题与解决方案:Ansible Tower/AAP Jobs API 数据查询优化
初始问题:获取最新半小时任务数据的分页困境
需要在Playbook中查询Ansible Tower的Jobs REST API,获取最近半小时的任务数据。最初使用以下代码拉取数据:
- name: Pull Jobs Data uri: url: https://ansible.xxxx.com/api/v2/jobs/?format=json&page=1&page_size=200 headers: Content-Type: application/json Authorization: "Bearer {{ lookup('env', 'TOWER_PASSWORD') }}" register: jobs_data - name: Get last half hour of data debug: var: "{{item}}" when: - item['started'] > current_epoch_half_hour_back loop: "{{ jobs_data['json']['results'] }}"
但由于数据保留两周(约15000页),page=1返回的是最旧数据,无法获取最新内容。且红帽建议不要修改配置文件将page_size调至200以上,因此需要一种无需硬编码页码、从最新数据开始查询的方法。
问题更新:排序解决分页顺序,但时间筛选失效
添加负序排序参数后解决了分页顺序问题,让page=1返回最新数据:
url: https://aap.prci.com/api/v2/jobs/?format=json&page=1&page_size=600&order_by=-{{'started'}}
但在AAP中,最近半小时数据的筛选条件失效(该条件在Tower中可正常工作)。当前生成时间参数并筛选的代码如下:
- set_fact: half_hour_back: "{{ '%Y-%m-%dT%H:%M:%S'|strftime((ansible_date_time.epoch|int) - (60*60*0.5)) }}" - name: Add jobs data to dictionary set_fact: list_of_jobs_info: "{{ list_of_jobs_info + [{ 'job_id' : item['id'], 'job_name' : item['name'], 'job_status' : item['status'] }] }}" when: - item['status'] == "canceled" - item['started'] > half_hour_back loop: "{{ jobs_data['json']['results'] }}"
API返回的started字段格式为:
"started": "2022-11-15T20:00:07.881083Z"
推测AAP API对数据类型/格式检查更严格,需要生成匹配格式的half_hour_back变量以实现正确的时间比较。
解决方案
1. 从最新数据开始查询(无需硬编码页码)
使用API的order_by参数按started字段倒序排序,这样page=1直接返回最新的任务数据,无需定位到最后一页。结合分页遍历,直到获取到半小时前的数据或没有更多分页:
- name: Pull latest Jobs Data (page 1, sorted by started descending) uri: url: "https://aap.prci.com/api/v2/jobs/?format=json&page=1&page_size=200&order_by=-started" headers: Content-Type: application/json Authorization: "Bearer {{ lookup('env', 'TOWER_PASSWORD') }}" register: jobs_data - name: Initialize jobs list set_fact: list_of_jobs_info: [] current_page: 1 - name: Iterate through pages to collect recent jobs uri: url: "https://aap.prci.com/api/v2/jobs/?format=json&page={{ current_page }}&page_size=200&order_by=-started" headers: Content-Type: application/json Authorization: "Bearer {{ lookup('env', 'TOWER_PASSWORD') }}" register: current_page_data until: - current_page_data.json.results | selectattr('started', '<=', half_hour_back) | list | length > 0 - current_page_data.json.next is not defined loop_control: extended: yes when: current_page_data.json.next is defined or current_page == 1 register: all_jobs_data # 后续处理所有页面的数据...
2. 修复时间比较的格式问题
AAP中字符串形式的时间比较是严格的字典序,之前生成的half_hour_back缺少毫秒部分和时区标识Z,导致比较逻辑失效。有两种可靠的解决方式:
方式一:统一转换为时间戳比较
将API返回的started时间字符串转换为Unix时间戳,与提前计算好的半小时前的时间戳对比:
- set_fact: half_hour_back_epoch: "{{ (ansible_date_time.epoch | int) - 1800 }}" # 30分钟=1800秒 - name: Add jobs data to dictionary set_fact: list_of_jobs_info: "{{ list_of_jobs_info + [{ 'job_id' : item['id'], 'job_name' : item['name'], 'job_status' : item['status'] }] }}" when: - item['status'] == "canceled" - (item['started'] | to_datetime('%Y-%m-%dT%H:%M:%S.%fZ')).strftime('%s') | int > half_hour_back_epoch loop: "{{ jobs_data['json']['results'] }}"
方式二:生成完全匹配格式的时间字符串
生成包含毫秒(设为000000)和时区Z的时间字符串,确保与API返回格式一致:
- set_fact: half_hour_back: "{{ '%Y-%m-%dT%H:%M:%S.000000Z' | strftime((ansible_date_time.epoch | int) - 1800) }}" - name: Add jobs data to dictionary set_fact: list_of_jobs_info: "{{ list_of_jobs_info + [{ 'job_id' : item['id'], 'job_name' : item['name'], 'job_status' : item['status'] }] }}" when: - item['status'] == "canceled" - item['started'] > half_hour_back loop: "{{ jobs_data['json']['results'] }}"
内容的提问来源于stack exchange,提问作者abrahavt
相关产品推荐
相关产品推荐

