0

Run show commands

by
Published today

Run up to 10 show commands on a Cisco Nexus switch through NX-API and return each output as structured JSON or plain text.

Script cisco_nxos Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 3 hours ago
1
//native
2

3
/**
4
 * Run show commands
5
 * Run up to 10 show commands on a Cisco Nexus switch through NX-API and return the output of each, as structured JSON (cli_show) or as plain text (cli_show_ascii).
6
 */
7
export async function main(
8
  auth: RT.CiscoNxos,
9
  commands: string[],
10
  output_format: "json" | "text" | undefined
11
) {
12
  const cmds = (commands ?? []).map((c) => c.trim()).filter((c) => c !== "")
13
  if (cmds.length === 0) {
14
    throw new Error("Provide at least one show command")
15
  }
16
  // NX-API splits input on ';', and in text mode it runs any exec command:
17
  // keep this action to show commands.
18
  for (const c of cmds) {
19
    if (!/^show\s/i.test(c) || c.includes(";")) {
20
      throw new Error(`Not a single show command: ${c}`)
21
    }
22
  }
23
  // NX-API ignores show commands past the 10th in a single request
24
  if (cmds.length > 10) {
25
    throw new Error("NX-API accepts at most 10 show commands per request")
26
  }
27

28
  const type =
29
    (output_format || "json") === "text" ? "cli_show_ascii" : "cli_show"
30
  const outputs = await nxapi(auth, type, cmds)
31

32
  return outputs.map((o, i) => ({
33
    command: o.input ?? cmds[i],
34
    output: o.body,
35
  }))
36
}
37

38
type NxapiOutput = {
39
  input?: string
40
  body?: any
41
  code: string
42
  msg?: string
43
  clierror?: string
44
}
45

46
async function nxapi(
47
  auth: RT.CiscoNxos,
48
  type: "cli_show" | "cli_show_ascii" | "cli_conf",
49
  commands: string[]
50
): Promise<NxapiOutput[]> {
51
  const response = await fetch(new URL("/ins", auth.base_url), {
52
    method: "POST",
53
    headers: {
54
      Authorization: `Basic ${btoa(`${auth.username}:${auth.password}`)}`,
55
      "Content-Type": "application/json",
56
      Accept: "application/json",
57
    },
58
    // Keep "type" before "input": some NX-OS releases misparse the payload otherwise
59
    body: JSON.stringify({
60
      ins_api: {
61
        version: "1.0",
62
        type,
63
        chunk: "0",
64
        sid: null,
65
        input: commands.join(" ;"),
66
        output_format: "json",
67
      },
68
    }),
69
  })
70

71
  if (!response.ok) {
72
    throw new Error(`${response.status} ${await response.text()}`)
73
  }
74
  const text = await response.text()
75
  if (text.trimStart().startsWith("<")) {
76
    // NX-API falls back to XML when the output exceeds 1 MB
77
    throw new Error(
78
      `NX-API returned XML instead of JSON (outputs over 1 MB come back as XML): ${text.slice(0, 500)}`
79
    )
80
  }
81

82
  const data = JSON.parse(text)
83
  const raw = data?.ins_api?.outputs?.output
84
  const outputs: NxapiOutput[] =
85
    raw == null ? [] : Array.isArray(raw) ? raw : [raw]
86
  for (const o of outputs) {
87
    if (String(o.code) !== "200") {
88
      throw new Error(
89
        `${o.code} ${o.input ?? ""}: ${o.msg ?? ""} ${o.clierror ?? ""}`.trim()
90
      )
91
    }
92
  }
93
  return outputs
94
}
95