diff --git a/examples/rotuer.nix b/examples/rotuer.nix index 9f757c3..10b549b 100644 --- a/examples/rotuer.nix +++ b/examples/rotuer.nix @@ -119,7 +119,7 @@ in rec { services.dns = let interface = services.int; - in svc.dnsmasq { + in svc.dnsmasq.build { resolvconf = services.resolvconf; inherit interface; ranges = [ diff --git a/modules/dnsmasq/default.nix b/modules/dnsmasq/default.nix index a87ecfe..9ce7504 100644 --- a/modules/dnsmasq/default.nix +++ b/modules/dnsmasq/default.nix @@ -1,14 +1,46 @@ { lib, pkgs, config, ...}: let inherit (lib) mkOption types; + inherit (pkgs) liminix; in { options = { system.service.dnsmasq = mkOption { - type = types.functionTo types.package; + type = liminix.lib.types.serviceDefn; }; }; config = { - system.service.dnsmasq = pkgs.callPackage ./service.nix {}; + system.service.dnsmasq = liminix.callService ./service.nix { + user = mkOption { + type = types.str; + default = "dnsmasq"; + }; + group = mkOption { + type = types.str; + default = "dnsmasq"; + }; + resolvconf = mkOption { + type = types.nullOr liminix.lib.types.service; + default = null; + }; + interface = mkOption { + type = liminix.lib.types.service; + default = null; + }; + upstreams = mkOption { + type = types.listOf types.str; + default = []; + }; + ranges = mkOption { + type = types.listOf types.str; + }; + domain = mkOption { + # this can be given multiple times so probably should be + # domains plural and list of string + description = "Domain name for DHCP service: causes the DHCP server to return the domain to any hosts which request it, and sets the domain which it is legal for DHCP-configured hosts to claim"; + type = types.str; + example = "example.com"; + }; + }; users.dnsmasq = { uid = 51; gid= 51; gecos = "DNS/DHCP service user"; dir = "/run/dnsmasq"; diff --git a/modules/dnsmasq/service.nix b/modules/dnsmasq/service.nix index 226d95c..c446de2 100644 --- a/modules/dnsmasq/service.nix +++ b/modules/dnsmasq/service.nix @@ -4,46 +4,19 @@ , serviceFns , lib }: +{ + interface +, user +, domain +, group +, ranges +, upstreams +, resolvconf +}: let + name = "${interface.device}.dnsmasq"; inherit (liminix.services) longrun; inherit (lib) concatStringsSep; - inherit (liminix.lib) typeChecked; - inherit (lib) mkOption types; - - t = { - user = mkOption { - type = types.str; - default = "dnsmasq"; - }; - group = mkOption { - type = types.str; - default = "dnsmasq"; - }; - resolvconf = mkOption { - type = types.nullOr liminix.lib.types.service; - default = null; - }; - interface = mkOption { - type = liminix.lib.types.service; - default = null; - }; - upstreams = mkOption { - type = types.listOf types.str; - default = []; - }; - ranges = mkOption { - type = types.listOf types.str; - }; - domain = mkOption { - type = types.str; - }; - }; -in -params: -let - inherit (typeChecked "dnsmasq" t params) - interface user domain group ranges upstreams resolvconf; - name = "${interface.device}.dnsmasq"; in longrun { inherit name; diff --git a/pkgs/default.nix b/pkgs/default.nix index 0d03d0d..c841d0c 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -2,7 +2,14 @@ callPackage , lib }: -{ +let + typeChecked = caller: type: value: + let + inherit (lib) types mergeDefinitions; + defs = [{ file = caller; inherit value; }]; + type' = types.submodule { options = type; }; + in (mergeDefinitions [] type' defs).mergedValue; +in { pseudofile = callPackage ./pseudofile {}; liminix = { services = callPackage ./liminix-tools/services {}; @@ -11,22 +18,29 @@ squashfs = callPackage ./liminix-tools/builders/squashfs.nix {}; kernel = callPackage ./kernel {}; }; + callService = path : parameters : + let pkg = callPackage path {}; + checkTypes = t : p : typeChecked (builtins.tostring path) t p; + in { + inherit parameters; + build = args : pkg (checkTypes parameters args); + }; lib = { - types = { - service = - let inherit (lib) types isDerivation hasAttr; - in types.package // { + types = + let inherit (lib) types isDerivation; + in { + service = types.package // { name = "service"; description = "s6-rc service"; - check = x: isDerivation x && hasAttr "serviceType" x; + check = x: isDerivation x && x ? serviceType; }; - }; - typeChecked = caller: type: value: - let - inherit (lib) types mergeDefinitions; - defs = [{ file = caller; inherit value; }]; - type' = types.submodule { options = type; }; - in (mergeDefinitions [] type' defs).mergedValue; + serviceDefn = types.attrs // { + name = "service-defn"; + description = "parametrisable s6-rc service definition"; + check = x: lib.isAttrs x && x ? parameters && x ? build; + }; + }; + inherit typeChecked; }; }; writeFennelScript = callPackage ./write-fennel-script {}; diff --git a/tests/pppoe/configuration.nix b/tests/pppoe/configuration.nix index af47d40..0f48569 100644 --- a/tests/pppoe/configuration.nix +++ b/tests/pppoe/configuration.nix @@ -41,7 +41,7 @@ in rec { }; services.dns = - config.system.service.dnsmasq { + config.system.service.dnsmasq.build { interface = services.lan4; ranges = ["192.168.19.10,192.168.19.253"]; domain = "fake.liminix.org";