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 description
61 else description + ''
62 </para><para>
63 StrongSwan default: <literal><![CDATA[${builtins.toJSON strongswanDefault}]]></literal>
64 '';
65
66 single = f: name: value: { ${name} = f value; };
67
68 mkStrParam = mkParamOfType types.str;
69 mkOptionalStrParam = mkStrParam null;
70
71 mkEnumParam = values : mkParamOfType (types.enum values);
72
73 mkIntParam = mkParamOfType types.int;
74 mkOptionalIntParam = mkIntParam null;
75
76 # We should have floats in Nix...
77 mkFloatParam = mkStrParam;
78
79 # TODO: Check for hex format:
80 mkHexParam = mkStrParam;
81 mkOptionalHexParam = mkOptionalStrParam;
82
83 # TODO: Check for duration format:
84 mkDurationParam = mkStrParam;
85 mkOptionalDurationParam = mkOptionalStrParam;
86
87 mkYesNoParam = strongswanDefault : description : {
88 _type = "param";
89 option = mkOption {
90 type = types.nullOr types.bool;
91 default = null;
92 description = documentDefault description strongswanDefault;
93 };
94 render = single (b: if b then "yes" else "no");
95 };
96 yes = true;
97 no = false;
98
99 mkSpaceSepListParam = mkSepListParam " ";
100 mkCommaSepListParam = mkSepListParam ",";
101
102 mkSepListParam = sep : strongswanDefault : description : {
103 _type = "param";
104 option = mkOption {
105 type = types.nullOr (types.listOf types.str);
106 default = null;
107 description = documentDefault description strongswanDefault;
108 };
109 render = single (value: concatStringsSep sep value);
110 };
111
112 mkAttrsOfParams = params :
113 mkAttrsOf params (types.submodule {options = paramsToOptions params;});
114
115 mkAttrsOfParam = param :
116 mkAttrsOf param param.option.type;
117
118 mkAttrsOf = param : option : description : {
119 _type = "param";
120 option = mkOption {
121 type = types.attrsOf option;
122 default = {};
123 inherit description;
124 };
125 render = single (attrs:
126 (paramsToRenderedStrings attrs
127 (mapAttrs (_n: _v: param) attrs)));
128 };
129
130 mkPrefixedAttrsOfParams = params :
131 mkPrefixedAttrsOf params (types.submodule {options = paramsToOptions params;});
132
133 mkPrefixedAttrsOfParam = param :
134 mkPrefixedAttrsOf param param.option.type;
135
136 mkPrefixedAttrsOf = p : option : description : {
137 _type = "param";
138 option = mkOption {
139 type = types.attrsOf option;
140 default = {};
141 inherit description;
142 };
143 render = prefix: attrs:
144 let prefixedAttrs = mapAttrs' (name: nameValuePair "${prefix}-${name}") attrs;
145 in paramsToRenderedStrings prefixedAttrs
146 (mapAttrs (_n: _v: p) prefixedAttrs);
147 };
148
149 mkPostfixedAttrsOfParams = params : description : {
150 _type = "param";
151 option = mkOption {
152 type = types.attrsOf (types.submodule {options = paramsToOptions params;});
153 default = {};
154 inherit description;
155 };
156 render = postfix: attrs:
157 let postfixedAttrs = mapAttrs' (name: nameValuePair "${name}-${postfix}") attrs;
158 in paramsToRenderedStrings postfixedAttrs
159 (mapAttrs (_n: _v: params) postfixedAttrs);
160 };
161
162}