Add assertions and warnings to modular services

Changed files
+147 -8
nixos
modules
misc
system
service
+3 -1
nixos/modules/misc/assertions.nix
···
};
};
-
# impl of assertions is in <nixpkgs/nixos/modules/system/activation/top-level.nix>
+
# impl of assertions is in
+
# - <nixpkgs/nixos/modules/system/activation/top-level.nix>
+
# - <nixpkgs/nixos/modules/system/service/portable/lib.nix>
}
+33
nixos/modules/system/service/portable/lib.nix
···
+
{ lib, ... }:
+
let
+
inherit (lib) concatLists mapAttrsToList showOption;
+
in
+
rec {
+
flattenMapServicesConfigToList =
+
f: loc: config:
+
f loc config
+
++ concatLists (
+
mapAttrsToList (
+
k: v:
+
flattenMapServicesConfigToList f (
+
loc
+
++ [
+
"services"
+
k
+
]
+
) v
+
) config.services
+
);
+
+
getWarnings = flattenMapServicesConfigToList (
+
loc: config: map (msg: "in ${showOption loc}: ${msg}") config.warnings
+
);
+
+
getAssertions = flattenMapServicesConfigToList (
+
loc: config:
+
map (ass: {
+
message = "in ${showOption loc}: ${ass.message}";
+
assertion = ass.assertion;
+
}) config.assertions
+
);
+
}
+5
nixos/modules/system/service/portable/service.nix
···
};
in
{
+
# https://nixos.org/manual/nixos/unstable/#modular-services
+
_class = "service";
+
imports = [
+
../../../misc/assertions.nix
+
];
options = {
services = mkOption {
type = types.attrsOf (
+83 -6
nixos/modules/system/service/portable/test.nix
···
inherit (lib) mkOption types;
+
portable-lib = import ./lib.nix { inherit lib; };
+
dummyPkg =
name:
derivation {
···
executable = "/usr/bin/echo"; # *giggles*
args = [ "hello" ];
};
+
assertions = [
+
{
+
assertion = false;
+
message = "you can't enable this for that reason";
+
}
+
];
+
warnings = [
+
"The `foo' service is deprecated and will go away soon!"
+
];
};
service2 = {
process = {
···
};
service3 = {
process = {
-
executable = dummyPkg "cowsay-ng" // {
-
meta.mainProgram = "cowsay";
+
executable = "/bin/false";
+
args = [ ];
+
};
+
services.exclacow = {
+
process = {
+
executable = dummyPkg "cowsay-ng" // {
+
meta.mainProgram = "cowsay";
+
};
+
args = [ "!" ];
};
-
args = [ "!" ];
+
assertions = [
+
{
+
assertion = false;
+
message = "you can't enable this for such reason";
+
}
+
];
+
warnings = [
+
"The `bar' service is deprecated and will go away soon!"
+
];
};
};
};
···
args = [ "hello" ];
};
services = { };
+
assertions = [
+
{
+
assertion = false;
+
message = "you can't enable this for that reason";
+
}
+
];
+
warnings = [
+
"The `foo' service is deprecated and will go away soon!"
+
];
};
service2 = {
process = {
···
args = [ "world" ];
};
services = { };
+
assertions = [ ];
+
warnings = [ ];
};
service3 = {
process = {
-
executable = "${dummyPkg "cowsay-ng"}/bin/cowsay";
-
args = [ "!" ];
+
executable = "/bin/false";
+
args = [ ];
};
-
services = { };
+
services.exclacow = {
+
process = {
+
executable = "${dummyPkg "cowsay-ng"}/bin/cowsay";
+
args = [ "!" ];
+
};
+
services = { };
+
assertions = [
+
{
+
assertion = false;
+
message = "you can't enable this for such reason";
+
}
+
];
+
warnings = [ "The `bar' service is deprecated and will go away soon!" ];
+
};
+
assertions = [ ];
+
warnings = [ ];
};
};
};
+
+
assert
+
portable-lib.getWarnings [ "service1" ] exampleEval.config.services.service1 == [
+
"in service1: The `foo' service is deprecated and will go away soon!"
+
];
+
+
assert
+
portable-lib.getAssertions [ "service1" ] exampleEval.config.services.service1 == [
+
{
+
message = "in service1: you can't enable this for that reason";
+
assertion = false;
+
}
+
];
+
+
assert
+
portable-lib.getWarnings [ "service3" ] exampleEval.config.services.service3 == [
+
"in service3.services.exclacow: The `bar' service is deprecated and will go away soon!"
+
];
+
assert
+
portable-lib.getAssertions [ "service3" ] exampleEval.config.services.service3 == [
+
{
+
message = "in service3.services.exclacow: you can't enable this for such reason";
+
assertion = false;
+
}
+
];
"ok";
+23 -1
nixos/modules/system/service/systemd/system.nix
···
{
lib,
config,
+
options,
pkgs,
...
}:
let
-
inherit (lib) concatMapAttrs mkOption types;
+
inherit (lib)
+
concatMapAttrs
+
mkOption
+
types
+
concatLists
+
mapAttrsToList
+
;
+
+
portable-lib = import ../portable/lib.nix { inherit lib; };
dash =
before: after:
···
# Second half of the magic: siphon units that were defined in isolation to the system
config = {
+
+
assertions = concatLists (
+
mapAttrsToList (
+
name: cfg: portable-lib.getAssertions (options.system.services.loc ++ [ name ]) cfg
+
) config.system.services
+
);
+
+
warnings = concatLists (
+
mapAttrsToList (
+
name: cfg: portable-lib.getWarnings (options.system.services.loc ++ [ name ]) cfg
+
) config.system.services
+
);
+
systemd.services = concatMapAttrs (
serviceName: topLevelService: makeUnits "services" serviceName topLevelService
) config.system.services;