scripts/discover-unifi: correct field selectors for real API response shape
Raw dumps of /ea/hosts and /ea/devices surfaced the actual JSON:
- /ea/hosts: LAN IP isn't at top-level ipAddress (that's WAN public);
it's buried in reportedState.ipAddrs[] mixed with WAN + link-local.
Have to pick the first RFC1918 entry that ISN'T also a WAN interface
IP (reportedState.wans[].ipv4). Name/mac/model all live under
reportedState.{hostname,mac,hardware.shortname}.
- /ea/devices: outer records are per-host wrappers; real AP/switch
records are in the nested `devices` array with top-level `ip`, `mac`,
`name`, `model` fields. Previous parser was reading the wrapper and
getting all `-`.
Reorder all TSV outputs so IP is column 1 — makes discover-gaps.sh
work uniformly against both FortiGate and UniFi sources. Sites TSV
dropped its IP slot since sites have no meaningful IP (metadata only).
Verified against the real payloads the user captured: ESH-UDMPM now
surfaces as 10.0.0.1 (LAN) instead of 192.168.200.111 (WAN2, RFC1918
but excluded via the wans cross-check). A sample device record
(E7-ESH-Media at 10.0.250.176) flattens correctly into a single TSV row.
This commit is contained in:
+39
-17
@@ -20,15 +20,19 @@
|
||||
# UNIFI_API_KEY=...
|
||||
# and source it before calling.
|
||||
#
|
||||
# Output: TSV on stdout. Column layout depends on the endpoint:
|
||||
# Output: TSV on stdout. IP is column 1 for hosts/devices so these can
|
||||
# be piped into discover-gaps.sh directly:
|
||||
#
|
||||
# hosts: host_id host_name host_ip model_name controller_version
|
||||
# sites: site_id site_name host_id description
|
||||
# devices: mac ip name model site_id host_id
|
||||
# hosts: IP MAC NAME MODEL FW_VERSION SOURCE
|
||||
# (IP is LAN — picked from reportedState.ipAddrs first
|
||||
# private-range entry; falls back to WAN if none found)
|
||||
# devices: IP MAC NAME MODEL HOST_NAME SOURCE
|
||||
# (APs, switches — the actual network equipment)
|
||||
# sites: SITE_ID SITE_NAME HOST_ID SOURCE
|
||||
# (metadata only — no IP column, not useful for gap analysis)
|
||||
#
|
||||
# Each row ends with a SOURCE column so outputs can be concatenated and
|
||||
# still distinguished:
|
||||
# unifi:<endpoint>
|
||||
# SOURCE column is "unifi:<endpoint>" so concatenated outputs stay
|
||||
# distinguishable.
|
||||
#
|
||||
# Requires: curl + jq (apt install jq).
|
||||
|
||||
@@ -107,12 +111,27 @@ ui_get() {
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
emit_hosts() {
|
||||
# LAN IP is the first RFC1918 entry in reportedState.ipAddrs that is
|
||||
# NOT also present as a WAN ipv4 (reportedState.wans[]) — UDMs with
|
||||
# RFC1918-addressed WAN2 interfaces would otherwise get mis-picked as
|
||||
# their LAN IP. Falls back through the usual chain if nothing matches.
|
||||
ui_get /ea/hosts | jq -r '
|
||||
. as $h |
|
||||
(($h.reportedState.wans // []) | map(.ipv4 // empty)) as $wans |
|
||||
[
|
||||
(.id // "-"),
|
||||
(.hardware.name // .userData.name // .reportedState.name // "-"),
|
||||
(.ipAddress // .reportedState.ip // "-"),
|
||||
(.hardware.shortname // .type // "-"),
|
||||
(
|
||||
([(.reportedState.ipAddrs // [])[] | select(
|
||||
(test("^10\\.") or
|
||||
test("^192\\.168\\.") or
|
||||
test("^172\\.(1[6-9]|2[0-9]|3[0-1])\\.")
|
||||
) and
|
||||
(. as $ip | ($wans | index($ip)) == null)
|
||||
)] | .[0])
|
||||
// .reportedState.ip // .ipAddress // "-"
|
||||
),
|
||||
(.reportedState.mac // "-"),
|
||||
(.reportedState.hostname // .reportedState.name // "-"),
|
||||
(.reportedState.hardware.shortname // .reportedState.hardware.name // .type // "-"),
|
||||
(.reportedState.version // "-"),
|
||||
"unifi:hosts"
|
||||
] | @tsv
|
||||
@@ -120,26 +139,29 @@ emit_hosts() {
|
||||
}
|
||||
|
||||
emit_sites() {
|
||||
# Sites have no IP — no point running these through discover-gaps.sh.
|
||||
# Kept here for inventory purposes only.
|
||||
ui_get /ea/sites | jq -r '
|
||||
[
|
||||
(.siteId // .id // "-"),
|
||||
(.meta.name // .name // "-"),
|
||||
(.hostId // "-"),
|
||||
(.meta.desc // "-"),
|
||||
"unifi:sites"
|
||||
] | @tsv
|
||||
'
|
||||
}
|
||||
|
||||
emit_devices() {
|
||||
# /ea/devices returns per-host wrappers; flatten into one row per AP/switch.
|
||||
ui_get /ea/devices | jq -r '
|
||||
. as $h |
|
||||
(.devices // [])[] |
|
||||
[
|
||||
(.mac // "-"),
|
||||
(.ip // "-"),
|
||||
(.name // .hardware.name // "-"),
|
||||
(.model // .hardware.shortname // "-"),
|
||||
(.siteId // "-"),
|
||||
(.hostId // "-"),
|
||||
(.mac // .id // "-"),
|
||||
(.name // "-"),
|
||||
(.model // .shortname // "-"),
|
||||
($h.hostName // $h.hostId // "-"),
|
||||
"unifi:devices"
|
||||
] | @tsv
|
||||
'
|
||||
|
||||
Reference in New Issue
Block a user