From dbb78088f4e26e4109185f5b1244977191c6ff0d Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 9 Jan 2023 03:48:07 +0000 Subject: [PATCH] refactor: cleanup instances where we map to attrs to be more resilient against duplicate names --- hosts/common/ssh.nix | 21 +++++++++------------ modules/lib/default.nix | 15 +++++++++++++-- modules/persist/default.nix | 12 ++++++++---- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/hosts/common/ssh.nix b/hosts/common/ssh.nix index 83d495b1..b105865d 100644 --- a/hosts/common/ssh.nix +++ b/hosts/common/ssh.nix @@ -12,16 +12,13 @@ in "${name}@${host}"; - # given a DNS-style recursive AttrSet, return a flat AttrSet that maps ssh id => pubkey. - keysFor = attrs: - let - by-path = sane-lib.flattenAttrs attrs; - in - sane-lib.mapToAttrs ({ path, value }: { - name = keyNameForPath path; - inherit value; - }) by-path; - globalKeys = keysFor sane-data.keys; - localKeys = keysFor sane-data.keys.org.uninsane.local; - in lib.mkMerge [ globalKeys localKeys ]; + # [{ path :: [String], value :: String }] for the keys we want to install + globalKeys = sane-lib.flattenAttrs sane-data.keys; + localKeys = sane-lib.flattenAttrs sane-data.keys.org.uninsane.local; + in lib.mkMerge (builtins.map + ({ path, value }: { + "${keyNameForPath path}" = value; + }) + (globalKeys ++ localKeys) + ); } diff --git a/modules/lib/default.nix b/modules/lib/default.nix index 0ea34ada..28454217 100644 --- a/modules/lib/default.nix +++ b/modules/lib/default.nix @@ -6,6 +6,16 @@ rec { path = import ./path.nix moduleArgs; types = import ./types.nix moduleArgs; + # like `builtins.listToAttrs` but any duplicated `name` throws error on access. + # Type: listToDisjointAttrs :: [{ name :: String, value :: Any }] -> AttrSet + listToDisjointAttrs = l: lib.foldl' lib.attrsets.unionOfDisjoint {} (builtins.map nameValueToAttrs l); + + # evaluate a `{ name, value }` pair in the same way that `listToAttrs` does. + # Type: nameValueToAttrs :: { name :: String, value :: Any } -> Any + nameValueToAttrs = { name, value }: { + "${name}" = value; + }; + # if `maybe-null` is non-null, yield that. else, return the `default`. withDefault = default: maybe-null: if maybe-null != null then maybe-null @@ -22,9 +32,10 @@ rec { (name: value: builtins.elem name names) attrs; - # transform a list into an AttrSet via a function which maps an element to a name + value + # transform a list into an AttrSet via a function which maps an element to a { name, value } pair. + # it's an error for the same name to be specified more than once # Type: mapToAttrs :: (a -> { name :: String, value :: Any }) -> [a] -> AttrSet - mapToAttrs = f: list: builtins.listToAttrs (builtins.map f list); + mapToAttrs = f: list: listToDisjointAttrs (builtins.map f list); # flatten a nested AttrSet into a list of { path = [String]; value } items. # Type: flattenAttrs :: AttrSet[AttrSet|Any] -> [{ path :: String, value :: Any }] diff --git a/modules/persist/default.nix b/modules/persist/default.nix index 28578728..b96fb677 100644 --- a/modules/persist/default.nix +++ b/modules/persist/default.nix @@ -235,10 +235,14 @@ in } { # default each item along the backing path to have the same acl as the location it would be mounted. - sane.fs = sane-lib.mapToAttrs (fsSubpath: { - name = fsPathToBackingPath fsSubpath; - value.generated.acl = config.sane.fs."${fsSubpath}".generated.acl; - }) (path.walk store.prefix fspath); + sane.fs = lib.mkMerge (builtins.map + (fsSubpath: { + "${fsPathToBackingPath fsSubpath}" = { + generated.acl = config.sane.fs."${fsSubpath}".generated.acl; + }; + }) + (path.walk store.prefix fspath) + ); } ]; configsPerPath = lib.mapAttrsToList cfgFor cfg.byPath;