1lib: 2 3with lib; 4 5rec { 6 paramsToConf = cfg: ps: mkConf 0 (paramsToRenderedStrings cfg ps); 7 8 # mkConf takes an indentation level (which usually starts at 0) and a nested 9 # attribute set of strings and will render that set to a strongswan.conf style 10 # configuration format. For example: 11 # 12 # mkConf 0 {a = "1"; b = { c = { "foo" = "2"; "bar" = "3"; }; d = "4";};} => '' 13 # a = 1 14 # b { 15 # c { 16 # foo = 2 17 # bar = 3 18 # } 19 # d = 4 20 # }'' 21 mkConf = 22 indent: ps: 23 concatMapStringsSep "\n" ( 24 name: 25 let 26 value = ps.${name}; 27 indentation = replicate indent " "; 28 in 29 indentation 30 + ( 31 if isAttrs value then 32 "${name} {\n" + mkConf (indent + 2) value + "\n" + indentation + "}" 33 else 34 "${name} = ${value}" 35 ) 36 ) (attrNames ps); 37 38 replicate = n: c: concatStrings (builtins.genList (_x: c) n); 39 40 # `paramsToRenderedStrings cfg ps` converts the NixOS configuration `cfg` 41 # (typically the "config" argument of a NixOS module) and the set of 42 # parameters `ps` (an attribute set where the values are constructed using the 43 # parameter constructors in ./param-constructors.nix) to a nested attribute 44 # set of strings (rendered parameters). 45 paramsToRenderedStrings = 46 cfg: ps: 47 filterEmptySets ( 48 (mapParamsRecursive ( 49 path: name: param: 50 let 51 value = attrByPath path null cfg; 52 in 53 optionalAttrs (value != null) (param.render name value) 54 ) ps) 55 ); 56 57 filterEmptySets = 58 set: 59 filterAttrs (n: v: (v != null)) ( 60 mapAttrs ( 61 name: value: 62 if isAttrs value then 63 let 64 value' = filterEmptySets value; 65 in 66 if value' == { } then null else value' 67 else 68 value 69 ) set 70 ); 71 72 # Recursively map over every parameter in the given attribute set. 73 mapParamsRecursive = mapAttrsRecursiveCond' (as: (!(as ? _type && as._type == "param"))); 74 75 mapAttrsRecursiveCond' = 76 cond: f: set: 77 let 78 recurse = 79 path: set: 80 let 81 g = 82 name: value: 83 if isAttrs value && cond value then 84 { ${name} = recurse (path ++ [ name ]) value; } 85 else 86 f (path ++ [ name ]) name value; 87 in 88 mapAttrs'' g set; 89 in 90 recurse [ ] set; 91 92 mapAttrs'' = f: set: foldl' (a: b: a // b) { } (mapAttrsToList f set); 93 94 # Extract the options from the given set of parameters. 95 paramsToOptions = ps: mapParamsRecursive (_path: name: param: { ${name} = param.option; }) ps; 96 97}