Edits history of script submission #23995 for ' Cancel job (awx)'

  • bunnative
    One script reply has been approved by the moderators
    Ap­pro­ved
    //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