Parses wg show <interface> dump output into LibclusterMesh.Peer structs.
The dump format is stable and tab-separated: the first line describes the interface, every following line is a peer:
<public-key> <preshared-key> <endpoint> <allowed-ips> <latest-handshake> <rx> <tx> <keepalive>The peer's mesh address is the first /32 entry in allowed-ips that
falls inside the member CIDR. Both halves of that carry weight. A node is
reached at one address, so an entry covering a range — the mesh itself,
advertised by a subnet router — names no host and is not a candidate. And
a subnet router lists the routes it carries alongside its own address, in
no particular order, so the entry inside the CIDR is the one to take
rather than the first one of any kind.
Plain WireGuard has no hostnames, so hostname is set to the IP string. A
peer counts as online when its latest handshake is no older than
handshake_max_age seconds (WireGuard rekeys about every 2 minutes on
active tunnels).
Summary
Functions
Parses the dump output. now is the current Unix time in seconds and
cidr selects which allowed-ips entry is the peer's mesh address.
Functions
@spec parse_peers(String.t(), integer(), pos_integer(), LibclusterMesh.CIDR.t()) :: {:ok, [LibclusterMesh.Peer.t()]} | {:error, String.t()}
Parses the dump output. now is the current Unix time in seconds and
cidr selects which allowed-ips entry is the peer's mesh address.
Never raises. Unrecognised peer lines are skipped, but output that is not a dump at all is an error rather than an empty mesh — the other three parsers draw that line too, and a cluster that never forms is the hardest failure here to tell from a mesh that is simply quiet.
iex> out = "privkey\tpubkey\t51820\toff\n" <>
...> "peerkey1\t(none)\t172.17.0.3:51820\t192.168.1.0/24,10.77.0.2/32\t1700000000\t1000\t1000\toff\n" <>
...> "peerkey2\t(none)\t(none)\t10.77.0.3/32\t0\t0\t0\toff\n"
iex> cidr = LibclusterMesh.CIDR.parse!("10.77.0.0/24")
iex> LibclusterMesh.WireGuardDump.parse_peers(out, 1700000060, 180, cidr)
{:ok,
[
%LibclusterMesh.Peer{ip: "10.77.0.2", hostname: "10.77.0.2", online?: true},
%LibclusterMesh.Peer{ip: "10.77.0.3", hostname: "10.77.0.3", online?: false}
]}