100 lines
2.5 KiB
Nix
100 lines
2.5 KiB
Nix
{ lib }:
|
|
let
|
|
inherit (lib)
|
|
concatLists
|
|
concatStringsSep
|
|
foldl'
|
|
groupBy
|
|
mapAttrsToList
|
|
unique
|
|
;
|
|
|
|
declarations = raw:
|
|
concatLists (
|
|
mapAttrsToList (
|
|
_evalHost: hostDeclarations:
|
|
concatLists (
|
|
mapAttrsToList (
|
|
hostName: entries:
|
|
mapAttrsToList (serviceName: uid: {
|
|
path = "${hostName}.${serviceName}";
|
|
inherit serviceName uid;
|
|
}) entries
|
|
) hostDeclarations
|
|
)
|
|
) raw
|
|
);
|
|
|
|
duplicateServices = entries:
|
|
let
|
|
byService = groupBy (entry: entry.serviceName) entries;
|
|
in
|
|
foldl' (
|
|
acc: serviceName:
|
|
let
|
|
serviceEntries = byService.${serviceName};
|
|
uids = unique (map (entry: entry.uid) serviceEntries);
|
|
in
|
|
if builtins.length uids > 1 then
|
|
acc ++ [ {
|
|
inherit serviceName uids;
|
|
paths = map (entry: entry.path) serviceEntries;
|
|
} ]
|
|
else
|
|
acc
|
|
) [ ] (builtins.attrNames byService);
|
|
|
|
duplicateUids = entries:
|
|
let
|
|
byUid = groupBy (entry: toString entry.uid) entries;
|
|
in
|
|
foldl' (
|
|
acc: uid:
|
|
let
|
|
uidEntries = byUid.${uid};
|
|
serviceNames = unique (map (entry: entry.serviceName) uidEntries);
|
|
in
|
|
if builtins.length serviceNames > 1 then
|
|
acc ++ [ {
|
|
uid = lib.toInt uid;
|
|
inherit serviceNames;
|
|
paths = map (entry: entry.path) uidEntries;
|
|
} ]
|
|
else
|
|
acc
|
|
) [ ] (builtins.attrNames byUid);
|
|
|
|
renderServiceConflict = conflict:
|
|
"${conflict.serviceName} is assigned UIDs ${concatStringsSep ", " (map toString conflict.uids)} by ${concatStringsSep ", " conflict.paths}";
|
|
|
|
renderUidConflict = conflict:
|
|
"${toString conflict.uid} is assigned to ${concatStringsSep ", " conflict.serviceNames} by ${concatStringsSep ", " conflict.paths}";
|
|
in
|
|
{
|
|
# Next stable UID: 20003
|
|
replicate = true;
|
|
|
|
type = lib.types.ints.positive;
|
|
|
|
validate = raw:
|
|
let
|
|
entries = declarations raw;
|
|
serviceConflicts = duplicateServices entries;
|
|
uidConflicts = duplicateUids entries;
|
|
in
|
|
[
|
|
{
|
|
assertion = serviceConflicts == [ ];
|
|
message = ''
|
|
Conflicting stable UID allocation(s): ${concatStringsSep "\n" (map renderServiceConflict serviceConflicts)}
|
|
'';
|
|
}
|
|
{
|
|
assertion = uidConflicts == [ ];
|
|
message = ''
|
|
Duplicate stable UID allocation(s): ${concatStringsSep "\n" (map renderUidConflict uidConflicts)}
|
|
'';
|
|
}
|
|
];
|
|
}
|