1 | |
2 |
|
3 | |
4 | * Save config |
5 | * Copy the running configuration to the startup configuration (`copy running-config startup-config`) so it survives a reload. |
6 | */ |
7 | export async function main(auth: RT.CiscoNxos) { |
8 | const command = "copy running-config startup-config" |
9 | const [output] = await nxapi(auth, "cli_show_ascii", [command]) |
10 |
|
11 | return { command, output: output?.body ?? "" } |
12 | } |
13 |
|
14 | type NxapiOutput = { |
15 | input?: string |
16 | body?: any |
17 | code: string |
18 | msg?: string |
19 | clierror?: string |
20 | } |
21 |
|
22 | async function nxapi( |
23 | auth: RT.CiscoNxos, |
24 | type: "cli_show" | "cli_show_ascii" | "cli_conf", |
25 | commands: string[] |
26 | ): Promise<NxapiOutput[]> { |
27 | const response = await fetch(new URL("/ins", auth.base_url), { |
28 | method: "POST", |
29 | headers: { |
30 | Authorization: `Basic ${btoa(`${auth.username}:${auth.password}`)}`, |
31 | "Content-Type": "application/json", |
32 | Accept: "application/json", |
33 | }, |
34 | |
35 | body: JSON.stringify({ |
36 | ins_api: { |
37 | version: "1.0", |
38 | type, |
39 | chunk: "0", |
40 | sid: null, |
41 | input: commands.join(" ;"), |
42 | output_format: "json", |
43 | }, |
44 | }), |
45 | }) |
46 |
|
47 | if (!response.ok) { |
48 | throw new Error(`${response.status} ${await response.text()}`) |
49 | } |
50 | const text = await response.text() |
51 | if (text.trimStart().startsWith("<")) { |
52 | |
53 | throw new Error( |
54 | `NX-API returned XML instead of JSON (outputs over 1 MB come back as XML): ${text.slice(0, 500)}` |
55 | ) |
56 | } |
57 |
|
58 | const data = JSON.parse(text) |
59 | const raw = data?.ins_api?.outputs?.output |
60 | const outputs: NxapiOutput[] = |
61 | raw == null ? [] : Array.isArray(raw) ? raw : [raw] |
62 | for (const o of outputs) { |
63 | if (String(o.code) !== "200") { |
64 | throw new Error( |
65 | `${o.code} ${o.input ?? ""}: ${o.msg ?? ""} ${o.clierror ?? ""}`.trim() |
66 | ) |
67 | } |
68 | } |
69 | return outputs |
70 | } |
71 |
|