nixos/activation: improve preSwitchChecks
A couple of improvements: 1. Avoid the generally discouraged apply argument to options, as it has quite weird semantics 2. Avoid issues when a user calls a preSwitchCheck `script`, which would've been silently overridden by the existing implementation. Reliance on a special attribute name like that is bound to lead to a very-hard-to-debug problem for someone at some point 3. Use writeShellApplication so that the preSwitchChecks are checked by shellcheck and and so that they run with basic bash guardrails 4. Fix shellcheck issue (testing the value of $?) 5. Add a positive preSwitchCheck to the nixos test, to make sure that that works as intended
This commit is contained in:
@@ -1,21 +1,35 @@
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
preSwitchCheckScript =
|
||||
set:
|
||||
lib.concatLines (
|
||||
lib.mapAttrsToList (name: text: ''
|
||||
# pre-switch check ${name}
|
||||
(
|
||||
${text}
|
||||
)
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Pre-switch check '${name}' failed"
|
||||
exit 1
|
||||
fi
|
||||
'') set
|
||||
);
|
||||
preSwitchCheckScript = lib.concatLines (
|
||||
lib.mapAttrsToList (name: text: ''
|
||||
# pre-switch check ${name}
|
||||
if ! (
|
||||
${text}
|
||||
); then
|
||||
echo "Pre-switch check '${name}' failed"
|
||||
exit 1
|
||||
fi
|
||||
'') config.system.preSwitchChecks
|
||||
);
|
||||
in
|
||||
{
|
||||
options.system.preSwitchChecksScript = lib.mkOption {
|
||||
type = lib.types.pathInStore;
|
||||
internal = true;
|
||||
readOnly = true;
|
||||
default = lib.getExe (
|
||||
pkgs.writeShellApplication {
|
||||
name = "pre-switch-checks";
|
||||
text = preSwitchCheckScript;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
options.system.preSwitchChecks = lib.mkOption {
|
||||
default = { };
|
||||
example = lib.literalExpression ''
|
||||
@@ -33,12 +47,5 @@ in
|
||||
'';
|
||||
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
|
||||
apply =
|
||||
set:
|
||||
set
|
||||
// {
|
||||
script = pkgs.writeShellScript "pre-switch-checks" (preSwitchCheckScript set);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ in
|
||||
--subst-var-by coreutils "${pkgs.coreutils}" \
|
||||
--subst-var-by distroId ${lib.escapeShellArg config.system.nixos.distroId} \
|
||||
--subst-var-by installBootLoader ${lib.escapeShellArg config.system.build.installBootLoader} \
|
||||
--subst-var-by preSwitchCheck ${lib.escapeShellArg config.system.preSwitchChecks.script} \
|
||||
--subst-var-by preSwitchCheck ${lib.escapeShellArg config.system.preSwitchChecksScript} \
|
||||
--subst-var-by localeArchive "${config.i18n.glibcLocales}/lib/locale/locale-archive" \
|
||||
--subst-var-by perl "${perlWrapped}" \
|
||||
--subst-var-by shell "${pkgs.bash}/bin/sh" \
|
||||
@@ -94,7 +94,7 @@ in
|
||||
--set TOPLEVEL ''${!toplevelVar} \
|
||||
--set DISTRO_ID ${lib.escapeShellArg config.system.nixos.distroId} \
|
||||
--set INSTALL_BOOTLOADER ${lib.escapeShellArg config.system.build.installBootLoader} \
|
||||
--set PRE_SWITCH_CHECK ${lib.escapeShellArg config.system.preSwitchChecks.script} \
|
||||
--set PRE_SWITCH_CHECK ${lib.escapeShellArg config.system.preSwitchChecksScript} \
|
||||
--set LOCALE_ARCHIVE ${config.i18n.glibcLocales}/lib/locale/locale-archive \
|
||||
--set SYSTEMD ${config.systemd.package}
|
||||
)
|
||||
|
||||
@@ -343,7 +343,7 @@ in
|
||||
perl = pkgs.perl.withPackages (p: with p; [ ConfigIniFiles FileSlurp ]);
|
||||
# End if legacy environment variables
|
||||
|
||||
preSwitchCheck = config.system.preSwitchChecks.script;
|
||||
preSwitchCheck = config.system.preSwitchChecksScript;
|
||||
|
||||
# Not actually used in the builder. `passedChecks` is just here to create
|
||||
# the build dependencies. Checks are similar to build dependencies in the
|
||||
|
||||
@@ -611,6 +611,10 @@ in {
|
||||
other = {
|
||||
system.switch.enable = true;
|
||||
users.mutableUsers = true;
|
||||
system.preSwitchChecks.succeeds = ''
|
||||
echo this will succeed
|
||||
true
|
||||
'';
|
||||
specialisation.failingCheck.configuration.system.preSwitchChecks.failEveryTime = ''
|
||||
echo this will fail
|
||||
false
|
||||
|
||||
Reference in New Issue
Block a user