| 1 | # List nodes via Netdata Cloud |
| 2 | |
| 3 | This guide is part of the [`query-netdata-cloud`](./SKILL.md) skill. |
| 4 | Read the [SKILL.md prerequisites](./SKILL.md#prerequisites) first. |
| 5 | |
| 6 | For a single agent's own identity (`/api/v3/info` direct, hardware |
| 7 | labels, vnodes, parent/child role), see |
| 8 | [../query-netdata-agents/query-nodes.md](../query-netdata-agents/query-nodes.md). |
| 9 | This file covers the **Cloud-side** enumeration -- nodes across a |
| 10 | room, across a space, with full metadata payloads. |
| 11 | |
| 12 | --- |
| 13 | |
| 14 | ## Endpoints |
| 15 | |
| 16 | | Method | Path | Purpose | |
| 17 | |---|---|---| |
| 18 | | `POST` | `/api/v3/spaces/{spaceID}/rooms/{roomID}/nodes` | List nodes in a room (full metadata) | |
| 19 | |
| 20 | The body is `{}` for "all nodes in the room" or accepts |
| 21 | filters/options that mirror the metrics-query body's |
| 22 | `scope`/`selectors` shape -- see |
| 23 | [query-metrics.md](./query-metrics.md) for the cross-cutting |
| 24 | filter language. |
| 25 | |
| 26 | ## Use the wrapper |
| 27 | |
| 28 | ```bash |
| 29 | source "$(git rev-parse --show-toplevel)/.agents/skills/query-netdata-agents/scripts/_lib.sh" |
| 30 | agents_load_env |
| 31 | |
| 32 | agents_query_cloud POST "/api/v3/spaces/$SPACE/rooms/$ROOM/nodes" '{}' |
| 33 | ``` |
| 34 | |
| 35 | The wrapper emits only the response body; `NETDATA_CLOUD_TOKEN` |
| 36 | never reaches stdout. |
| 37 | |
| 38 | ## Per-node response fields |
| 39 | |
| 40 | Verified live -- response is a JSON array, each entry an object: |
| 41 | |
| 42 | | Field | Description | |
| 43 | |---|---| |
| 44 | | `nd` | **Node UUID.** This is the value to pass anywhere the API expects a node id (e.g. `/api/v2/nodes/{nd}/function?...`) | |
| 45 | | `mg` | Machine GUID (stable per OS install) | |
| 46 | | `nm` | Hostname | |
| 47 | | `state` | `reachable` (live) / `stale` (disconnected) / `offline` | |
| 48 | | `v` | Agent version (e.g. `v2.10.3-nightly`) | |
| 49 | | `labels` | Object: all `_*` chart-labels keyed by name (architecture, kernel, OS, CPU count, RAM, container/k8s/cloud-provider info) | |
| 50 | | `hw` | `{cpus, memory, disk_space, architecture}` summary | |
| 51 | | `os` | `{nm, v, kernel}` summary | |
| 52 | | `health` | Alert-status summary: `{status, alerts: {warning, critical}}` | |
| 53 | | `capabilities` | Feature flags: `ml`, `funcs`, `health`, etc. | |
| 54 | | `room_memberships` | Other rooms this node is in | |
| 55 | | `eligibility` | Per-feature eligibility (e.g. for paid features) | |
| 56 | | `replication`, `replication_factor` | Streaming / parent-child replication state | |
| 57 | | `isPreferred` | Whether the node is the preferred parent for its room | |
| 58 | |
| 59 | ## Common patterns |
| 60 | |
| 61 | ```bash |
| 62 | # Hostname -> node UUID lookup. |
| 63 | agents_query_cloud POST "/api/v3/spaces/$SPACE/rooms/$ROOM/nodes" '{}' \ |
| 64 | | jq -r --arg HOST "costa-desktop" '.[] | select(.nm==$HOST) | .nd' |
| 65 | |
| 66 | # All "reachable" nodes' (UUID, hostname, version) tuples. |
| 67 | agents_query_cloud POST "/api/v3/spaces/$SPACE/rooms/$ROOM/nodes" '{}' \ |
| 68 | | jq -r '.[] | select(.state=="reachable") | "\(.nd)\t\(.nm)\t\(.v)"' |
| 69 | |
| 70 | # Nodes whose label `_is_parent` is true. |
| 71 | agents_query_cloud POST "/api/v3/spaces/$SPACE/rooms/$ROOM/nodes" '{}' \ |
| 72 | | jq -r '.[] | select(.labels._is_parent=="true") | .nm' |
| 73 | |
| 74 | # Aggregate by cloud provider. |
| 75 | agents_query_cloud POST "/api/v3/spaces/$SPACE/rooms/$ROOM/nodes" '{}' \ |
| 76 | | jq -r '[.[] | .labels._cloud_provider_type // "unknown"] | group_by(.) | map({(.[0]): length}) | add' |
| 77 | ``` |
| 78 | |
| 79 | ## Hardware / OS facts |
| 80 | |
| 81 | Hardware and OS facts live in `.labels`: |
| 82 | |
| 83 | | Question | Field | |
| 84 | |---|---| |
| 85 | | CPU architecture | `.labels._architecture` | |
| 86 | | Kernel version | `.labels._kernel_version` | |
| 87 | | OS name / version | `.labels._os_name`, `._os_version` | |
| 88 | | CPU cores | `.labels._system_cores` | |
| 89 | | Total RAM (bytes) | `.labels._system_ram_total` | |
| 90 | | Total disk space (bytes) | `.labels._system_disk_space` | |
| 91 | | Container / virt | `.labels._container`, `._is_k8s_node` | |
| 92 | | Cloud provider / region / instance type | `.labels._cloud_provider_type`, `._cloud_instance_region`, `._cloud_instance_type` | |
| 93 | | Parent role | `.labels._is_parent` (`"true"` / `"false"` strings) | |
| 94 | |
| 95 | For deeper per-host introspection (vnodes, failed jobs, claim_id), |
| 96 | fall through to the agent-direct path in |
| 97 | [../query-netdata-agents/query-nodes.md](../query-netdata-agents/query-nodes.md) |
| 98 | and [../query-netdata-agents/query-dyncfg.md](../query-netdata-agents/query-dyncfg.md). |
| 99 | |
| 100 | ## Limits and gotchas |
| 101 | |
| 102 | - **Stale nodes appear in the list** -- always check `.state` |
| 103 | before issuing further queries against `nd`. |
| 104 | - **The full label set is large** (50+ keys per node). Use |
| 105 | `jq` projections to keep responses readable. |
| 106 | - **Cross-room view requires re-querying.** A node can be in |
| 107 | multiple rooms; use `room_memberships` to detect duplicates |
| 108 | when aggregating across rooms. |
| 109 | - **Multi-space view requires multiple Cloud calls.** Iterate |
| 110 | over `/api/v2/spaces` -> `/api/v2/spaces/{sp}/rooms` -> |
| 111 | `/api/v3/spaces/{sp}/rooms/{rm}/nodes`. |
| 112 | |
| 113 | ## See also |
| 114 | |
| 115 | - [query-rooms.md](./query-rooms.md) -- enumerate rooms (and |
| 116 | their `node_count`, `member_count`, permissions). |
| 117 | - [query-functions.md](./query-functions.md) -- invoke a Function |
| 118 | on a specific node by UUID. |
| 119 | - [../query-netdata-agents/query-nodes.md](../query-netdata-agents/query-nodes.md) |
| 120 | -- single-host identity, vnodes, claim_id. |