summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/default.nix176
-rw-r--r--lib/genid.nix3
-rw-r--r--lib/haskell.nix25
-rw-r--r--lib/impure.nix3
-rw-r--r--lib/pure.nix226
-rw-r--r--lib/svg-colors.json149
-rw-r--r--lib/types.nix135
7 files changed, 507 insertions, 210 deletions
diff --git a/lib/default.nix b/lib/default.nix
index 738e5218..f9f2f157 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -1,175 +1 @@
-let
- nixpkgs-lib = import <nixpkgs/lib>;
- lib = with lib; nixpkgs-lib // builtins // {
-
- evalSource = import ./eval-source.nix;
-
- git = import ./git.nix { inherit lib; };
- haskell = import ./haskell.nix { inherit lib; };
- krebs = import ./krebs lib;
- krops = import ../submodules/krops/lib;
- shell = import ./shell.nix { inherit lib; };
- systemd = {
- encodeName = replaceChars ["/"] ["\\x2f"];
- };
- types = nixpkgs-lib.types // import ./types.nix { inherit lib; };
- uri = import ./uri.nix { inherit lib; };
- xml = import ./xml.nix { inherit lib; };
-
- # compose a list of functions to be applied from left to right, i.e.
- # compose :: [ (xm -> xn) ... (x1 -> x2) (x0 -> x1) ] -> x0 -> xn
- compose = foldl' (f: g: x: f (g x)) id;
-
- eq = x: y: x == y;
- ne = x: y: x != y;
- mod = x: y: x - y * (x / y);
-
- genid = lib.genid_uint32; # TODO remove
- genid_uint31 = x: ((lib.genid_uint32 x) + 16777216) / 2;
- genid_uint32 = import ./genid.nix { inherit lib; };
-
- lpad = n: c: s:
- if lib.stringLength s < n
- then lib.lpad n c (c + s)
- else s;
-
- genAttrs' = names: f: listToAttrs (map f names);
-
- getAttrs = names: set:
- listToAttrs (map (name: nameValuePair name set.${name})
- (filter (flip hasAttr set) names));
-
- packageName = pkg:
- pkg.pname or (parseDrvName pkg.name).name;
-
- test = re: x: isString x && testString re x;
-
- testString = re: x: match re x != null;
-
- toC = x: let
- type = typeOf x;
- reject = throw "cannot convert ${type}";
- in {
- list = "{ ${concatStringsSep ", " (map toC x)} }";
- null = "NULL";
- set = if isDerivation x then toJSON x else reject;
- string = toJSON x; # close enough
- }.${type} or reject;
-
- indent = replaceChars ["\n"] ["\n "];
-
- stripAttr = converge (filterAttrsRecursive (n: v: v != {} && v != null));
-
- mapNixDir = f: x: {
- list = foldl' mergeAttrs {} (map (mapNixDir1 f) x);
- path = mapNixDir1 f x;
- }.${typeOf x};
-
- mapNixDir1 = f: dirPath:
- let
- toPackageName = name:
- if test "^[0-9].*" name then "_${name}" else name;
- in
- listToAttrs
- (map
- (relPath: let
- name = removeSuffix ".nix" relPath;
- path = dirPath + "/${relPath}";
- in
- nameValuePair (toPackageName name) (f path))
- (filter
- (name: name != "default.nix" && !hasPrefix "." name)
- (attrNames (readDir dirPath))));
-
- # https://tools.ietf.org/html/rfc5952
- normalize-ip6-addr =
- let
- max-run-0 =
- let
- both = v: { off = v; pos = v; };
- gt = a: b: a.pos - a.off > b.pos - b.off;
-
- chkmax = ctx: {
- cur = both (ctx.cur.pos + 1);
- max = if gt ctx.cur ctx.max then ctx.cur else ctx.max;
- };
-
- incpos = ctx: recursiveUpdate ctx {
- cur.pos = ctx.cur.pos + 1;
- };
-
- f = ctx: blk: (if blk == "0" then incpos else chkmax) ctx;
- z = { cur = both 0; max = both 0; };
- in
- blks: (chkmax (foldl' f z blks)).max;
-
- group-zeros = a:
- let
- blks = splitString ":" a;
- max = max-run-0 blks;
- lhs = take max.off blks;
- rhs = drop max.pos blks;
- in
- if max.pos == 0
- then a
- else let
- sep =
- if 8 - (length lhs + length rhs) == 1
- then ":0:"
- else "::";
- in
- "${concatStringsSep ":" lhs}${sep}${concatStringsSep ":" rhs}";
-
- drop-leading-zeros =
- let
- f = block:
- let
- res = match "0*(.+)" block;
- in
- if res == null
- then block # empty block
- else elemAt res 0;
- in
- a: concatStringsSep ":" (map f (splitString ":" a));
- in
- a:
- toLower
- (if test ".*::.*" a
- then a
- else group-zeros (drop-leading-zeros a));
-
- hashToLength = n: s: substring 0 n (hashString "sha256" s);
-
- dropLast = n: xs: reverseList (drop n (reverseList xs));
- takeLast = n: xs: reverseList (take n (reverseList xs));
-
- # Split string into list of chunks where each chunk is at most n chars long.
- # The leftmost chunk might shorter.
- # Example: stringToGroupsOf "123456" -> ["12" "3456"]
- stringToGroupsOf = n: s: let
- acc =
- foldl'
- (acc: c: if stringLength acc.chunk < n then {
- chunk = acc.chunk + c;
- chunks = acc.chunks;
- } else {
- chunk = c;
- chunks = acc.chunks ++ [acc.chunk];
- })
- {
- chunk = "";
- chunks = [];
- }
- (stringToCharacters s);
- in
- filter (x: x != []) ([acc.chunk] ++ acc.chunks);
-
- warnOldVersion = oldName: newName:
- if compareVersions oldName newName != -1 then
- trace "Upstream `${oldName}' gets overridden by `${newName}'." newName
- else
- newName;
- };
-in
-
-lib
+import ./impure.nix
diff --git a/lib/genid.nix b/lib/genid.nix
index 0aed1d35..bfa4a9a0 100644
--- a/lib/genid.nix
+++ b/lib/genid.nix
@@ -32,6 +32,5 @@ let out = genid;
hexint = x: hexvals.${toLower x};
# :: attrset char uint4
- hexvals = listToAttrs (imap (i: c: { name = c; value = i - 1; })
- (stringToCharacters "0123456789abcdef"));
+ hexvals = listToAttrs (imap (i: c: { name = c; value = i - 1; }) hexchars);
in out
diff --git a/lib/haskell.nix b/lib/haskell.nix
index b1889caf..f87cfa76 100644
--- a/lib/haskell.nix
+++ b/lib/haskell.nix
@@ -9,19 +9,14 @@ rec {
# "${pkgs.bar}/bin/foo" for each {-pkg:bar-}"foo".
# If a package doesn't exist, a warning gets printed.
substitutePkgs = name: { callsite ? null, pkgs, path }:
- pkgs.writeText name (substitutePkgs' {
- inherit pkgs;
+ let
sourceDescription =
if callsite != null then
"${name} in ${toString callsite}"
else
"${name} from ${toString path}";
- text = readFile path;
- });
- substitutePkgs' = { pkgs, sourceDescription, text }:
- let
- f = s:
+ f = dependencies: s:
let
parse = match "(.*)([{]-pkg(:([^}]+))?-[}]\"([^\"]+)\")(.*)" s;
prefix = elemAt parse 0;
@@ -35,7 +30,7 @@ rec {
"${pkg}/bin/${exename}"
else
trace (toString [
- "lib.haskell.replacePkg:"
+ "lib.haskell.substitutePkgs:"
"warning:"
"while deriving ${sourceDescription}:"
"no substitute found for ${elemAt parse 1}"
@@ -43,9 +38,17 @@ rec {
exename;
in
if parse == null then
- s
+ (pkgs.writeText name s).overrideAttrs (old: {
+ dependencies =
+ lib.uniq
+ (lib.sort (lib.on lib.lessThan (lib.getAttr "name"))
+ (filter
+ (lib.ne null)
+ (old.dependencies or [] ++ dependencies)));
+ })
+
else
- f (prefix + toJSON substitute + suffix);
+ f (dependencies ++ [pkg]) (prefix + toJSON substitute + suffix);
in
- f text;
+ f [] (readFile path);
}
diff --git a/lib/impure.nix b/lib/impure.nix
new file mode 100644
index 00000000..3f95c375
--- /dev/null
+++ b/lib/impure.nix
@@ -0,0 +1,3 @@
+import ./pure.nix {
+ lib = import <nixpkgs/lib>;
+}
diff --git a/lib/pure.nix b/lib/pure.nix
new file mode 100644
index 00000000..3fe51cd5
--- /dev/null
+++ b/lib/pure.nix
@@ -0,0 +1,226 @@
+{ lib, ... }:
+let
+ nixpkgs-lib = lib;
+ stockholm.lib = with stockholm.lib; nixpkgs-lib // builtins // {
+
+ evalModulesConfig = modules: let
+ eval = evalModules {
+ inherit modules;
+ };
+ in filterAttrsRecursive (name: _: !hasPrefix "_" name) eval.config;
+
+ evalSource = import ./eval-source.nix;
+
+ evalSubmodule = submodule: modules: let
+ prefix = ["evalSubmodule"];
+ in evalModulesConfig [
+ {
+ options = removeAttrs (submodule.getSubOptions prefix) ["_module"];
+ imports = modules;
+ }
+ ];
+
+ git = import ./git.nix { inherit (stockholm) lib; };
+ haskell = import ./haskell.nix { inherit (stockholm) lib; };
+ krebs = import ./krebs stockholm.lib;
+ shell = import ./shell.nix { inherit (stockholm) lib; };
+ systemd = {
+ encodeName = replaceStrings ["/"] ["\\x2f"];
+ };
+ types = nixpkgs-lib.types // import ./types.nix { lib = stockholm.lib; };
+ uri = import ./uri.nix { inherit (stockholm) lib; };
+ xml = import ./xml.nix { inherit (stockholm) lib; };
+
+ # compose a list of functions to be applied from left to right, i.e.
+ # compose :: [ (xm -> xn) ... (x1 -> x2) (x0 -> x1) ] -> x0 -> xn
+ compose = foldl' (f: g: x: f (g x)) id;
+
+ eq = x: y: x == y;
+ ne = x: y: x != y;
+ mod = x: y: x - y * (x / y);
+
+ on = b: u: x: y: b (u x) (u y);
+
+ genid = stockholm.lib.genid_uint32; # TODO remove
+ genid_uint31 = x: ((stockholm.lib.genid_uint32 x) + 16777216) / 2;
+ genid_uint32 = import ./genid.nix { lib = stockholm.lib; };
+
+ hexchars = stringToCharacters "0123456789abcdef";
+
+ lpad = n: c: s:
+ if lib.stringLength s < n
+ then stockholm.lib.lpad n c (c + s)
+ else s;
+
+ genAttrs' = names: f: listToAttrs (map f names);
+
+ getAttrs = names: set:
+ listToAttrs (map (name: nameValuePair name set.${name})
+ (filter (flip hasAttr set) names));
+
+ maybeHead = x: if isList x && length x > 0 then head x else null;
+
+ packageName = pkg:
+ pkg.pname or (parseDrvName pkg.name).name;
+
+ test = re: x: isString x && testString re x;
+
+ testString = re: x: match re x != null;
+
+ toC = x: let
+ type = typeOf x;
+ reject = throw "cannot convert ${type}";
+ in {
+ int = toJSON x; # close enough
+ list = "{ ${concatStringsSep ", " (map toC x)} }";
+ null = "NULL";
+ set = if isDerivation x then toJSON x else reject;
+ string = toJSON x; # close enough
+ }.${type} or reject;
+
+ indent = replaceStrings ["\n"] ["\n "];
+
+ stripAttr = converge (filterAttrsRecursive (n: v: v != {} && v != null));
+
+ mapNixDir = f: x: {
+ list = foldl' mergeAttrs {} (map (mapNixDir1 f) x);
+ path = mapNixDir1 f x;
+ }.${typeOf x};
+
+ mapNixDir1 = f: dirPath:
+ let
+ toPackageName = name:
+ if test "^[0-9].*" name then "_${name}" else name;
+ in
+ listToAttrs
+ (map
+ (relPath: let
+ name = removeSuffix ".nix" relPath;
+ path = dirPath + "/${relPath}";
+ in
+ nameValuePair (toPackageName name) (f path))
+ (attrNames
+ (filterAttrs isNixDirEntry (readDir dirPath))));
+
+ isNixDirEntry = name: type:
+ (type == "regular" && hasSuffix ".nix" name && name != "default.nix") ||
+ (type == "directory" && !hasPrefix "." name);
+
+ # https://tools.ietf.org/html/rfc5952
+ normalize-ip6-addr =
+ let
+ max-run-0 =
+ let
+ both = v: { off = v; pos = v; };
+ gt = a: b: a.pos - a.off > b.pos - b.off;
+
+ chkmax = ctx: {
+ cur = both (ctx.cur.pos + 1);
+ max = if gt ctx.cur ctx.max then ctx.cur else ctx.max;
+ };
+
+ incpos = ctx: recursiveUpdate ctx {
+ cur.pos = ctx.cur.pos + 1;
+ };
+
+ f = ctx: blk: (if blk == "0" then incpos else chkmax) ctx;
+ z = { cur = both 0; max = both 0; };
+ in
+ blks: (chkmax (foldl' f z blks)).max;
+
+ group-zeros = a:
+ let
+ blks = splitString ":" a;
+ max = max-run-0 blks;
+ lhs = take max.off blks;
+ rhs = drop max.pos blks;
+ in
+ if max.pos == 0
+ then a
+ else let
+ sep =
+ if 8 - (length lhs + length rhs) == 1
+ then ":0:"
+ else "::";
+ in
+ "${concatStringsSep ":" lhs}${sep}${concatStringsSep ":" rhs}";
+
+ drop-leading-zeros =
+ let
+ f = block:
+ let
+ res = match "0*(.+)" block;
+ in
+ if res == null
+ then block # empty block
+ else elemAt res 0;
+ in
+ a: concatStringsSep ":" (map f (splitString ":" a));
+ in
+ a:
+ toLower
+ (if test ".*::.*" a
+ then a
+ else group-zeros (drop-leading-zeros a));
+
+ hashToLength = n: s: substring 0 n (hashString "sha256" s);
+
+ dropLast = n: xs: reverseList (drop n (reverseList xs));
+ takeLast = n: xs: reverseList (take n (reverseList xs));
+
+ # Split string into list of chunks where each chunk is at most n chars long.
+ # The leftmost chunk might shorter.
+ # Example: stringToGroupsOf "123456" -> ["12" "3456"]
+ stringToGroupsOf = n: s: let
+ acc =
+ foldl'
+ (acc: c: if stringLength acc.chunk < n then {
+ chunk = acc.chunk + c;
+ chunks = acc.chunks;
+ } else {
+ chunk = c;
+ chunks = acc.chunks ++ [acc.chunk];
+ })
+ {
+ chunk = "";
+ chunks = [];
+ }
+ (stringToCharacters s);
+ in
+ filter (x: x != []) ([acc.chunk] ++ acc.chunks);
+
+ # Filter adjacent duplicate elements.
+ uniq = uniqBy eq;
+
+ # Filter adjacent duplicate elements determined via the given function.
+ uniqBy = cmp: let
+ f = a: s:
+ if length s == 0 then
+ []
+ else let
+ b = head s;
+ in
+ if cmp a b then
+ f b (tail s)
+ else
+ [b] ++ f b (tail s);
+ in
+ s:
+ if length s == 0 then
+ []
+ else let
+ b = head s;
+ in
+ [b] ++ f b (tail s);
+
+ warnOldVersion = oldName: newName:
+ if compareVersions oldName newName != -1 then
+ trace "Upstream `${oldName}' gets overridden by `${newName}'." newName
+ else
+ newName;
+ };
+in
+
+stockholm.lib
+// { lib = stockholm.lib; }
+
diff --git a/lib/svg-colors.json b/lib/svg-colors.json
new file mode 100644
index 00000000..834bf14f
--- /dev/null
+++ b/lib/svg-colors.json
@@ -0,0 +1,149 @@
+[
+ "aliceblue",
+ "antiquewhite",
+ "aqua",
+ "aquamarine",
+ "azure",
+ "beige",
+ "bisque",
+ "black",
+ "blanchedalmond",
+ "blue",
+ "blueviolet",
+ "brown",
+ "burlywood",
+ "cadetblue",
+ "chartreuse",
+ "chocolate",
+ "coral",
+ "cornflowerblue",
+ "cornsilk",
+ "crimson",
+ "cyan",
+ "darkblue",
+ "darkcyan",
+ "darkgoldenrod",
+ "darkgray",
+ "darkgreen",
+ "darkgrey",
+ "darkkhaki",
+ "darkmagenta",
+ "darkolivegreen",
+ "darkorange",
+ "darkorchid",
+ "darkred",
+ "darksalmon",
+ "darkseagreen",
+ "darkslateblue",
+ "darkslategray",
+ "darkslategrey",
+ "darkturquoise",
+ "darkviolet",
+ "deeppink",
+ "deepskyblue",
+ "dimgray",
+ "dimgrey",
+ "dodgerblue",
+ "firebrick",
+ "floralwhite",
+ "forestgreen",
+ "fuchsia",
+ "gainsboro",
+ "ghostwhite",
+ "gold",
+ "goldenrod",
+ "gray",
+ "green",
+ "greenyellow",
+ "grey",
+ "honeydew",
+ "hotpink",
+ "indianred",
+ "indigo",
+ "ivory",
+ "khaki",
+ "lavender",
+ "lavenderblush",
+ "lawngreen",
+ "lemonchiffon",
+ "lightblue",
+ "lightcoral",
+ "lightcyan",
+ "lightgoldenrodyellow",
+ "lightgray",
+ "lightgreen",
+ "lightgrey",
+ "lightpink",
+ "lightsalmon",
+ "lightseagreen",
+ "lightskyblue",
+ "lightslategray",
+ "lightslategrey",
+ "lightsteelblue",
+ "lightyellow",
+ "lime",
+ "limegreen",
+ "linen",
+ "magenta",
+ "maroon",
+ "mediumaquamarine",
+ "mediumblue",
+ "mediumorchid",
+ "mediumpurple",
+ "mediumseagreen",
+ "mediumslateblue",
+ "mediumspringgreen",
+ "mediumturquoise",
+ "mediumvioletred",
+ "midnightblue",
+ "mintcream",
+ "mistyrose",
+ "moccasin",
+ "navajowhite",
+ "navy",
+ "oldlace",
+ "olive",
+ "olivedrab",
+ "orange",
+ "orangered",
+ "orchid",
+ "palegoldenrod",
+ "palegreen",
+ "paleturquoise",
+ "palevioletred",
+ "papayawhip",
+ "peachpuff",
+ "peru",
+ "pink",
+ "plum",
+ "powderblue",
+ "purple",
+ "red",
+ "rosybrown",
+ "royalblue",
+ "saddlebrown",
+ "salmon",
+ "sandybrown",
+ "seagreen",
+ "seashell",
+ "sienna",
+ "silver",
+ "skyblue",
+ "slateblue",
+ "slategray",
+ "slategrey",
+ "snow",
+ "springgreen",
+ "steelblue",
+ "tan",
+ "teal",
+ "thistle",
+ "tomato",
+ "turquoise",
+ "violet",
+ "wheat",
+ "white",
+ "whitesmoke",
+ "yellow",
+ "yellowgreen"
+]
diff --git a/lib/types.nix b/lib/types.nix
index 689a2c80..ad8421b1 100644
--- a/lib/types.nix
+++ b/lib/types.nix
@@ -3,11 +3,11 @@
let
inherit (lib)
all any attrNames concatMapStringsSep concatStringsSep const filter flip
- genid_uint31 hasSuffix head isInt isString length mergeOneOption mkOption
- mkOptionType optional optionalAttrs optionals range splitString
+ genid_uint31 hasSuffix head importJSON isInt isString length mergeOneOption
+ mkOption mkOptionType optional optionalAttrs optionals range splitString
stringLength substring test testString typeOf;
inherit (lib.types)
- attrsOf bool either enum int listOf nullOr path str submodule;
+ addCheck attrsOf bool either enum int lines listOf nullOr path str submodule;
in
rec {
@@ -18,9 +18,6 @@ rec {
type = label;
default = config._module.args.name;
};
- cores = mkOption {
- type = uint;
- };
nets = mkOption {
type = attrsOf net;
default = {};
@@ -34,7 +31,7 @@ rec {
ci = mkOption {
description = ''
If true, then the host wants to be tested by some CI system.
- See <stockholm/krebs/2configs/buildbot-all.nix>
+ See ‹stockholm/krebs/2configs/buildbot-all.nix›
'';
type = bool;
default = false;
@@ -43,7 +40,7 @@ rec {
external = mkOption {
description = ''
Whether the host is defined externally (in contrast to being defined
- in <stockholm>). This is useful e.g. when legacy and/or adopted
+ in ‹stockholm›). This is useful e.g. when legacy and/or adopted
hosts should be part of retiolum or some other component.
'';
type = bool;
@@ -58,6 +55,14 @@ rec {
default = false;
};
+ consul = mkOption {
+ description = ''
+ Whether the host is a member of the global consul network
+ '';
+ type = bool;
+ default = false;
+ };
+
owner = mkOption {
type = user;
};
@@ -102,11 +107,18 @@ rec {
default = config._module.args.name;
};
via = mkOption {
- type = nullOr net;
+ type =
+ # XXX break infinite recursion when generating manuals
+ if config._module.args.name == "‹name›" then
+ mkOptionType {
+ name = "‹net›";
+ }
+ else
+ nullOr net;
default = null;
};
addrs = mkOption {
- type = listOf addr;
+ type = listOf (either addr str);
default =
optional (config.ip4 != null) config.ip4.addr ++
optional (config.ip6 != null) config.ip6.addr;
@@ -121,22 +133,33 @@ rec {
default = null;
};
ip4 = mkOption {
- type = nullOr (submodule {
+ type = nullOr (submodule (ip4: {
options = {
addr = mkOption {
type = addr4;
};
prefix = mkOption ({
type = cidr4;
- } // optionalAttrs (config.name == "retiolum") {
- default = "10.243.0.0/16";
+ } // {
+ retiolum.default = "10.243.0.0/16";
+ wiregrill.default = "10.244.0.0/16";
+ }.${config._module.args.name} or {
+ default = "${ip4.config.addr}/32";
+ });
+ prefixLength = mkOption ({
+ type = uint;
+ } // {
+ retiolum.default = 16;
+ wiregrill.default = 16;
+ }.${config._module.args.name} or {
+ default = 32;
});
};
- });
+ }));
default = null;
};
ip6 = mkOption {
- type = nullOr (submodule {
+ type = nullOr (submodule (ip6: {
options = {
addr = mkOption {
type = addr6;
@@ -144,11 +167,22 @@ rec {
};
prefix = mkOption ({
type = cidr6;
- } // optionalAttrs (config.name == "retiolum") {
- default = "42::/16";
+ } // {
+ retiolum.default = "42:0::/32";
+ wiregrill.default = "42:1::/32";
+ }.${config._module.args.name} or {
+ default = "${ip6.config.addr}/128";
+ });
+ prefixLength = mkOption ({
+ type = uint;
+ } // {
+ retiolum.default = 32;
+ wiregrill.default = 32;
+ }.${config._module.args.name} or {
+ default = 128;
});
};
- });
+ }));
default = null;
};
ssh = mkOption {
@@ -178,7 +212,19 @@ rec {
[config.extraConfig]
++
[config.pubkey]
+ ++
+ optional (config.pubkey_ed25519 != null) ''
+ Ed25519PublicKey = ${config.pubkey_ed25519}
+ ''
+ ++
+ optional (config.weight != null) "Weight = ${toString config.weight}"
);
+ defaultText = ''
+ Address = ‹addr› ‹port› # for each ‹net.via.addrs›
+ Subnet = ‹addr› # for each ‹net.addrs›
+ ‹extraConfig›
+ ‹pubkey›
+ '';
};
pubkey = mkOption {
type = tinc-pubkey;
@@ -190,7 +236,7 @@ rec {
extraConfig = mkOption {
description = "Extra Configuration to be appended to the hosts file";
default = "";
- type = str;
+ type = lines;
};
port = mkOption {
type = int;
@@ -202,6 +248,15 @@ rec {
description = "tinc subnets";
default = [];
};
+ weight = mkOption {
+ type = nullOr int;
+ description = ''
+ global tinc weight (latency in ms) of this particular node.
+ can be set to some high value to make it unprobable to be used as router.
+ if set to null, tinc will autogenerate the value based on latency.
+ '';
+ default = if net.via != null then null else 300;
+ };
};
}));
default = null;
@@ -227,19 +282,32 @@ rec {
};
};
}));
+ default = null;
};
};
});
+ boundedInt = min: max: mkOptionType {
+ name = "bounded integer";
+ check = x: isInt x && min <= x && x <= max;
+ merge = mergeOneOption;
+ };
+
+ lowerBoundedInt = min: mkOptionType {
+ name = "lower bounded integer";
+ check = x: isInt x && min <= x;
+ merge = mergeOneOption;
+ };
+
positive = mkOptionType {
+ inherit (lowerBoundedInt 1) check;
name = "positive integer";
- check = x: isInt x && x > 0;
merge = mergeOneOption;
};
uint = mkOptionType {
+ inherit (lowerBoundedInt 0) check;
name = "unsigned integer";
- check = x: isInt x && x >= 0;
merge = mergeOneOption;
};
@@ -252,6 +320,7 @@ rec {
path = mkOption {
type = absolute-pathname;
default = "/run/keys/${config.name}";
+ defaultText = "/run/keys/‹name›";
};
mode = mkOption {
type = file-mode;
@@ -267,10 +336,12 @@ rec {
service = mkOption {
type = systemd.unit-name;
default = "secret-${lib.systemd.encodeName config.name}.service";
+ defaultText = "secret-‹name›.service";
};
source-path = mkOption {
type = str;
- default = toString <secrets> + "/${config.name}";
+ default = config.name;
+ defaultText = "‹secrets/‹name››";
};
};
});
@@ -379,6 +450,7 @@ rec {
home = mkOption {
type = absolute-pathname;
default = "/home/${config.name}";
+ defaultText = "/home/‹name›";
};
mail = mkOption {
type = nullOr str;
@@ -406,6 +478,7 @@ rec {
uid = mkOption {
type = int;
default = genid_uint31 config.name;
+ defaultText = "genid_uint31 ‹name›";
};
};
});
@@ -414,10 +487,12 @@ rec {
name = mkOption {
type = username;
default = config._module.args.name;
+ defaultText = "genid_uint31 ‹name›";
};
gid = mkOption {
type = int;
default = genid_uint31 config.name;
+ defaultText = "genid_uint31 ‹name›";
};
};
});
@@ -520,6 +595,9 @@ rec {
};
};
+ flameshot.color =
+ either (addCheck str (test "#[0-9A-Fa-f]{6}")) svg.color-keyword;
+
file-mode = mkOptionType {
name = "file mode";
check = test "[0-7]{4}";
@@ -538,6 +616,19 @@ rec {
merge = mergeOneOption;
};
+ # SVG 1.1, 4.4 Recognized color keyword names
+ #
+ # svg-colors.json has been generated with:
+ # curl -sS https://www.w3.org/TR/SVG11/types.html#ColorKeywords |
+ # fq -d html '[
+ # grep_by(.["@class"]=="color-keywords") |
+ # grep_by(.["@class"]=="prop-value"and.["#text"]!="").["#text"]
+ # ] | sort'
+ #
+ svg.color-keyword = enum (importJSON ./svg-colors.json) // {
+ name = "SVG 1.1 recognized color keyword";
+ };
+
systemd.unit-name = mkOptionType {
name = "systemd unit name";
check = x: