summary refs log tree commit diff
path: root/nixos/modules/services/networking/strongswan-swanctl/param-constructors.nix
blob: dfdfc50d8ae2335444aafae966348df44362e6d8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# In the following context a parameter is an attribute set that
# contains a NixOS option and a render function. It also contains the
# attribute: '_type = "param"' so we can distinguish it from other
# sets.
#
# The render function is used to convert the value of the option to a
# snippet of strongswan.conf. Most parameters simply render their
# value to a string. For example, take the following parameter:
#
#   threads = mkIntParam 10 "Threads to use for request handling.";
#
# When a users defines the corresponding option as for example:
#
#   services.strongswan-swanctl.strongswan.threads = 32;
#
# It will get rendered to the following snippet in strongswan.conf:
#
#   threads = 32
#
# Some parameters however need to be able to change the attribute
# name. For example, take the following parameter:
#
#   id = mkPrefixedAttrsOfParam (mkOptionalStrParam "") "...";
#
# A user can define the corresponding option as for example:
#
#   id = {
#     "foo" = "bar";
#     "baz" = "qux";
#   };
#
# This will get rendered to the following snippet:
#
#   foo-id = bar
#   baz-id = qux
#
# For this reason the render function is not simply a function from
# value -> string but a function from a value to an attribute set:
# { "${name}" = string }. This allows parameters to change the attribute
# name like in the previous example.

lib :

with lib;
with (import ./param-lib.nix lib);

rec {
  mkParamOfType = type : strongswanDefault : description : {
    _type = "param";
    option = mkOption {
      type = types.nullOr type;
      default = null;
      description = documentDefault description strongswanDefault;
    };
    render = single toString;
  };

  documentDefault = description : strongswanDefault :
    if strongswanDefault == null
    then description
    else description + ''
      </para><para>
      StrongSwan default: <literal><![CDATA[${builtins.toJSON strongswanDefault}]]></literal>
    '';

  single = f: name: value: { ${name} = f value; };

  mkStrParam         = mkParamOfType types.str;
  mkOptionalStrParam = mkStrParam null;

  mkEnumParam = values : mkParamOfType (types.enum values);

  mkIntParam         = mkParamOfType types.int;
  mkOptionalIntParam = mkIntParam null;

  # We should have floats in Nix...
  mkFloatParam = mkStrParam;

  # TODO: Check for hex format:
  mkHexParam         = mkStrParam;
  mkOptionalHexParam = mkOptionalStrParam;

  # TODO: Check for duration format:
  mkDurationParam         = mkStrParam;
  mkOptionalDurationParam = mkOptionalStrParam;

  mkYesNoParam = strongswanDefault : description : {
    _type = "param";
    option = mkOption {
      type = types.nullOr types.bool;
      default = null;
      description = documentDefault description strongswanDefault;
    };
    render = single (b: if b then "yes" else "no");
  };
  yes = true;
  no  = false;

  mkSpaceSepListParam = mkSepListParam " ";
  mkCommaSepListParam = mkSepListParam ",";

  mkSepListParam = sep : strongswanDefault : description : {
    _type = "param";
    option = mkOption {
      type = types.nullOr (types.listOf types.str);
      default = null;
      description = documentDefault description strongswanDefault;
    };
    render = single (value: concatStringsSep sep value);
  };

  mkAttrsOfParams = params :
    mkAttrsOf params (types.submodule {options = paramsToOptions params;});

  mkAttrsOfParam = param :
    mkAttrsOf param param.option.type;

  mkAttrsOf = param : option : description : {
    _type = "param";
    option = mkOption {
      type = types.attrsOf option;
      default = {};
      inherit description;
    };
    render = single (attrs:
      (paramsToRenderedStrings attrs
        (mapAttrs (_n: _v: param) attrs)));
  };

  mkPrefixedAttrsOfParams = params :
    mkPrefixedAttrsOf params (types.submodule {options = paramsToOptions params;});

  mkPrefixedAttrsOfParam = param :
    mkPrefixedAttrsOf param param.option.type;

  mkPrefixedAttrsOf = p : option : description : {
    _type = "param";
    option = mkOption {
      type = types.attrsOf option;
      default = {};
      inherit description;
    };
    render = prefix: attrs:
      let prefixedAttrs = mapAttrs' (name: nameValuePair "${prefix}-${name}") attrs;
      in paramsToRenderedStrings prefixedAttrs
           (mapAttrs (_n: _v: p) prefixedAttrs);
  };

  mkPostfixedAttrsOfParams = params : description : {
    _type = "param";
    option = mkOption {
      type = types.attrsOf (types.submodule {options = paramsToOptions params;});
      default = {};
      inherit description;
    };
    render = postfix: attrs:
      let postfixedAttrs = mapAttrs' (name: nameValuePair "${name}-${postfix}") attrs;
      in paramsToRenderedStrings postfixedAttrs
           (mapAttrs (_n: _v: params) postfixedAttrs);
  };

}