jcloude/press/api/callbacks.py
2025-12-23 21:34:08 +08:00

117 lines
2.8 KiB
Python

# Copyright (c) 2019, JINGROW
# For license information, please see license.txt
from __future__ import annotations
import ipaddress
import jingrow
from jcloude.agent import Agent
from jcloude.jcloude.pagetype.agent_job.agent_job import handle_polled_job
from jcloude.utils import log_error
def check_ip_version(remote_addr: str):
try:
return ipaddress.ip_interface(remote_addr).version
except ValueError:
return None
def validate_server_request(remote_addr: str):
version = check_ip_version(remote_addr)
if version == 4:
server = jingrow.get_value("Server", {"ip": remote_addr})
elif version == 6:
# Added this here, however fc does not support ipv6
remote_addr = f"{remote_addr.split('::')[0]}::"
server = jingrow.get_value("Server", {"ipv6": remote_addr})
else:
server = None
return server
def verify_job_id(server: str, job_id: str):
return jingrow.get_value("Agent Job", {"server": server, "job_id": job_id})
def handle_job_updates(server: str, job_identifier: str):
server_info = jingrow.get_value(
"Server",
{"name": server},
fieldname=[
"use_for_build",
"use_agent_job_callbacks",
],
as_dict=True,
)
if not server_info.use_for_build:
return
current_user = jingrow.session.user
try:
jingrow.set_user("Administrator")
job_id = job_identifier
agent = Agent(server, "Server")
jcloude_settings_use_callbacks = jingrow.get_value(
"Jcloude Settings", fieldname=["use_agent_job_callbacks"]
)
if not jcloude_settings_use_callbacks or not server_info.use_agent_job_callbacks:
return
# For some reason output is not returned when job returns from rq callback
polled_job = agent.get_job_status(job_id)
job = jingrow.get_value(
"Agent Job",
fieldname=[
"name",
"job_id",
"status",
"callback_failure_count",
"job_type",
],
filters={"job_id": job_id},
as_dict=True,
)
callback = jingrow.get_pg(
{
"pagetype": "Agent Job Callback",
"job_name": job.job_type,
"agent_job": polled_job["agent_job_id"],
"status": polled_job["status"],
}
)
callback.insert()
handle_polled_job(polled_job=polled_job, job=job)
except Exception as e:
log_error("Failed to process agent job callback", data=e)
raise
finally:
jingrow.set_user(current_user)
@jingrow.whitelist(allow_guest=True)
def callback(job_id: str):
"""
Handle job updates sent from agent.
This api should ideally only be hit from a build server.
"""
remote_addr = jingrow.request.environ["HTTP_X_FORWARDED_FOR"]
server = validate_server_request(remote_addr)
# Request origin not authorized to update job status.
if not server:
jingrow.throw("Not permitted", jingrow.ValidationError)
job = verify_job_id(server, job_id)
if not job:
jingrow.throw("Invalid Job Id", jingrow.ValidationError)
jingrow.enqueue(handle_job_updates, server=server, job_identifier=job_id)