Edits history of script submission #24162 for ' List tasks (arista_cloudvision)'

  • bunnative
    One script reply has been approved by the moderators
    Ap­pro­ved
    //native
    
    /**
     * List tasks
     * List provisioning tasks (legacy Network Provisioning API), pending ones by default. Each task has its workOrderId, the device it targets and its workOrderUserDefinedStatus (Pending, Completed, Failed, Cancelled). CloudVision pages them by index: end_index 0 returns all of them.
     */
    export async function main(
      auth: RT.AristaCloudvision,
      status: "Pending" | "Completed" | "Failed" | "Cancelled" | "All" = "Pending",
      start_index: number = 0,
      end_index: number = 0
    ) {
      const query = status === "All" ? "" : status || "Pending"
      return await cv(
        auth,
        `/cvpservice/task/getTasks.do?queryparam=${encodeURIComponent(query)}&startIndex=${start_index ?? 0}&endIndex=${end_index ?? 0}`
      )
    }
    
    // Calls CloudVision and turns its failures into readable errors. Legacy
    // endpoints report errors as HTTP 200 with an errorCode field.
    async function cv(
      auth: RT.AristaCloudvision,
      path: string,
      options: { body?: unknown; notFound?: string; optional?: boolean } = {}
    ): Promise<any> {
      const url = new URL(path, auth.base_url)
      // cvprac sends legacy endpoints to /cvpservice on CVaaS and /web on
      // on-premises CVP. Its is_cvaas flag is the resource's deployment field;
      // when that is unset, a host under arista.io is taken as CVaaS.
      const cvaas = auth.deployment
        ? auth.deployment === "cvaas"
        : /(^|\.)arista\.io\.?$/i.test(url.hostname)
      if (!cvaas && url.pathname.startsWith("/cvpservice/")) {
        url.pathname = url.pathname.replace(/^\/cvpservice\//, "/web/")
      }
      const response = await fetch(url, {
        method: options.body === undefined ? "GET" : "POST",
        headers: {
          Authorization: `Bearer ${auth.token}`,
          ...(options.body === undefined
            ? {}
            : { "Content-Type": "application/json" }),
          Accept: "application/json",
        },
        body: options.body === undefined ? undefined : JSON.stringify(options.body),
      })
      const text = await response.text()
      if (
        response.status === 401 ||
        response.status === 403 ||
        (!response.ok && text.includes("User is unauthorized"))
      ) {
        throw new Error(
          `CloudVision refused the token (HTTP ${response.status}): check that the service-account token is valid, not expired, and that its role allows this call. ${text}`
        )
      }
      const data =
        text.trim() === ""
          ? {}
          : /^\s*[[{]/.test(text)
            ? JSON.parse(text)
            : undefined
      const error = findError(data)
      if (response.ok && data !== undefined && !error) return data
      const detail = error
        ? `${error.errorCode} ${error.errorMessage ?? (error.errors ?? []).join("; ")}`
        : `HTTP ${response.status} ${text.slice(0, 500)}`
      // Legacy lookups answer an unknown name or ID with an errorCode (cvprac
      // treats any error from getTaskById and getImageBundleByName that way).
      if (
        response.status === 404 ||
        (error && (options.optional || options.notFound))
      ) {
        if (options.optional) return undefined
        if (options.notFound) throw new Error(`${options.notFound} (${detail})`)
      }
      if (response.ok && !error) {
        throw new Error(
          `CloudVision returned a non-JSON response for ${url.pathname}: check that base_url is the CloudVision address. ${detail}`
        )
      }
      throw new Error(`CloudVision ${url.pathname} failed: ${detail}`)
    }
    
    function findError(value: any): any {
      if (!value || typeof value !== "object") return undefined
      // Like cvprac, only a truthy errorCode counts, at any depth.
      if (!Array.isArray(value) && value.errorCode) return value
      for (const item of Object.values(value)) {
        const error = findError(item)
        if (error) return error
      }
      return undefined
    }
    

    Submitted by hugo989 5 hours ago