Add the possibility to define assertions to be checked before activation.

This commit is contained in:
r-vdp 2023-03-22 15:52:56 +01:00
parent 02a0e81d6d
commit c9a47913f4
No known key found for this signature in database
3 changed files with 105 additions and 2 deletions

View file

@ -106,6 +106,50 @@ in
${system-manager}/bin/system-manager deactivate "$@"
'';
preActivationAssertionScript =
let
mkAssertion = { name, script, ... }: ''
# ${name}
echo -e "Evaluating pre-activation assertion ${name}...\n"
(
set +e
${script}
)
assertion_result=$?
if [ $assertion_result -ne 0 ]; then
failed_assertions+=${name}
fi
'';
mkAssertions = assertions:
lib.concatStringsSep "\n" (
lib.mapAttrsToList (name: mkAssertion) (
lib.filterAttrs (name: cfg: cfg.enable)
assertions
)
);
in
pkgs.writeShellScript "preActivationAssertions" ''
set -ou pipefail
declare -a failed_assertions=()
${mkAssertions nixosConfig.system-manager.preActivationAssertions}
if [ ''${#failed_assertions[@]} -ne 0 ]; then
for failed_assertion in ''${failed_assertions[@]}; do
echo "Pre-activation assertion $failed_assertion failed."
done
echo "See the output above for more details."
exit 1
else
echo "All pre-activation assertions succeeded."
exit 0
fi
'';
linkFarmNestedEntryFromDrv = dirs: drv: {
name = lib.concatStringsSep "/" (dirs ++ [ "${drv.name}" ]);
path = drv;
@ -120,6 +164,7 @@ in
(linkFarmBinEntryFromDrv activationScript)
(linkFarmBinEntryFromDrv deactivationScript)
(linkFarmBinEntryFromDrv registerProfileScript)
(linkFarmBinEntryFromDrv preActivationAssertionScript)
]
);
}

View file

@ -14,6 +14,24 @@
type = with lib.types; listOf str;
default = [ ];
};
preActivationAssertions = lib.mkOption {
type = with lib.types; attrsOf (submodule ({ name, ... }: {
options = {
enable = lib.mkEnableOption "the assertion";
name = lib.mkOption {
type = lib.types.str;
default = name;
};
script = lib.mkOption {
type = lib.types.str;
};
};
}));
default = { };
};
};
config = {
@ -46,6 +64,27 @@
}
);
system-manager.preActivationAssertions = {
osVersion =
let
supportedIds = [ "nixos" "ubuntu" ];
in
{
enable = true;
script = ''
source /etc/os-release
${lib.concatStringsSep "\n" (lib.flip map supportedIds (supportedId: ''
if [ $ID = "${supportedId}" ]; then
exit 0
fi
''))}
echo "This OS is not currently supported."
echo "Supported OSs are: ${lib.concatStringsSep ", " supportedIds}"
exit 1
'';
};
};
# Add the system directory for systemd
system-manager.etcFiles = [ "systemd/system" ];

View file

@ -2,6 +2,7 @@ mod etc_files;
mod services;
use anyhow::Result;
use std::process;
use crate::StorePath;
@ -11,12 +12,17 @@ pub fn activate(store_path: &StorePath, ephemeral: bool) -> Result<()> {
log::info!("Running in ephemeral mode");
}
// TODO we probably need to first deactivate left-over files and services
// before we start putting in place the new ones.
log::info!("Running pre-activation assertions...");
if !run_preactivation_assertions(store_path)?.success() {
anyhow::bail!("Failure in pre-activation assertions.");
}
log::info!("Activating etc files...");
etc_files::activate(store_path, ephemeral)?;
log::info!("Activating systemd services...");
services::activate(store_path, ephemeral)?;
Ok(())
}
@ -27,3 +33,16 @@ pub fn deactivate() -> Result<()> {
services::deactivate()?;
Ok(())
}
fn run_preactivation_assertions(store_path: &StorePath) -> Result<process::ExitStatus> {
let status = process::Command::new(
store_path
.store_path
.join("bin")
.join("preActivationAssertions"),
)
.stderr(process::Stdio::inherit())
.stdout(process::Stdio::inherit())
.status()?;
Ok(status)
}