{ pkgs ? import {}, ... }: with pkgs.lib; let join-lines = concatStringsSep "\n"; makeSrvRecords = protocol: type: records: join-lines (map (record: "_${type}._${protocol} IN SRV ${toString record.priority} ${toString record.weight} ${toString record.port} ${record.host}.") records); makeSrvProtocolRecords = protocol: types: join-lines (mapAttrsToList (makeSrvRecords protocol) types); srvRecordOpts = with types; { options = { weight = mkOption { type = int; description = "Weight relative to other records."; default = 1; }; priority = mkOption { type = int; description = "Priority to give this record."; default = 0; }; port = mkOption { type = port; description = "Port to use when connecting."; }; host = mkOption { type = str; description = "Host to contact for this service."; example = "my-host.my-domain.com."; }; }; }; srvRecordPair = domain: protocol: type: record: { "_${type}._${protocol}.${domain}" = "${toString record.priority} ${toString record.weight} ${toString record.port} ${record.host}."; }; in rec { srvRecords = with types; attrsOf (attrsOf (listOf (submodule srvRecordOpts))); srvRecordsToBindZone = srvRecords: join-lines (mapAttrsToList makeSrvProtocolRecords srvRecords); concatMapAttrs = f: attrs: concatMap (x: x) (mapAttrsToList (key: val: f key val) attrs); srvRecordsToPairs = domain: srvRecords: listToAttrs (concatMapAttrs (protocol: types: concatMapAttrs (type: records: map (srvRecordPair domain protocol type) records) types) srvRecords); }