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