0

Rollback to checkpoint

by
Published today

Roll the running configuration of a Cisco Nexus switch back to a named checkpoint.

Script cisco_nxos Verified

The script

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

3
/**
4
 * Rollback to checkpoint
5
 * Roll the running configuration back to a named checkpoint (`rollback running-config checkpoint <name>`). Atomic mode (the NX-OS default) only applies the rollback if no error occurs; best-effort skips errors; stop-at-first-failure stops at the first error.
6
 */
7
export async function main(
8
  auth: RT.CiscoNxos,
9
  checkpoint_name: string,
10
  mode: "atomic" | "best-effort" | "stop-at-first-failure" | undefined
11
) {
12
  const name = checkpoint_name?.trim()
13
  if (!name) {
14
    throw new Error("checkpoint_name is required")
15
  }
16
  if (/[\s;|]/.test(name)) {
17
    throw new Error("checkpoint_name must not contain spaces, ';' or '|'")
18
  }
19

20
  const command = `rollback running-config checkpoint ${name} ${mode || "atomic"}`
21
  const [output] = await nxapi(auth, "cli_show_ascii", [command])
22

23
  return { command, output: output?.body ?? "" }
24
}
25

26
type NxapiOutput = {
27
  input?: string
28
  body?: any
29
  code: string
30
  msg?: string
31
  clierror?: string
32
}
33

34
async function nxapi(
35
  auth: RT.CiscoNxos,
36
  type: "cli_show" | "cli_show_ascii" | "cli_conf",
37
  commands: string[]
38
): Promise<NxapiOutput[]> {
39
  const response = await fetch(new URL("/ins", auth.base_url), {
40
    method: "POST",
41
    headers: {
42
      Authorization: `Basic ${btoa(`${auth.username}:${auth.password}`)}`,
43
      "Content-Type": "application/json",
44
      Accept: "application/json",
45
    },
46
    // Keep "type" before "input": some NX-OS releases misparse the payload otherwise
47
    body: JSON.stringify({
48
      ins_api: {
49
        version: "1.0",
50
        type,
51
        chunk: "0",
52
        sid: null,
53
        input: commands.join(" ;"),
54
        output_format: "json",
55
      },
56
    }),
57
  })
58

59
  if (!response.ok) {
60
    throw new Error(`${response.status} ${await response.text()}`)
61
  }
62
  const text = await response.text()
63
  if (text.trimStart().startsWith("<")) {
64
    // NX-API falls back to XML when the output exceeds 1 MB
65
    throw new Error(
66
      `NX-API returned XML instead of JSON (outputs over 1 MB come back as XML): ${text.slice(0, 500)}`
67
    )
68
  }
69

70
  const data = JSON.parse(text)
71
  const raw = data?.ins_api?.outputs?.output
72
  const outputs: NxapiOutput[] =
73
    raw == null ? [] : Array.isArray(raw) ? raw : [raw]
74
  for (const o of outputs) {
75
    if (String(o.code) !== "200") {
76
      throw new Error(
77
        `${o.code} ${o.input ?? ""}: ${o.msg ?? ""} ${o.clierror ?? ""}`.trim()
78
      )
79
    }
80
  }
81
  return outputs
82
}
83