pi/validation/auto_ssh.nix
2026-04-04 19:45:40 +02:00

75 lines
2.6 KiB
Nix

let
lib = import <nixpkgs/lib>;
getDevices = net:
if net ? devices && builtins.isAttrs net.devices then
net.devices
else
throw "config/network.nix must define devices as an attrset.";
getAutoSshDevices = devices:
lib.filterAttrs (_: device:
if !builtins.isAttrs device then
throw "Every device in config/network.nix.devices must be an attrset."
else if !(device ? type) then
throw "Every device in config/network.nix.devices must define a type."
else
device.type == "auto_ssh"
) devices;
getAutoSshDomains = autoSshDevices:
map (device:
if !(device ? domain) || !builtins.isString device.domain || device.domain == "" then
throw "Every auto_ssh device in config/network.nix must define domain as a non-empty string."
else
device.domain
) (builtins.attrValues autoSshDevices);
getAutoSshConfig = deviceName: device:
if !(device ? auto_ssh) then
throw "Auto SSH device '${deviceName}' is missing required field: auto_ssh."
else if !builtins.isAttrs device.auto_ssh then
throw "Auto SSH device '${deviceName}' field auto_ssh must be an attrset."
else
device.auto_ssh;
getRemotePortMap = device:
if !(device ? auto_ssh) then
[]
else if !builtins.isAttrs device.auto_ssh then
throw "Device auto_ssh must be an attrset when present."
else if !(device.auto_ssh ? remotePortMap) then
[]
else if !builtins.isList device.auto_ssh.remotePortMap then
throw "Device auto_ssh.remotePortMap must be a list of { localPort = int; remotePort = int; }."
else if !lib.all (entry:
builtins.isAttrs entry
&& entry ? localPort
&& entry ? remotePort
&& builtins.isInt entry.localPort
&& builtins.isInt entry.remotePort
) device.auto_ssh.remotePortMap then
throw "Every remotePortMap entry must be { localPort = int; remotePort = int; }."
else
device.auto_ssh.remotePortMap;
getPortOffset = device:
if !(device ? auto_ssh) then
0
else if !builtins.isAttrs device.auto_ssh then
throw "Device auto_ssh must be an attrset when present."
else if !(device.auto_ssh ? portOffset) then
0
else if !builtins.isInt device.auto_ssh.portOffset then
throw "Device auto_ssh.portOffset must be an int."
else if device.auto_ssh.portOffset < 0 then
throw "Device auto_ssh.portOffset must be >= 0."
else
device.auto_ssh.portOffset;
isSafeName = name:
builtins.match "^[a-z_][a-z0-9_-]*$" name != null;
in
{
inherit getDevices getAutoSshDevices getAutoSshDomains getAutoSshConfig getRemotePortMap getPortOffset isSafeName;
}