Edits history of script submission #24068 for ' Get device interfaces (akips)'

  • bunnative
    One script reply has been approved by the moderators
    Ap­pro­ved
    //native
    
    /**
     * Get device interfaces
     * Get the interfaces of one device with their IF-MIB attributes (ifDescr, ifAlias, ifAdminStatus, ifOperStatus, ifSpeed, ...). Optionally narrow to one interface name or /regex/.
     */
    export async function main(
      auth: RT.Akips,
      device: string,
      interface_name: string | undefined
    ) {
      const cmd = `mget * ${device} ${interface_name || "*"} /^IF-MIB\\./`
    
      // A line break starts a second api-db command (§4.5.2 data), so inputs must stay on one line.
      if (/[\r\n]/.test(cmd)) throw new Error("api-db command must be a single line")
    
      // Documented form (API guide §4.5.2): password in the URL, commands in the POST body.
      const url = new URL(`${auth.base_url}/api-db`)
      url.searchParams.append("username", auth.username)
      url.searchParams.append("password", auth.password)
      const response = await fetch(url, {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: new URLSearchParams({ cmds: cmd }),
      }).catch((e) => {
        // Network errors quote the full URL: drop the query string, which holds the password.
        throw new Error(String(e).replaceAll(url.search, ""))
      })
      const text = await response.text()
      if (!response.ok || text.startsWith("ERROR:")) {
        throw new Error(`${response.status} ${text}`)
      }
    
      // Each line: "{device} {interface} IF-MIB.{attribute} = {value}"
      const byInterface = new Map<string, { [key: string]: string }>()
      for (const line of text.split("\n")) {
        const match = line.match(/^(\S+)\s+(\S+)\s+IF-MIB\.(\S+)\s+=\s?(.*)$/)
        if (!match) continue
        const [, , name, attribute, value] = match
        if (!byInterface.has(name)) byInterface.set(name, {})
        byInterface.get(name)![attribute] = value
      }
    
      // Enum values are "{number},{text},{created},{modified}[,{child description}]"
      const enumText = (v: string | undefined) =>
        v == null ? undefined : v.split(",")[1]
    
      const interfaces = [...byInterface.entries()].map(([name, a]) => ({
        name,
        descr: a["ifDescr"],
        alias: a["ifAlias"],
        admin_status: enumText(a["ifAdminStatus"]),
        oper_status: enumText(a["ifOperStatus"]),
        attributes: a,
      }))
    
      return { device, count: interfaces.length, interfaces }
    }
    

    Submitted by hugo989 6 hours ago