nixos: Check for duplicate assignments

This commit is contained in:
Jack O'Sullivan 2022-06-11 16:33:32 +01:00
parent 58b2c6d8c5
commit 1f51a3ec08
3 changed files with 66 additions and 17 deletions

View File

@ -2,7 +2,7 @@
let let
inherit (builtins) head tail mapAttrs attrValues; inherit (builtins) head tail mapAttrs attrValues;
inherit (lib) flatten optional mkOption mkDefault mkOptionType; inherit (lib) flatten optional mkOption mkDefault mkOptionType;
inherit (lib.my) homeStateVersion mkOpt' commonOpts inlineModule'; inherit (lib.my) homeStateVersion mkOpt' commonOpts inlineModule' applyAssertions;
cfg = config.home-manager; cfg = config.home-manager;
@ -40,7 +40,11 @@ let
] ++ (tail defs); ] ++ (tail defs);
}; };
homeOpts = with lib.types; { config, ... }: { homeOpts = with lib.types; { ... }@args:
let
config' = args.config;
in
{
options = { options = {
inherit (commonOpts) system nixpkgs home-manager; inherit (commonOpts) system nixpkgs home-manager;
# TODO: docCustom for home-manager? # TODO: docCustom for home-manager?
@ -53,16 +57,16 @@ let
description = "home-manager configuration module."; description = "home-manager configuration module.";
type = mkOptionType { type = mkOptionType {
name = "home-manager configuration"; name = "home-manager configuration";
merge = _: defs: mkHome { merge = _: defs: applyAssertions config (mkHome {
config' = config; inherit config';
defs = map (d: inlineModule' d.file d.value) defs; defs = map (d: inlineModule' d.file d.value) defs;
}; });
}; };
}; };
}; };
config = { config = {
nixpkgs = mkDefault config.home-manager; nixpkgs = mkDefault config'.home-manager;
}; };
}; };
in in

23
lib.nix
View File

@ -1,9 +1,10 @@
{ lib }: { lib }:
let let
inherit (builtins) length match replaceStrings elemAt mapAttrs head split; inherit (builtins) length match replaceStrings elemAt mapAttrs head split filter;
inherit (lib) inherit (lib)
genAttrs mapAttrs' mapAttrsToList filterAttrsRecursive nameValuePair types genAttrs mapAttrs' mapAttrsToList filterAttrsRecursive nameValuePair types
mkOption mkOverride mkForce mkIf mergeEqualOption optional hasPrefix; mkOption mkOverride mkForce mkIf mergeEqualOption optional hasPrefix
showWarnings concatStringsSep flatten unique;
inherit (lib.flake) defaultSystems; inherit (lib.flake) defaultSystems;
in in
rec { rec {
@ -69,6 +70,24 @@ rec {
mkDefault' = mkOverride 900; mkDefault' = mkOverride 900;
mkVMOverride' = mkOverride 9; mkVMOverride' = mkOverride 9;
# This is shocking...
duplicates = l:
flatten
(map
(e:
optional
((length (filter (e2: e2 == e) l)) > 1)
e)
(unique l));
applyAssertions = config: res:
let
failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions);
in
if failedAssertions != []
then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
else showWarnings config.warnings res;
homeStateVersion = hmBranch: { homeStateVersion = hmBranch: {
# The flake passes a default setting, but we don't care about that # The flake passes a default setting, but we don't care about that
# Currently don't need any logic here, but we might need to use a newer version later # Currently don't need any logic here, but we might need to use a newer version later

View File

@ -1,8 +1,10 @@
{ lib, pkgsFlakes, hmFlakes, inputs, pkgs', config, ... }: { lib, pkgsFlakes, hmFlakes, inputs, pkgs', config, ... }:
let let
inherit (builtins) attrValues mapAttrs; inherit (builtins) attrValues mapAttrs;
inherit (lib) substring flatten optional optionals mkIf mkDefault mkForce mkOption mkOptionType; inherit (lib)
inherit (lib.my) naiveIPv4Gateway homeStateVersion mkOpt' mkBoolOpt' mkDefault' commonOpts inlineModule'; substring flatten optional optionals mkIf mkDefault mkForce mkOption mkOptionType;
inherit (lib.my)
naiveIPv4Gateway homeStateVersion mkOpt' mkBoolOpt' mkDefault' commonOpts inlineModule' applyAssertions duplicates;
cfg = config.nixos; cfg = config.nixos;
@ -114,7 +116,11 @@ let
}; };
}; };
systemOpts = with lib.types; { name, config, ... }: { systemOpts = with lib.types; { name, ... }@args:
let
config' = args.config;
in
{
options = { options = {
inherit (commonOpts) system nixpkgs home-manager; inherit (commonOpts) system nixpkgs home-manager;
hmNixpkgs = commonOpts.nixpkgs; hmNixpkgs = commonOpts.nixpkgs;
@ -131,18 +137,17 @@ let
# Based on the definition of containers.<name>.config # Based on the definition of containers.<name>.config
type = mkOptionType { type = mkOptionType {
name = "Toplevel NixOS config"; name = "Toplevel NixOS config";
merge = _: defs: mkSystem { merge = _: defs: applyAssertions config (mkSystem {
inherit name; inherit name config';
config' = config;
defs = map (d: inlineModule' d.file d.value) defs; defs = map (d: inlineModule' d.file d.value) defs;
}; });
}; };
}; };
}; };
config = { config = {
home-manager = mkDefault config.nixpkgs; home-manager = mkDefault config'.nixpkgs;
hmNixpkgs = mkDefault config.nixpkgs; hmNixpkgs = mkDefault config'.nixpkgs;
}; };
}; };
in in
@ -156,4 +161,25 @@ in
systems = mkOpt' (attrsOf (submodule systemOpts)) { } "NixOS systems to be exported by nixfiles."; systems = mkOpt' (attrsOf (submodule systemOpts)) { } "NixOS systems to be exported by nixfiles.";
}; };
}; };
config = {
assertions =
let
assignedIPs =
flatten
(map
(as:
map
(a: [ a.ipv4.address a.ipv6.address ])
(attrValues as))
(attrValues allAssignments));
dupIPs = duplicates assignedIPs;
in
[
{
assertion = dupIPs == [ ];
message = "Duplicate assignments: ${toString dupIPs}";
}
];
};
} }