1# In the following context a parameter is an attribute set that
2# contains a NixOS option and a render function. It also contains the
3# attribute: '_type = "param"' so we can distinguish it from other
4# sets.
5#
6# The render function is used to convert the value of the option to a
7# snippet of strongswan.conf. Most parameters simply render their
8# value to a string. For example, take the following parameter:
9#
10# threads = mkIntParam 10 "Threads to use for request handling.";
11#
12# When a users defines the corresponding option as for example:
13#
14# services.strongswan-swanctl.strongswan.threads = 32;
15#
16# It will get rendered to the following snippet in strongswan.conf:
17#
18# threads = 32
19#
20# Some parameters however need to be able to change the attribute
21# name. For example, take the following parameter:
22#
23# id = mkPrefixedAttrsOfParam (mkOptionalStrParam "") "...";
24#
25# A user can define the corresponding option as for example:
26#
27# id = {
28# "foo" = "bar";
29# "baz" = "qux";
30# };
31#
32# This will get rendered to the following snippet:
33#
34# foo-id = bar
35# baz-id = qux
36#
37# For this reason the render function is not simply a function from
38# value -> string but a function from a value to an attribute set:
39# { "${name}" = string }. This allows parameters to change the attribute
40# name like in the previous example.
41
42lib :
43
44with lib;
45with (import ./param-lib.nix lib);
46
47rec {
48 mkParamOfType = type : strongswanDefault : description : {
49 _type = "param";
50 option = mkOption {
51 type = types.nullOr type;
52 default = null;
53 description = documentDefault description strongswanDefault;
54 };
55 render = single toString;
56 };
57
58 documentDefault = description : strongswanDefault :
59 if strongswanDefault == null
60 then mdDoc description
61 else mdDoc (description + ''
62
63
64 StrongSwan default: ````${builtins.toJSON strongswanDefault}````
65 '');
66
67 single = f: name: value: { ${name} = f value; };
68
69 mkStrParam = mkParamOfType types.str;
70 mkOptionalStrParam = mkStrParam null;
71
72 mkEnumParam = values : mkParamOfType (types.enum values);
73
74 mkIntParam = mkParamOfType types.int;
75 mkOptionalIntParam = mkIntParam null;
76
77 # We should have floats in Nix...
78 mkFloatParam = mkStrParam;
79
80 # TODO: Check for hex format:
81 mkHexParam = mkStrParam;
82 mkOptionalHexParam = mkOptionalStrParam;
83
84 # TODO: Check for duration format:
85 mkDurationParam = mkStrParam;
86 mkOptionalDurationParam = mkOptionalStrParam;
87
88 mkYesNoParam = strongswanDefault : description : {
89 _type = "param";
90 option = mkOption {
91 type = types.nullOr types.bool;
92 default = null;
93 description = documentDefault description strongswanDefault;
94 };
95 render = single (b: if b then "yes" else "no");
96 };
97 yes = true;
98 no = false;
99
100 mkSpaceSepListParam = mkSepListParam " ";
101 mkCommaSepListParam = mkSepListParam ",";
102
103 mkSepListParam = sep : strongswanDefault : description : {
104 _type = "param";
105 option = mkOption {
106 type = types.nullOr (types.listOf types.str);
107 default = null;
108 description = documentDefault description strongswanDefault;
109 };
110 render = single (value: concatStringsSep sep value);
111 };
112
113 mkAttrsOfParams = params :
114 mkAttrsOf params (types.submodule {options = paramsToOptions params;});
115
116 mkAttrsOfParam = param :
117 mkAttrsOf param param.option.type;
118
119 mkAttrsOf = param : option : description : {
120 _type = "param";
121 option = mkOption {
122 type = types.attrsOf option;
123 default = {};
124 description = mdDoc description;
125 };
126 render = single (attrs:
127 (paramsToRenderedStrings attrs
128 (mapAttrs (_n: _v: param) attrs)));
129 };
130
131 mkPrefixedAttrsOfParams = params :
132 mkPrefixedAttrsOf params (types.submodule {options = paramsToOptions params;});
133
134 mkPrefixedAttrsOfParam = param :
135 mkPrefixedAttrsOf param param.option.type;
136
137 mkPrefixedAttrsOf = p : option : description : {
138 _type = "param";
139 option = mkOption {
140 type = types.attrsOf option;
141 default = {};
142 description = mdDoc description;
143 };
144 render = prefix: attrs:
145 let prefixedAttrs = mapAttrs' (name: nameValuePair "${prefix}-${name}") attrs;
146 in paramsToRenderedStrings prefixedAttrs
147 (mapAttrs (_n: _v: p) prefixedAttrs);
148 };
149
150 mkPostfixedAttrsOfParams = params : description : {
151 _type = "param";
152 option = mkOption {
153 type = types.attrsOf (types.submodule {options = paramsToOptions params;});
154 default = {};
155 description = lib.mdDoc description;
156 };
157 render = postfix: attrs:
158 let postfixedAttrs = mapAttrs' (name: nameValuePair "${name}-${postfix}") attrs;
159 in paramsToRenderedStrings postfixedAttrs
160 (mapAttrs (_n: _v: params) postfixedAttrs);
161 };
162
163}