//native
/**
* Cancel job
* Cancel a pending or running job or workflow job. Checks can_cancel first: a job that already finished is left alone and returned with canceled false. Set job_type to workflow_job for a workflow job id.
*/
export async function main(
auth: RT.Awx,
job_id: number,
job_type: "job" | "workflow_job" | undefined
) {
const collection = job_type === "workflow_job" ? "workflow_jobs" : "jobs"
const url = new URL(`${apiRoot(auth)}/${collection}/${job_id}/cancel/`)
const check = await fetch(url, {
headers: {
Authorization: authorization(auth),
Accept: "application/json",
},
})
if (!check.ok) {
throw new Error(`${check.status} ${await check.text()}`)
}
const { can_cancel } = (await check.json()) as { can_cancel: boolean }
if (!can_cancel) {
return { job_id, job_type: job_type || "job", canceled: false }
}
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: authorization(auth),
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({}),
})
// 405: the job finished between the check and the cancel.
if (response.status === 405) {
return { job_id, job_type: job_type || "job", canceled: false }
}
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
return { job_id, job_type: job_type || "job", canceled: true }
}
function apiRoot(auth: RT.Awx) {
const path = (auth.api_path || "/api/v2").replace(/^\/+|\/+$/g, "")
// Tolerate a base_url pasted with the API path already on it.
const base = auth.base_url
.replace(/\/+$/, "")
.replace(new RegExp(`/${path}$`), "")
return `${base}/${path}`
}
function authorization(auth: RT.Awx) {
if (auth.token) {
return `Bearer ${auth.token}`
}
if (auth.username) {
const bytes = new TextEncoder().encode(
`${auth.username}:${auth.password ?? ""}`
)
return `Basic ${btoa(String.fromCharCode(...bytes))}`
}
throw new Error(
"The AWX resource needs either a token or a username and password"
)
}
Submitted by hugo989 3 hours ago