Merge pull request #162063 from martinetd/logrotate_size
logrotate: update to freeform
This commit is contained in:
commit
c7ac6ff789
11 changed files with 435 additions and 107 deletions
nixos
doc/manual
modules
services
logging
misc
networking
web-servers
system/boot
virtualisation
tests
pkgs/tools/system/logrotate
|
@ -1655,9 +1655,20 @@
|
|||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>services.logrotate.enable</literal> now defaults to
|
||||
true if any rotate path has been defined, and some paths have
|
||||
been added by default.
|
||||
<link linkend="opt-services.logrotate.enable">services.logrotate.enable</link>
|
||||
now defaults to true if any rotate path has been defined, and
|
||||
some paths have been added by default.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The logrotate module also has been updated to freeform syntax:
|
||||
<link linkend="opt-services.logrotate.paths">services.logrotate.paths</link>
|
||||
and
|
||||
<link linkend="opt-services.logrotate.extraConfig">services.logrotate.extraConfig</link>
|
||||
will work, but issue deprecation warnings and
|
||||
<link linkend="opt-services.logrotate.settings">services.logrotate.settings</link>
|
||||
should now be used instead.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
|
|
|
@ -578,8 +578,11 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
- `services.mattermost.plugins` has been added to allow the declarative installation of Mattermost plugins.
|
||||
Plugins are automatically repackaged using autoPatchelf.
|
||||
|
||||
- `services.logrotate.enable` now defaults to true if any rotate path has
|
||||
- [services.logrotate.enable](#opt-services.logrotate.enable) now defaults to true if any rotate path has
|
||||
been defined, and some paths have been added by default.
|
||||
- The logrotate module also has been updated to freeform syntax: [services.logrotate.paths](#opt-services.logrotate.paths)
|
||||
and [services.logrotate.extraConfig](#opt-services.logrotate.extraConfig) will work, but issue deprecation
|
||||
warnings and [services.logrotate.settings](#opt-services.logrotate.settings) should now be used instead.
|
||||
|
||||
- The `zrepl` package has been updated from 0.4.0 to 0.5:
|
||||
|
||||
|
|
|
@ -5,7 +5,10 @@ with lib;
|
|||
let
|
||||
cfg = config.services.logrotate;
|
||||
|
||||
pathOpts = { name, ... }: {
|
||||
# deprecated legacy compat settings
|
||||
# these options will be removed before 22.11 in the following PR:
|
||||
# https://github.com/NixOS/nixpkgs/pull/164169
|
||||
pathOpts = { name, ... }: {
|
||||
options = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
|
@ -86,23 +89,113 @@ let
|
|||
config.name = name;
|
||||
};
|
||||
|
||||
mkConf = pathOpts: ''
|
||||
# generated by NixOS using the `services.logrotate.paths.${pathOpts.name}` attribute set
|
||||
${concatMapStringsSep " " (path: ''"${path}"'') (toList pathOpts.path)} {
|
||||
${optionalString (pathOpts.user != null || pathOpts.group != null) "su ${pathOpts.user} ${pathOpts.group}"}
|
||||
${pathOpts.frequency}
|
||||
rotate ${toString pathOpts.keep}
|
||||
${pathOpts.extraConfig}
|
||||
}
|
||||
'';
|
||||
|
||||
paths = sortProperties (attrValues (filterAttrs (_: pathOpts: pathOpts.enable) cfg.paths));
|
||||
configFile = pkgs.writeText "logrotate.conf" (
|
||||
concatStringsSep "\n" (
|
||||
[ "missingok" "notifempty" cfg.extraConfig ] ++ (map mkConf paths)
|
||||
)
|
||||
generateLine = n: v:
|
||||
if builtins.elem n [ "files" "priority" "enable" "global" ] || v == null then null
|
||||
else if builtins.elem n [ "extraConfig" "frequency" ] then "${v}\n"
|
||||
else if builtins.elem n [ "firstaction" "lastaction" "prerotate" "postrotate" "preremove" ]
|
||||
then "${n}\n ${v}\n endscript\n"
|
||||
else if isInt v then "${n} ${toString v}\n"
|
||||
else if v == true then "${n}\n"
|
||||
else if v == false then "no${n}\n"
|
||||
else "${n} ${v}\n";
|
||||
generateSection = indent: settings: concatStringsSep (fixedWidthString indent " " "") (
|
||||
filter (x: x != null) (mapAttrsToList generateLine settings)
|
||||
);
|
||||
|
||||
# generateSection includes a final newline hence weird closing brace
|
||||
mkConf = settings:
|
||||
if settings.global or false then generateSection 0 settings
|
||||
else ''
|
||||
${concatMapStringsSep "\n" (files: ''"${files}"'') (toList settings.files)} {
|
||||
${generateSection 2 settings}}
|
||||
'';
|
||||
|
||||
# below two mapPaths are compat functions
|
||||
mapPathOptToSetting = n: v:
|
||||
if n == "keep" then nameValuePair "rotate" v
|
||||
else if n == "path" then nameValuePair "files" v
|
||||
else nameValuePair n v;
|
||||
|
||||
mapPathsToSettings = path: pathOpts:
|
||||
nameValuePair path (
|
||||
filterAttrs (n: v: ! builtins.elem n [ "user" "group" "name" ] && v != "") (
|
||||
(mapAttrs' mapPathOptToSetting pathOpts) //
|
||||
{
|
||||
su =
|
||||
if pathOpts.user != null
|
||||
then "${pathOpts.user} ${pathOpts.group}"
|
||||
else null;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
settings = sortProperties (attrValues (filterAttrs (_: settings: settings.enable) (
|
||||
foldAttrs recursiveUpdate { } [
|
||||
{
|
||||
header = {
|
||||
enable = true;
|
||||
missingok = true;
|
||||
notifempty = true;
|
||||
frequency = "weekly";
|
||||
rotate = 4;
|
||||
};
|
||||
# compat section
|
||||
extraConfig = {
|
||||
enable = (cfg.extraConfig != "");
|
||||
global = true;
|
||||
extraConfig = cfg.extraConfig;
|
||||
priority = 101;
|
||||
};
|
||||
}
|
||||
(mapAttrs' mapPathsToSettings cfg.paths)
|
||||
cfg.settings
|
||||
{ header = { global = true; priority = 100; }; }
|
||||
]
|
||||
)));
|
||||
configFile = pkgs.writeTextFile {
|
||||
name = "logrotate.conf";
|
||||
text = concatStringsSep "\n" (
|
||||
map mkConf settings
|
||||
);
|
||||
checkPhase = optionalString cfg.checkConfig ''
|
||||
# logrotate --debug also checks that users specified in config
|
||||
# file exist, but we only have sandboxed users here so brown these
|
||||
# out. according to man page that means su, create and createolddir.
|
||||
# files required to exist also won't be present, so missingok is forced.
|
||||
user=$(${pkgs.coreutils}/bin/id -un)
|
||||
group=$(${pkgs.coreutils}/bin/id -gn)
|
||||
sed -e "s/\bsu\s.*/su $user $group/" \
|
||||
-e "s/\b\(create\s\+[0-9]*\s*\|createolddir\s\+[0-9]*\s\+\).*/\1$user $group/" \
|
||||
-e "1imissingok" -e "s/\bnomissingok\b//" \
|
||||
$out > /tmp/logrotate.conf
|
||||
# Since this makes for very verbose builds only show real error.
|
||||
# There is no way to control log level, but logrotate hardcodes
|
||||
# 'error:' at common log level, so we can use grep, taking care
|
||||
# to keep error codes
|
||||
set -o pipefail
|
||||
if ! ${pkgs.logrotate}/sbin/logrotate --debug /tmp/logrotate.conf 2>&1 \
|
||||
| ( ! grep "error:" ) > /tmp/logrotate-error; then
|
||||
echo "Logrotate configuration check failed."
|
||||
echo "The failing configuration (after adjustments to pass tests in sandbox) was:"
|
||||
printf "%s\n" "-------"
|
||||
cat /tmp/logrotate.conf
|
||||
printf "%s\n" "-------"
|
||||
echo "The error reported by logrotate was as follow:"
|
||||
printf "%s\n" "-------"
|
||||
cat /tmp/logrotate-error
|
||||
printf "%s\n" "-------"
|
||||
echo "You can disable this check with services.logrotate.checkConfig = false,"
|
||||
echo "but if you think it should work please report this failure along with"
|
||||
echo "the config file being tested!"
|
||||
false
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
mailOption =
|
||||
if foldr (n: a: a || n ? mail) false (attrValues cfg.settings)
|
||||
then "--mail=${pkgs.mailutils}/bin/mail"
|
||||
else "";
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
|
@ -112,17 +205,121 @@ in
|
|||
options = {
|
||||
services.logrotate = {
|
||||
enable = mkEnableOption "the logrotate systemd service" // {
|
||||
default = foldr (n: a: a || n.enable) false (attrValues cfg.paths);
|
||||
defaultText = literalExpression "cfg.paths != {}";
|
||||
default = foldr (n: a: a || n.enable) false (attrValues cfg.settings);
|
||||
defaultText = literalExpression "cfg.settings != {}";
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
default = { };
|
||||
description = ''
|
||||
logrotate freeform settings: each attribute here will define its own section,
|
||||
ordered by priority, which can either define files to rotate with their settings
|
||||
or settings common to all further files settings.
|
||||
Refer to <link xlink:href="https://linux.die.net/man/8/logrotate"/> for details.
|
||||
'';
|
||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||
freeformType = with types; attrsOf (nullOr (oneOf [ int bool str ]));
|
||||
|
||||
options = {
|
||||
enable = mkEnableOption "setting individual kill switch" // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
global = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether this setting is a global option or not: set to have these
|
||||
settings apply to all files settings with a higher priority.
|
||||
'';
|
||||
};
|
||||
files = mkOption {
|
||||
type = with types; either str (listOf str);
|
||||
default = name;
|
||||
defaultText = ''
|
||||
The attrset name if not specified
|
||||
'';
|
||||
description = ''
|
||||
Single or list of files for which rules are defined.
|
||||
The files are quoted with double-quotes in logrotate configuration,
|
||||
so globs and spaces are supported.
|
||||
Note this setting is ignored if globals is true.
|
||||
'';
|
||||
};
|
||||
|
||||
frequency = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
How often to rotate the logs. Defaults to previously set global setting,
|
||||
which itself defauts to weekly.
|
||||
'';
|
||||
};
|
||||
|
||||
priority = mkOption {
|
||||
type = types.int;
|
||||
default = 1000;
|
||||
description = ''
|
||||
Order of this logrotate block in relation to the others. The semantics are
|
||||
the same as with `lib.mkOrder`. Smaller values are inserted first.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
}));
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
default = configFile;
|
||||
defaultText = ''
|
||||
A configuration file automatically generated by NixOS.
|
||||
'';
|
||||
description = ''
|
||||
Override the configuration file used by MySQL. By default,
|
||||
NixOS generates one automatically from <xref linkend="opt-services.logrotate.settings"/>.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
pkgs.writeText "logrotate.conf" '''
|
||||
missingok
|
||||
"/var/log/*.log" {
|
||||
rotate 4
|
||||
weekly
|
||||
}
|
||||
''';
|
||||
'';
|
||||
};
|
||||
|
||||
checkConfig = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether the config should be checked at build time.
|
||||
|
||||
Some options are not checkable at build time because of the build sandbox:
|
||||
for example, the test does not know about existing files and system users are
|
||||
not known.
|
||||
These limitations mean we must adjust the file for tests (missingok is forced
|
||||
and users are replaced by dummy users), so tests are complemented by a
|
||||
logrotate-checkconf service that is enabled by default.
|
||||
This extra check can be disabled by disabling it at the systemd level with the
|
||||
<option>services.systemd.services.logrotate-checkconf.enable</option> option.
|
||||
|
||||
Conversely there are still things that might make this check fail incorrectly
|
||||
(e.g. a file path where we don't have access to intermediate directories):
|
||||
in this case you can disable the failing check with this option.
|
||||
'';
|
||||
};
|
||||
|
||||
# deprecated legacy compat settings
|
||||
paths = mkOption {
|
||||
type = with types; attrsOf (submodule pathOpts);
|
||||
default = {};
|
||||
default = { };
|
||||
description = ''
|
||||
Attribute set of paths to rotate. The order each block appears in the generated configuration file
|
||||
can be controlled by the <link linkend="opt-services.logrotate.paths._name_.priority">priority</link> option
|
||||
using the same semantics as `lib.mkOrder`. Smaller values have a greater priority.
|
||||
This setting has been deprecated in favor of <link linkend="opt-services.logrotate.settings">logrotate settings</link>.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
|
@ -151,19 +348,37 @@ in
|
|||
description = ''
|
||||
Extra contents to append to the logrotate configuration file. Refer to
|
||||
<link xlink:href="https://linux.die.net/man/8/logrotate"/> for details.
|
||||
This setting has been deprecated in favor of
|
||||
<link linkend="opt-services.logrotate.settings">logrotate settings</link>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = mapAttrsToList (name: pathOpts:
|
||||
{ assertion = (pathOpts.user != null) == (pathOpts.group != null);
|
||||
message = ''
|
||||
If either of `services.logrotate.paths.${name}.user` or `services.logrotate.paths.${name}.group` are specified then *both* must be specified.
|
||||
'';
|
||||
}
|
||||
) cfg.paths;
|
||||
assertions =
|
||||
mapAttrsToList
|
||||
(name: pathOpts:
|
||||
{
|
||||
assertion = (pathOpts.user != null) == (pathOpts.group != null);
|
||||
message = ''
|
||||
If either of `services.logrotate.paths.${name}.user` or `services.logrotate.paths.${name}.group` are specified then *both* must be specified.
|
||||
'';
|
||||
})
|
||||
cfg.paths;
|
||||
|
||||
warnings =
|
||||
(mapAttrsToList
|
||||
(name: pathOpts: ''
|
||||
Using config.services.logrotate.paths.${name} is deprecated and will become unsupported in a future release.
|
||||
Please use services.logrotate.settings instead.
|
||||
'')
|
||||
cfg.paths
|
||||
) ++
|
||||
(optional (cfg.extraConfig != "") ''
|
||||
Using config.services.logrotate.extraConfig is deprecated and will become unsupported in a future release.
|
||||
Please use services.logrotate.settings with globals=true instead.
|
||||
'');
|
||||
|
||||
systemd.services.logrotate = {
|
||||
description = "Logrotate Service";
|
||||
|
@ -172,7 +387,16 @@ in
|
|||
serviceConfig = {
|
||||
Restart = "no";
|
||||
User = "root";
|
||||
ExecStart = "${pkgs.logrotate}/sbin/logrotate ${configFile}";
|
||||
ExecStart = "${pkgs.logrotate}/sbin/logrotate ${mailOption} ${cfg.configFile}";
|
||||
};
|
||||
};
|
||||
systemd.services.logrotate-checkconf = {
|
||||
description = "Logrotate configuration check";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = "${pkgs.logrotate}/sbin/logrotate --debug ${cfg.configFile}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -848,10 +848,7 @@ in {
|
|||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
copytruncate
|
||||
compress
|
||||
'';
|
||||
default = "";
|
||||
description = ''
|
||||
Extra logrotate config options for this path. Refer to
|
||||
<link xlink:href="https://linux.die.net/man/8/logrotate"/> for details.
|
||||
|
@ -977,13 +974,14 @@ in {
|
|||
# Enable rotation of log files
|
||||
services.logrotate = {
|
||||
enable = cfg.logrotate.enable;
|
||||
paths = {
|
||||
settings = {
|
||||
gitlab = {
|
||||
path = "${cfg.statePath}/log/*.log";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
files = "${cfg.statePath}/log/*.log";
|
||||
su = "${cfg.user} ${cfg.group}";
|
||||
frequency = cfg.logrotate.frequency;
|
||||
keep = cfg.logrotate.keep;
|
||||
rotate = cfg.logrotate.keep;
|
||||
copytruncate = true;
|
||||
compress = true;
|
||||
extraConfig = cfg.logrotate.extraConfig;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -51,18 +51,14 @@ in
|
|||
|
||||
environment.etc."lxd-image-server/config.toml".source = format.generate "config.toml" cfg.settings;
|
||||
|
||||
services.logrotate.paths.lxd-image-server = {
|
||||
path = "/var/log/lxd-image-server/lxd-image-server.log";
|
||||
services.logrotate.settings.lxd-image-server = {
|
||||
files = "/var/log/lxd-image-server/lxd-image-server.log";
|
||||
frequency = "daily";
|
||||
keep = 21;
|
||||
extraConfig = ''
|
||||
create 755 lxd-image-server ${cfg.group}
|
||||
missingok
|
||||
compress
|
||||
delaycompress
|
||||
copytruncate
|
||||
notifempty
|
||||
'';
|
||||
rotate = 21;
|
||||
create = "755 lxd-image-server ${cfg.group}";
|
||||
compress = true;
|
||||
delaycompress = true;
|
||||
copytruncate = true;
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
|
|
|
@ -710,20 +710,15 @@ in
|
|||
|
||||
services.logrotate = optionalAttrs (cfg.logFormat != "none") {
|
||||
enable = mkDefault true;
|
||||
paths.httpd = {
|
||||
path = "${cfg.logDir}/*.log";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
settings.httpd = {
|
||||
files = "${cfg.logDir}/*.log";
|
||||
su = "${cfg.user} ${cfg.group}";
|
||||
frequency = "daily";
|
||||
keep = 28;
|
||||
extraConfig = ''
|
||||
sharedscripts
|
||||
compress
|
||||
delaycompress
|
||||
postrotate
|
||||
systemctl reload httpd.service > /dev/null 2>/dev/null || true
|
||||
endscript
|
||||
'';
|
||||
rotate = 28;
|
||||
sharedscripts = true;
|
||||
compress = true;
|
||||
delaycompress = true;
|
||||
postrotate = "systemctl reload httpd.service > /dev/null 2>/dev/null || true";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -989,17 +989,14 @@ in
|
|||
nginx.gid = config.ids.gids.nginx;
|
||||
};
|
||||
|
||||
services.logrotate.paths.nginx = mapAttrs (_: mkDefault) {
|
||||
path = "/var/log/nginx/*.log";
|
||||
services.logrotate.settings.nginx = mapAttrs (_: mkDefault) {
|
||||
files = "/var/log/nginx/*.log";
|
||||
frequency = "weekly";
|
||||
keep = 26;
|
||||
extraConfig = ''
|
||||
compress
|
||||
delaycompress
|
||||
postrotate
|
||||
[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`
|
||||
endscript
|
||||
'';
|
||||
su = "${cfg.user} ${cfg.group}";
|
||||
rotate = 26;
|
||||
compress = true;
|
||||
delaycompress = true;
|
||||
postrotate = "[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -612,22 +612,18 @@ in
|
|||
|
||||
boot.kernelParams = optional (!cfg.enableUnifiedCgroupHierarchy) "systemd.unified_cgroup_hierarchy=0";
|
||||
|
||||
services.logrotate.paths = {
|
||||
services.logrotate.settings = {
|
||||
"/var/log/btmp" = mapAttrs (_: mkDefault) {
|
||||
frequency = "monthly";
|
||||
keep = 1;
|
||||
extraConfig = ''
|
||||
create 0660 root ${config.users.groups.utmp.name}
|
||||
minsize 1M
|
||||
'';
|
||||
rotate = 1;
|
||||
create = "0660 root ${config.users.groups.utmp.name}";
|
||||
minsize = "1M";
|
||||
};
|
||||
"/var/log/wtmp" = mapAttrs (_: mkDefault) {
|
||||
frequency = "monthly";
|
||||
keep = 1;
|
||||
extraConfig = ''
|
||||
create 0664 root ${config.users.groups.utmp.name}
|
||||
minsize 1M
|
||||
'';
|
||||
rotate = 1;
|
||||
create = "0664 root ${config.users.groups.utmp.name}";
|
||||
minsize = "1M";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -146,15 +146,11 @@ in
|
|||
|
||||
services.logrotate = {
|
||||
enable = true;
|
||||
extraConfig = ''
|
||||
/var/log/waagent.log {
|
||||
compress
|
||||
monthly
|
||||
rotate 6
|
||||
notifempty
|
||||
missingok
|
||||
}
|
||||
'';
|
||||
settings."/var/log/waagent.log" = {
|
||||
compress = true;
|
||||
frequency = "monthly";
|
||||
rotate = 6;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.targets.provisioned = {
|
||||
|
|
|
@ -1,26 +1,105 @@
|
|||
# Test logrotate service works and is enabled by default
|
||||
|
||||
import ./make-test-python.nix ({ pkgs, ...} : rec {
|
||||
let
|
||||
importTest = { ... }: {
|
||||
services.logrotate.settings.import = {
|
||||
olddir = false;
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
import ./make-test-python.nix ({ pkgs, ... }: rec {
|
||||
name = "logrotate";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ martinetd ];
|
||||
};
|
||||
|
||||
# default machine
|
||||
nodes.machine = { ... }: {
|
||||
nodes = {
|
||||
defaultMachine = { ... }: { };
|
||||
failingMachine = { ... }: {
|
||||
services.logrotate.configFile = pkgs.writeText "logrotate.conf" ''
|
||||
# self-written config file
|
||||
su notarealuser notagroupeither
|
||||
'';
|
||||
};
|
||||
machine = { config, ... }: {
|
||||
imports = [ importTest ];
|
||||
|
||||
services.logrotate.settings = {
|
||||
# remove default frequency header and add another
|
||||
header = {
|
||||
frequency = null;
|
||||
delaycompress = true;
|
||||
};
|
||||
# extra global setting... affecting nothing
|
||||
last_line = {
|
||||
global = true;
|
||||
priority = 2000;
|
||||
shred = true;
|
||||
};
|
||||
# using mail somewhere should add --mail to logrotate invokation
|
||||
sendmail = {
|
||||
mail = "user@domain.tld";
|
||||
};
|
||||
# postrotate should be suffixed by 'endscript'
|
||||
postrotate = {
|
||||
postrotate = "touch /dev/null";
|
||||
};
|
||||
# check checkConfig works as expected: there is nothing to check here
|
||||
# except that the file build passes
|
||||
checkConf = {
|
||||
su = "root utmp";
|
||||
createolddir = "0750 root utmp";
|
||||
create = "root utmp";
|
||||
"create " = "0750 root utmp";
|
||||
};
|
||||
# multiple paths should be aggregated
|
||||
multipath = {
|
||||
files = [ "file1" "file2" ];
|
||||
};
|
||||
# overriding imported path should keep existing attributes
|
||||
# (e.g. olddir is still set)
|
||||
import = {
|
||||
notifempty = true;
|
||||
};
|
||||
};
|
||||
# extraConfig compatibility - should be added to top level, early.
|
||||
services.logrotate.extraConfig = ''
|
||||
nomail
|
||||
'';
|
||||
# paths compatibility
|
||||
services.logrotate.paths = {
|
||||
compat_path = {
|
||||
path = "compat_test_path";
|
||||
};
|
||||
# user/group should be grouped as 'su user group'
|
||||
compat_user = {
|
||||
user = config.users.users.root.name;
|
||||
group = "root";
|
||||
};
|
||||
# extraConfig in path should be added to block
|
||||
compat_extraConfig = {
|
||||
extraConfig = "dateext";
|
||||
};
|
||||
# keep -> rotate
|
||||
compat_keep = {
|
||||
keep = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
''
|
||||
with subtest("whether logrotate works"):
|
||||
machine.succeed(
|
||||
# we must rotate once first to create logrotate stamp
|
||||
"systemctl start logrotate.service")
|
||||
# we must rotate once first to create logrotate stamp
|
||||
defaultMachine.succeed("systemctl start logrotate.service")
|
||||
# we need to wait for console text once here to
|
||||
# clear console buffer up to this point for next wait
|
||||
machine.wait_for_console_text('logrotate.service: Deactivated successfully')
|
||||
defaultMachine.wait_for_console_text('logrotate.service: Deactivated successfully')
|
||||
|
||||
machine.succeed(
|
||||
defaultMachine.succeed(
|
||||
# wtmp is present in default config.
|
||||
"rm -f /var/log/wtmp*",
|
||||
# we need to give it at least 1MB
|
||||
|
@ -28,10 +107,46 @@ import ./make-test-python.nix ({ pkgs, ...} : rec {
|
|||
|
||||
# move into the future and check rotation.
|
||||
"date -s 'now + 1 month + 1 day'")
|
||||
machine.wait_for_console_text('logrotate.service: Deactivated successfully')
|
||||
machine.succeed(
|
||||
defaultMachine.wait_for_console_text('logrotate.service: Deactivated successfully')
|
||||
defaultMachine.succeed(
|
||||
# check rotate worked
|
||||
"[ -e /var/log/wtmp.1 ]",
|
||||
)
|
||||
with subtest("default config does not have mail"):
|
||||
defaultMachine.fail("systemctl cat logrotate.service | grep -- --mail")
|
||||
with subtest("using mails adds mail option"):
|
||||
machine.succeed("systemctl cat logrotate.service | grep -- --mail")
|
||||
with subtest("check generated config matches expectation"):
|
||||
machine.succeed(
|
||||
# copy conf to /tmp/logrotate.conf for easy grep
|
||||
"conf=$(systemctl cat logrotate | grep -oE '/nix/store[^ ]*logrotate.conf'); cp $conf /tmp/logrotate.conf",
|
||||
"! grep weekly /tmp/logrotate.conf",
|
||||
"grep -E '^delaycompress' /tmp/logrotate.conf",
|
||||
"tail -n 1 /tmp/logrotate.conf | grep shred",
|
||||
"sed -ne '/\"sendmail\" {/,/}/p' /tmp/logrotate.conf | grep 'mail user@domain.tld'",
|
||||
"sed -ne '/\"postrotate\" {/,/}/p' /tmp/logrotate.conf | grep endscript",
|
||||
"grep '\"file1\"\n\"file2\" {' /tmp/logrotate.conf",
|
||||
"sed -ne '/\"import\" {/,/}/p' /tmp/logrotate.conf | grep noolddir",
|
||||
"sed -ne '1,/^\"/p' /tmp/logrotate.conf | grep nomail",
|
||||
"grep '\"compat_test_path\" {' /tmp/logrotate.conf",
|
||||
"sed -ne '/\"compat_user\" {/,/}/p' /tmp/logrotate.conf | grep 'su root root'",
|
||||
"sed -ne '/\"compat_extraConfig\" {/,/}/p' /tmp/logrotate.conf | grep dateext",
|
||||
"[[ $(sed -ne '/\"compat_keep\" {/,/}/p' /tmp/logrotate.conf | grep -w rotate) = \" rotate 1\" ]]",
|
||||
"! sed -ne '/\"compat_keep\" {/,/}/p' /tmp/logrotate.conf | grep -w keep",
|
||||
)
|
||||
# also check configFile option
|
||||
failingMachine.succeed(
|
||||
"conf=$(systemctl cat logrotate | grep -oE '/nix/store[^ ]*logrotate.conf'); cp $conf /tmp/logrotate.conf",
|
||||
"grep 'self-written config' /tmp/logrotate.conf",
|
||||
)
|
||||
with subtest("Check logrotate-checkconf service"):
|
||||
machine.wait_for_unit("logrotate-checkconf.service")
|
||||
# wait_for_unit also asserts for success, so wait for
|
||||
# parent target instead and check manually.
|
||||
failingMachine.wait_for_unit("multi-user.target")
|
||||
info = failingMachine.get_unit_info("logrotate-checkconf.service")
|
||||
if info["ActiveState"] != "failed":
|
||||
raise Exception('logrotate-checkconf.service was not failed')
|
||||
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
{ lib, stdenv, fetchFromGitHub, gzip, popt, autoreconfHook
|
||||
, mailutils ? null
|
||||
, aclSupport ? true, acl
|
||||
, nixosTests
|
||||
}:
|
||||
|
@ -19,8 +18,6 @@ stdenv.mkDerivation rec {
|
|||
configureFlags = [
|
||||
"--with-compress-command=${gzip}/bin/gzip"
|
||||
"--with-uncompress-command=${gzip}/bin/gunzip"
|
||||
] ++ lib.optionals (mailutils != null) [
|
||||
"--with-default-mail-command=${mailutils}/bin/mail"
|
||||
];
|
||||
|
||||
nativeBuildInputs = [ autoreconfHook ];
|
||||
|
|
Loading…
Reference in a new issue