1 | |
2 |
|
3 | |
4 | * Get configlet |
5 | * Get one provisioning configlet (legacy Network Provisioning API) by name, with its key and config. |
6 | */ |
7 | export async function main(auth: RT.AristaCloudvision, name: string) { |
8 | return await cv( |
9 | auth, |
10 | `/cvpservice/configlet/getConfigletByName.do?name=${encodeURIComponent(name)}`, |
11 | { notFound: `Configlet ${name} not found` } |
12 | ) |
13 | } |
14 |
|
15 | |
16 | |
17 | async function cv( |
18 | auth: RT.AristaCloudvision, |
19 | path: string, |
20 | options: { body?: unknown; notFound?: string; optional?: boolean } = {} |
21 | ): Promise<any> { |
22 | const url = new URL(path, auth.base_url) |
23 | |
24 | |
25 | |
26 | const cvaas = auth.deployment |
27 | ? auth.deployment === "cvaas" |
28 | : /(^|\.)arista\.io\.?$/i.test(url.hostname) |
29 | if (!cvaas && url.pathname.startsWith("/cvpservice/")) { |
30 | url.pathname = url.pathname.replace(/^\/cvpservice\//, "/web/") |
31 | } |
32 | const response = await fetch(url, { |
33 | method: options.body === undefined ? "GET" : "POST", |
34 | headers: { |
35 | Authorization: `Bearer ${auth.token}`, |
36 | ...(options.body === undefined |
37 | ? {} |
38 | : { "Content-Type": "application/json" }), |
39 | Accept: "application/json", |
40 | }, |
41 | body: options.body === undefined ? undefined : JSON.stringify(options.body), |
42 | }) |
43 | const text = await response.text() |
44 | if ( |
45 | response.status === 401 || |
46 | response.status === 403 || |
47 | (!response.ok && text.includes("User is unauthorized")) |
48 | ) { |
49 | throw new Error( |
50 | `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}` |
51 | ) |
52 | } |
53 | const data = |
54 | text.trim() === "" |
55 | ? {} |
56 | : /^\s*[[{]/.test(text) |
57 | ? JSON.parse(text) |
58 | : undefined |
59 | const error = findError(data) |
60 | if (response.ok && data !== undefined && !error) return data |
61 | const detail = error |
62 | ? `${error.errorCode} ${error.errorMessage ?? (error.errors ?? []).join("; ")}` |
63 | : `HTTP ${response.status} ${text.slice(0, 500)}` |
64 | |
65 | |
66 | if ( |
67 | response.status === 404 || |
68 | (error && (options.optional || options.notFound)) |
69 | ) { |
70 | if (options.optional) return undefined |
71 | if (options.notFound) throw new Error(`${options.notFound} (${detail})`) |
72 | } |
73 | if (response.ok && !error) { |
74 | throw new Error( |
75 | `CloudVision returned a non-JSON response for ${url.pathname}: check that base_url is the CloudVision address. ${detail}` |
76 | ) |
77 | } |
78 | throw new Error(`CloudVision ${url.pathname} failed: ${detail}`) |
79 | } |
80 |
|
81 | function findError(value: any): any { |
82 | if (!value || typeof value !== "object") return undefined |
83 | |
84 | if (!Array.isArray(value) && value.errorCode) return value |
85 | for (const item of Object.values(value)) { |
86 | const error = findError(item) |
87 | if (error) return error |
88 | } |
89 | return undefined |
90 | } |
91 |
|