{ config, options, lib, ... }: with lib; let netOpts = { name, ... }: { options = { vlan = mkOption { description = "VLAN tag number"; type = types.int; }; subnet4 = mkOption { description = "v.w.x.y/z"; type = with types; nullOr str; default = null; }; subnets6 = mkOption { description = "IPv6 subnets w/o prefixlen (always 64)"; type = with types; attrsOf str; default = {}; }; }; }; interfaceOpts = { name, ... }: { options = { hwaddr = mkOption { type = with types; nullOr str; default = null; }; type = mkOption { type = types.enum [ "veth" "phys" ]; }; gw = mkOption { type = with types; nullOr str; default = null; }; gw6 = mkOption { type = with types; nullOr str; default = null; }; }; }; hostOpts = { name, ... }: { options = { role = mkOption { type = types.enum [ "ap" "switch" "server" "container" "client" ]; default = "client"; }; model = mkOption { type = types.str; default = { ap = "unknown"; switch = "unknown"; server = "pc"; container = "lxc"; client = "any"; }."${config.site.hosts.${name}.role}"; }; password = mkOption { type = with types; nullOr str; default = null; }; location = mkOption { type = with types; nullOr str; default = null; }; interfaces = mkOption { default = {}; type = with types; attrsOf (submodule interfaceOpts); }; }; }; in { options.site = { net = mkOption { default = {}; type = with types; attrsOf (submodule netOpts); }; hosts = mkOption { default = {}; type = with types; attrsOf (submodule hostOpts); }; }; config.warnings = let findCollisions = getter: xs: (builtins.foldl' ({ known, dup }: k: let ks = builtins.toString k; in if known ? ${ks} then { inherit known; dup = dup ++ [ks]; } else { known = known // { ${ks} = true; }; inherit dup; } ) { known = {}; dup = []; } ( concatMap getter (builtins.attrValues xs) )).dup; reportCollisions = name: getter: xs: map (k: "Duplicate ${name}: ${k}") (findCollisions getter xs); in (reportCollisions "VLAN tag" (x: [x.vlan]) config.site.net) ++ (reportCollisions "IPv4 subnet" (x: if x.subnet4 == null then [] else [x.subnet4]) config.site.net) ++ (reportCollisions "IPv6 subnet" (x: builtins.attrValues x.subnets6) config.site.net); }