Fix fcron service to properly load the crontab on first startup, make it multi-instance aware, add tests

This commit is contained in:
Sander van der Burg 2021-04-03 15:45:12 +02:00 committed by Sander van der Burg
parent c130294a0a
commit 89dba90892
7 changed files with 96 additions and 9 deletions

View File

@ -127,7 +127,7 @@ rec {
pkg = constructors.declarativeFcron { pkg = constructors.declarativeFcron {
fcrontabPerUser = { fcrontabPerUser = {
systab = '' systab = ''
@ 1 echo hello >> /tmp/hello */1 * * * * echo hello >> /tmp/hello
''; '';
}; };
}; };

View File

@ -74,7 +74,7 @@ in
declarativeFcron = import ./fcron/declarative.nix { declarativeFcron = import ./fcron/declarative.nix {
inherit createManagedProcess stateDir spoolDir runtimeDir tmpDir forceDisableUserChange; inherit createManagedProcess stateDir spoolDir runtimeDir tmpDir forceDisableUserChange;
inherit (pkgs) lib writeTextFile fcron; inherit (pkgs) lib writeTextFile fcron utillinux;
}; };
hydra-evaluator = import ./hydra/hydra-evaluator.nix { hydra-evaluator = import ./hydra/hydra-evaluator.nix {

View File

@ -1,4 +1,4 @@
{createManagedProcess, writeTextFile, lib, fcron, stateDir, runtimeDir, tmpDir, spoolDir, forceDisableUserChange}: {createManagedProcess, writeTextFile, lib, fcron, utillinux, stateDir, runtimeDir, tmpDir, spoolDir, forceDisableUserChange}:
{ instanceSuffix ? "" { instanceSuffix ? ""
, instanceName ? "fcron${instanceSuffix}" , instanceName ? "fcron${instanceSuffix}"
@ -8,14 +8,15 @@
let let
fcronSpoolDir = "${spoolDir}/${instanceName}"; fcronSpoolDir = "${spoolDir}/${instanceName}";
fcronEtcDir = "${stateDir}/etc/${instanceName}";
in in
import ./default.nix { import ./default.nix {
inherit createManagedProcess writeTextFile lib fcron stateDir runtimeDir tmpDir spoolDir forceDisableUserChange; inherit createManagedProcess writeTextFile lib fcron stateDir runtimeDir tmpDir spoolDir forceDisableUserChange;
} { } {
inherit instanceSuffix instanceName; inherit instanceSuffix instanceName;
initialize = '' initialize =
${lib.concatMapStrings (user: lib.concatMapStrings (user:
let let
fcrontab = builtins.getAttr user fcrontabPerUser; fcrontab = builtins.getAttr user fcrontabPerUser;
fcrontabFile = writeTextFile { fcrontabFile = writeTextFile {
@ -26,7 +27,9 @@ import ./default.nix {
'' ''
cp ${fcrontabFile} ${fcronSpoolDir}/${user}.orig cp ${fcrontabFile} ${fcronSpoolDir}/${user}.orig
'' ''
) (builtins.attrNames fcrontabPerUser)} + ''
${initialize} ${lib.optionalString (!forceDisableUserChange) "${utillinux}/bin/runuser -u root -g ${instanceName} --"} fcrontab -c ${fcronEtcDir}/fcron.conf -u systab -z
''; ''
) (builtins.attrNames fcrontabPerUser)
+ initialize;
} }

View File

@ -20,6 +20,21 @@ let
user = instanceName; user = instanceName;
group = instanceName; group = instanceName;
# We must override the package configuration settings to compile it with different configuration settings,
# if we want to use a different group or run fcron as unprivileged user
fcronPkg =
if forceDisableUserChange then fcron.overrideAttrs (originalAttrs:
originalAttrs // {
configureFlags = originalAttrs.configureFlags ++ [ "--with-run-non-privileged" "--with-rootname=unprivileged" "--with-rootgroup=users" "--with-username=unprivileged" "--with-groupname=users" ];
}
)
else if user != "fcron" || group != "fcron" then fcron.overrideAttrs (originalAttrs:
originalAttrs // {
configureFlags = originalAttrs.configureFlags ++ [ "--with-rootgroup=${group}" "--with-username=${user}" "--with-groupname=${group}" ];
}
)
else fcron;
in in
createManagedProcess { createManagedProcess {
inherit instanceName; inherit instanceName;
@ -34,7 +49,8 @@ createManagedProcess {
${initialize} ${initialize}
''; '';
process = "${fcron}/bin/fcron"; path = [ fcronPkg ];
process = "${fcronPkg}/bin/fcron";
args = [ "--configfile" "${fcronEtcDir}/fcron.conf" ]; args = [ "--configfile" "${fcronEtcDir}/fcron.conf" ];
foregroundProcessExtraArgs = [ "--foreground" "--nosyslog" ]; foregroundProcessExtraArgs = [ "--foreground" "--nosyslog" ];
daemonExtraArgs = [ "--background" ]; daemonExtraArgs = [ "--background" ];

View File

@ -27,6 +27,10 @@ in
inherit pkgs processManagers profiles testService; inherit pkgs processManagers profiles testService;
}; };
fcron = import ./fcron {
inherit pkgs processManagers profiles testService;
};
influxdb = import ./influxdb { influxdb = import ./influxdb {
inherit pkgs processManagers profiles testService; inherit pkgs processManagers profiles testService;
}; };

24
tests/fcron/default.nix Normal file
View File

@ -0,0 +1,24 @@
{ pkgs, testService, processManagers, profiles }:
testService {
exprFile = ./processes.nix;
readiness = {instanceName, instance, ...}:
''
'';
tests = {instanceName, instance, ...}:
''
machine.succeed("sleep 70")
''
+
(if instanceName == "fcron" then ''
machine.succeed("grep 'hello' /tmp/hello")
''
else if instanceName == "fcron-secondary" then ''
machine.succeed("grep 'bye' /tmp/bye")
''
else "");
inherit processManagers profiles;
}

40
tests/fcron/processes.nix Normal file
View File

@ -0,0 +1,40 @@
{ pkgs ? import <nixpkgs> { inherit system; }
, system ? builtins.currentSystem
, stateDir ? "/var"
, runtimeDir ? "${stateDir}/run"
, logDir ? "${stateDir}/log"
, spoolDir ? "${stateDir}/spool"
, cacheDir ? "${stateDir}/cache"
, libDir ? "${stateDir}/lib"
, tmpDir ? (if stateDir == "/var" then "/tmp" else "${stateDir}/tmp")
, forceDisableUserChange ? false
, processManager
}:
let
constructors = import ../../services-agnostic/constructors.nix {
inherit pkgs stateDir runtimeDir logDir tmpDir cacheDir libDir spoolDir forceDisableUserChange processManager;
};
in
rec {
fcron = {
pkg = constructors.declarativeFcron {
fcrontabPerUser = {
systab = ''
*/1 * * * * echo hello >> /tmp/hello
'';
};
};
};
fcron-secondary = {
pkg = constructors.declarativeFcron {
instanceSuffix = "-secondary";
fcrontabPerUser = {
systab = ''
*/1 * * * * echo bye >> /tmp/bye
'';
};
};
};
}