如何通过Job ID在Flask API中查询异步Ansible Playbook运行状态?
通过Job ID查询Ansible异步Playbook运行状态的实现方案
核心思路
要实现状态查询,关键是把每个异步任务的Job ID和对应的ansible_runner.Runner实例绑定存储,后续通过Job ID从存储中取出Runner对象,就能获取实时运行状态。
具体实现步骤
1. 初始化任务存储
首先需要一个存储结构来保存Job ID与Runner实例、线程的映射关系。开发阶段可以用内存字典,生产环境建议用Redis、MongoDB这类持久化存储,避免服务重启后数据丢失:
from flask import Flask, jsonify, request import ansible_runner import uuid import threading app = Flask(__name__) # 内存存储任务信息,生产环境替换为Redis/数据库 job_store = {}
2. 实现提交Playbook的端点
在提交任务时生成唯一Job ID,启动异步Playbook,并将Runner实例、线程及初始状态存入存储:
@app.route('/run-playbook', methods=['POST']) def run_playbook(): # 从请求参数获取playbook路径、inventory等配置 playbook_path = request.json.get('playbook_path') inventory = request.json.get('inventory') # 生成唯一Job ID job_id = str(uuid.uuid4()) # 初始化Runner并启动异步线程 runner = ansible_runner.Runner( playbook=playbook_path, inventory=inventory, # 可添加其他ansible_runner配置(如extra_vars等) ) thread = threading.Thread(target=runner.run) thread.start() # 存入任务信息 job_store[job_id] = { 'runner': runner, 'thread': thread, 'status': 'running' } return jsonify({'job_id': job_id, 'status': 'started'})
3. 实现状态查询端点
根据传入的Job ID,从存储中取出Runner对象,实时更新并返回任务状态:
@app.route('/job-status/<job_id>', methods=['GET']) def get_job_status(job_id): if job_id not in job_store: return jsonify({'error': 'Job ID not found'}), 404 job_info = job_store[job_id] runner = job_info['runner'] thread = job_info['thread'] # 同步最新状态 if not thread.is_alive(): job_info['status'] = 'completed' if runner.status == 'successful' else 'failed' else: job_info['status'] = 'running' # 返回核心状态信息,可按需扩展(如日志片段、执行进度) response = { 'job_id': job_id, 'status': job_info['status'], 'ansible_internal_status': runner.status, 'return_code': runner.rc # 0表示成功,非0表示失败 } return jsonify(response)
生产环境优化建议
- 替换内存存储:用Redis哈希结构或数据库持久化任务状态(注意Runner实例无法序列化,可在任务结束后提取状态、返回码、日志路径等信息存储)。
- 任务清理:定期清理已完成的任务记录,避免存储资源浪费。
- 日志扩展:将ansible_runner的日志路径与Job ID绑定,查询端点可提供日志片段或下载接口,方便用户排查问题。
内容的提问来源于stack exchange,提问作者Pitto
相关产品推荐
相关产品推荐

