//native
/**
* Save config
* Copy the running configuration to the startup configuration (`copy running-config startup-config`) so it survives a reload.
*/
export async function main(auth: RT.CiscoNxos) {
const command = "copy running-config startup-config"
const [output] = await nxapi(auth, "cli_show_ascii", [command])
return { command, output: output?.body ?? "" }
}
type NxapiOutput = {
input?: string
body?: any
code: string
msg?: string
clierror?: string
}
async function nxapi(
auth: RT.CiscoNxos,
type: "cli_show" | "cli_show_ascii" | "cli_conf",
commands: string[]
): Promise<NxapiOutput[]> {
const response = await fetch(new URL("/ins", auth.base_url), {
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${auth.username}:${auth.password}`)}`,
"Content-Type": "application/json",
Accept: "application/json",
},
// Keep "type" before "input": some NX-OS releases misparse the payload otherwise
body: JSON.stringify({
ins_api: {
version: "1.0",
type,
chunk: "0",
sid: null,
input: commands.join(" ;"),
output_format: "json",
},
}),
})
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
const text = await response.text()
if (text.trimStart().startsWith("<")) {
// NX-API falls back to XML when the output exceeds 1 MB
throw new Error(
`NX-API returned XML instead of JSON (outputs over 1 MB come back as XML): ${text.slice(0, 500)}`
)
}
const data = JSON.parse(text)
const raw = data?.ins_api?.outputs?.output
const outputs: NxapiOutput[] =
raw == null ? [] : Array.isArray(raw) ? raw : [raw]
for (const o of outputs) {
if (String(o.code) !== "200") {
throw new Error(
`${o.code} ${o.input ?? ""}: ${o.msg ?? ""} ${o.clierror ?? ""}`.trim()
)
}
}
return outputs
}
Submitted by hugo989 3 hours ago