nixos/storage/disk: Allow only one match method

Having multiple matchers is a bit tricky if we don't know how they
should be combined. For example if we have a match on a label and a
device name and both produce valid matches, which one should we choose?

So let's restrict the use of device matchers to allow only one method
right now. If we later figure out a better way how to combine these
matchers, we can still lift this restriction easily.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
This commit is contained in:
aszlig
2017-01-05 00:32:19 +01:00
parent 4fbea84433
commit 02765b407f

View File

@@ -160,14 +160,35 @@ let
# Return true if an option is referencing a btrfs storage specification.
isBtrfs = storage: lib.isString storage && lib.hasPrefix "btrfs." storage;
# Make sure that whenever a fsType is set to something different than "btrfs"
# while using a "btrfs" device spec type we throw an assertion error.
assertions = lib.mapAttrsToList (fs: cfg: {
assertion = if isBtrfs cfg.storage then cfg.fsType == "btrfs" else true;
message = "The option `fileSystems.${fs}.fsType' is `${cfg.fsType}' but"
+ " \"btrfs\" is expected because `fileSystems.${fs}.storage'"
+ " is set to `${cfg.storage}'.";
}) config.fileSystems;
assertions = let
# Make sure that whenever a fsType is set to something different than
# "btrfs" while using a "btrfs" device spec type we throw an assertion
# error.
btrfsAssertions = lib.mapAttrsToList (fs: cfg: {
assertion = if isBtrfs cfg.storage then cfg.fsType == "btrfs" else true;
message = "The option `fileSystems.${fs}.fsType' is `${cfg.fsType}' but"
+ " \"btrfs\" is expected because `fileSystems.${fs}.storage'"
+ " is set to `${cfg.storage}'.";
}) config.fileSystems;
# Only allow one match method to be set for a disk and throw an assertion
# if either no match methods or too many (more than one) are defined.
matcherAssertions = lib.mapAttrsToList (disk: cfg: let
inherit (lib) attrNames filterAttrs;
isMatcher = name: name != "_module" && name != "allowIncomplete";
filterMatcher = name: val: isMatcher name && val != null;
defined = attrNames (filterAttrs filterMatcher cfg.match);
amount = lib.length defined;
optStr = "`storage.disk.${disk}'";
noneMsg = "No match methods have been defined for ${optStr}.";
manyMsg = "The disk ${optStr} has more than one match methods"
+ " defined: ${lib.concatStringsSep ", " defined}";
in {
assertion = amount == 1;
message = if amount < 1 then noneMsg else manyMsg;
}) config.storage.disk;
in btrfsAssertions ++ matcherAssertions;
in