Parses netbird status --json output into LibclusterMesh.Peer structs.
The relevant shape (see OutputOverview / PeerStateDetailOutput in
netbirdio/netbird client/status/status.go) is:
{"peers": {"details": [{"fqdn": "...", "netbirdIp": "...", "status": "Connected", ...}]}}A peer counts as online when its status is "Connected" or "Idle" —
with NetBird's lazy connections an idle peer is reachable on demand, and
the incoming distribution connection is exactly what wakes it up.
Summary
Functions
Parses the JSON status output. Never raises: peers with missing or
unexpected fields are skipped, and undecodable input is surfaced as
{:error, message}.
The name this node answers to on the mesh, or nil.
Functions
@spec parse_peers(String.t()) :: {:ok, [LibclusterMesh.Peer.t()]} | {:error, String.t()}
Parses the JSON status output. Never raises: peers with missing or
unexpected fields are skipped, and undecodable input is surfaced as
{:error, message}.
iex> json = ~S({"peers": {"details": [{"fqdn": "myapp-1.netbird.cloud",
...> "netbirdIp": "100.94.0.5/16", "status": "Connected"}]}})
iex> LibclusterMesh.NetbirdStatus.parse_peers(json)
{:ok, [%LibclusterMesh.Peer{ip: "100.94.0.5", hostname: "myapp-1", online?: true}]}
iex> LibclusterMesh.NetbirdStatus.parse_peers(~S({"peers": {"details": []}}))
{:ok, []}
The name this node answers to on the mesh, or nil.
Not in peers.details — a node is not something to connect to — but it is
the one entry a person is guaranteed to be looking at, so anything showing
the mesh by name needs it separately.
iex> LibclusterMesh.NetbirdStatus.parse_self(~S({"fqdn": "myapp-1.netbird.cloud"}))
"myapp-1"
iex> LibclusterMesh.NetbirdStatus.parse_self(~S({"peers": {"details": []}}))
nil