Merge master into staging-next
This commit is contained in:
commit
420df1e082
|
@ -87,7 +87,32 @@
|
|||
</section>
|
||||
<section xml:id="sec-release-22.05-notable-changes">
|
||||
<title>Other Notable Changes</title>
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para>
|
||||
The option
|
||||
<link linkend="opt-services.redis.servers">services.redis.servers</link>
|
||||
was added to support per-application
|
||||
<literal>redis-server</literal> which is more secure since
|
||||
Redis databases are only mere key prefixes without any
|
||||
configuration or ACL of their own. Backward-compatibility is
|
||||
preserved by mapping old
|
||||
<literal>services.redis.settings</literal> to
|
||||
<literal>services.redis.servers."".settings</literal>,
|
||||
but you are strongly encouraged to name each
|
||||
<literal>redis-server</literal> instance after the application
|
||||
using it, instead of keeping that nameless one. Except for the
|
||||
nameless
|
||||
<literal>services.redis.servers.""</literal> still
|
||||
accessible at <literal>127.0.0.1:6379</literal>, and to the
|
||||
members of the Unix group <literal>redis</literal> through the
|
||||
Unix socket <literal>/run/redis/redis.sock</literal>, all
|
||||
other <literal>services.redis.servers.${serverName}</literal>
|
||||
are only accessible by default to the members of the Unix
|
||||
group <literal>redis-${serverName}</literal> through the Unix
|
||||
socket <literal>/run/redis-${serverName}/redis.sock</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -35,3 +35,19 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
Please switch to `claws-mail`, which is Claws Mail's latest release based on GTK+3 and Python 3.
|
||||
|
||||
## Other Notable Changes {#sec-release-22.05-notable-changes}
|
||||
|
||||
- The option [services.redis.servers](#opt-services.redis.servers) was added
|
||||
to support per-application `redis-server` which is more secure since Redis databases
|
||||
are only mere key prefixes without any configuration or ACL of their own.
|
||||
Backward-compatibility is preserved by mapping old `services.redis.settings`
|
||||
to `services.redis.servers."".settings`, but you are strongly encouraged
|
||||
to name each `redis-server` instance after the application using it,
|
||||
instead of keeping that nameless one.
|
||||
Except for the nameless `services.redis.servers.""`
|
||||
still accessible at `127.0.0.1:6379`,
|
||||
and to the members of the Unix group `redis`
|
||||
through the Unix socket `/run/redis/redis.sock`,
|
||||
all other `services.redis.servers.${serverName}`
|
||||
are only accessible by default
|
||||
to the members of the Unix group `redis-${serverName}`
|
||||
through the Unix socket `/run/redis-${serverName}/redis.sock`.
|
||||
|
|
|
@ -5,17 +5,18 @@ with lib;
|
|||
let
|
||||
cfg = config.services.redis;
|
||||
|
||||
ulimitNofile = cfg.maxclients + 32;
|
||||
|
||||
mkValueString = value:
|
||||
if value == true then "yes"
|
||||
else if value == false then "no"
|
||||
else generators.mkValueStringDefault { } value;
|
||||
|
||||
redisConfig = pkgs.writeText "redis.conf" (generators.toKeyValue {
|
||||
redisConfig = settings: pkgs.writeText "redis.conf" (generators.toKeyValue {
|
||||
listsAsDuplicateKeys = true;
|
||||
mkKeyValue = generators.mkKeyValueDefault { inherit mkValueString; } " ";
|
||||
} cfg.settings);
|
||||
} settings);
|
||||
|
||||
redisName = name: "redis" + optionalString (name != "") ("-"+name);
|
||||
enabledServers = filterAttrs (name: conf: conf.enable) config.services.redis.servers;
|
||||
|
||||
in {
|
||||
imports = [
|
||||
|
@ -24,7 +25,28 @@ in {
|
|||
(mkRemovedOptionModule [ "services" "redis" "dbFilename" ] "The redis module now uses /var/lib/redis/dump.rdb as database dump location.")
|
||||
(mkRemovedOptionModule [ "services" "redis" "appendOnlyFilename" ] "This option was never used.")
|
||||
(mkRemovedOptionModule [ "services" "redis" "pidFile" ] "This option was removed.")
|
||||
(mkRemovedOptionModule [ "services" "redis" "extraConfig" ] "Use services.redis.settings instead.")
|
||||
(mkRemovedOptionModule [ "services" "redis" "extraConfig" ] "Use services.redis.servers.*.settings instead.")
|
||||
(mkRenamedOptionModule [ "services" "redis" "enable"] [ "services" "redis" "servers" "" "enable" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "port"] [ "services" "redis" "servers" "" "port" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "openFirewall"] [ "services" "redis" "servers" "" "openFirewall" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "bind"] [ "services" "redis" "servers" "" "bind" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "unixSocket"] [ "services" "redis" "servers" "" "unixSocket" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "unixSocketPerm"] [ "services" "redis" "servers" "" "unixSocketPerm" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "logLevel"] [ "services" "redis" "servers" "" "logLevel" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "logfile"] [ "services" "redis" "servers" "" "logfile" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "syslog"] [ "services" "redis" "servers" "" "syslog" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "databases"] [ "services" "redis" "servers" "" "databases" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "maxclients"] [ "services" "redis" "servers" "" "maxclients" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "save"] [ "services" "redis" "servers" "" "save" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "slaveOf"] [ "services" "redis" "servers" "" "slaveOf" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "masterAuth"] [ "services" "redis" "servers" "" "masterAuth" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "requirePass"] [ "services" "redis" "servers" "" "requirePass" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "requirePassFile"] [ "services" "redis" "servers" "" "requirePassFile" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "appendOnly"] [ "services" "redis" "servers" "" "appendOnly" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "appendFsync"] [ "services" "redis" "servers" "" "appendFsync" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "slowLogLogSlowerThan"] [ "services" "redis" "servers" "" "slowLogLogSlowerThan" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "slowLogMaxLen"] [ "services" "redis" "servers" "" "slowLogMaxLen" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "settings"] [ "services" "redis" "servers" "" "settings" ])
|
||||
];
|
||||
|
||||
###### interface
|
||||
|
@ -32,18 +54,6 @@ in {
|
|||
options = {
|
||||
|
||||
services.redis = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable the Redis server. Note that the NixOS module for
|
||||
Redis disables kernel support for Transparent Huge Pages (THP),
|
||||
because this features causes major performance problems for Redis,
|
||||
e.g. (https://redis.io/topics/latency).
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.redis;
|
||||
|
@ -51,20 +61,36 @@ in {
|
|||
description = "Which Redis derivation to use.";
|
||||
};
|
||||
|
||||
vmOverCommit = mkEnableOption ''
|
||||
setting of vm.overcommit_memory to 1
|
||||
(Suggested for Background Saving: http://redis.io/topics/faq)
|
||||
'';
|
||||
|
||||
servers = mkOption {
|
||||
type = with types; attrsOf (submodule ({config, name, ...}@args: {
|
||||
options = {
|
||||
enable = mkEnableOption ''
|
||||
Redis server.
|
||||
|
||||
Note that the NixOS module for Redis disables kernel support
|
||||
for Transparent Huge Pages (THP),
|
||||
because this features causes major performance problems for Redis,
|
||||
e.g. (https://redis.io/topics/latency).
|
||||
'';
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = redisName name;
|
||||
defaultText = "\"redis\" or \"redis-\${name}\" if name != \"\"";
|
||||
description = "The username and groupname for redis-server.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 6379;
|
||||
description = "The port for Redis to listen to.";
|
||||
};
|
||||
|
||||
vmOverCommit = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Set vm.overcommit_memory to 1 (Suggested for Background Saving: http://redis.io/topics/faq)
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
|
@ -75,7 +101,8 @@ in {
|
|||
|
||||
bind = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = "127.0.0.1";
|
||||
default = if name == "" then "127.0.0.1" else null;
|
||||
defaultText = "127.0.0.1 or null if name != \"\"";
|
||||
description = ''
|
||||
The IP interface to bind to.
|
||||
<literal>null</literal> means "all interfaces".
|
||||
|
@ -85,16 +112,16 @@ in {
|
|||
|
||||
unixSocket = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
default = "/run/${redisName name}/redis.sock";
|
||||
defaultText = "\"/run/redis/redis.sock\" or \"/run/redis-\${name}/redis.sock\" if name != \"\"";
|
||||
description = "The path to the socket to bind to.";
|
||||
example = "/run/redis/redis.sock";
|
||||
};
|
||||
|
||||
unixSocketPerm = mkOption {
|
||||
type = types.int;
|
||||
default = 750;
|
||||
default = 660;
|
||||
description = "Change permissions for the socket";
|
||||
example = 700;
|
||||
example = 600;
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
|
@ -209,6 +236,7 @@ in {
|
|||
};
|
||||
|
||||
settings = mkOption {
|
||||
# TODO: this should be converted to freeformType
|
||||
type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
|
||||
default = {};
|
||||
description = ''
|
||||
|
@ -223,84 +251,99 @@ in {
|
|||
'';
|
||||
};
|
||||
};
|
||||
config.settings = mkMerge [
|
||||
{
|
||||
port = if config.bind == null then 0 else config.port;
|
||||
daemonize = false;
|
||||
supervised = "systemd";
|
||||
loglevel = config.logLevel;
|
||||
logfile = config.logfile;
|
||||
syslog-enabled = config.syslog;
|
||||
databases = config.databases;
|
||||
maxclients = config.maxclients;
|
||||
save = map (d: "${toString (builtins.elemAt d 0)} ${toString (builtins.elemAt d 1)}") config.save;
|
||||
dbfilename = "dump.rdb";
|
||||
dir = "/var/lib/${redisName name}";
|
||||
appendOnly = config.appendOnly;
|
||||
appendfsync = config.appendFsync;
|
||||
slowlog-log-slower-than = config.slowLogLogSlowerThan;
|
||||
slowlog-max-len = config.slowLogMaxLen;
|
||||
}
|
||||
(mkIf (config.bind != null) { bind = config.bind; })
|
||||
(mkIf (config.unixSocket != null) {
|
||||
unixsocket = config.unixSocket;
|
||||
unixsocketperm = toString config.unixSocketPerm;
|
||||
})
|
||||
(mkIf (config.slaveOf != null) { slaveof = "${config.slaveOf.ip} ${toString config.slaveOf.port}"; })
|
||||
(mkIf (config.masterAuth != null) { masterauth = config.masterAuth; })
|
||||
(mkIf (config.requirePass != null) { requirepass = config.requirePass; })
|
||||
];
|
||||
}));
|
||||
description = "Configuration of multiple <literal>redis-server</literal> instances.";
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf config.services.redis.enable {
|
||||
assertions = [{
|
||||
assertion = cfg.requirePass != null -> cfg.requirePassFile == null;
|
||||
message = "You can only set one services.redis.requirePass or services.redis.requirePassFile";
|
||||
}];
|
||||
boot.kernel.sysctl = (mkMerge [
|
||||
config = mkIf (enabledServers != {}) {
|
||||
|
||||
assertions = attrValues (mapAttrs (name: conf: {
|
||||
assertion = conf.requirePass != null -> conf.requirePassFile == null;
|
||||
message = ''
|
||||
You can only set one services.redis.servers.${name}.requirePass
|
||||
or services.redis.servers.${name}.requirePassFile
|
||||
'';
|
||||
}) enabledServers);
|
||||
|
||||
boot.kernel.sysctl = mkMerge [
|
||||
{ "vm.nr_hugepages" = "0"; }
|
||||
( mkIf cfg.vmOverCommit { "vm.overcommit_memory" = "1"; } )
|
||||
]);
|
||||
];
|
||||
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
};
|
||||
|
||||
users.users.redis = {
|
||||
description = "Redis database user";
|
||||
group = "redis";
|
||||
isSystemUser = true;
|
||||
};
|
||||
users.groups.redis = {};
|
||||
networking.firewall.allowedTCPPorts = concatMap (conf:
|
||||
optional conf.openFirewall conf.port
|
||||
) (attrValues enabledServers);
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
services.redis.settings = mkMerge [
|
||||
{
|
||||
port = cfg.port;
|
||||
daemonize = false;
|
||||
supervised = "systemd";
|
||||
loglevel = cfg.logLevel;
|
||||
logfile = cfg.logfile;
|
||||
syslog-enabled = cfg.syslog;
|
||||
databases = cfg.databases;
|
||||
maxclients = cfg.maxclients;
|
||||
save = map (d: "${toString (builtins.elemAt d 0)} ${toString (builtins.elemAt d 1)}") cfg.save;
|
||||
dbfilename = "dump.rdb";
|
||||
dir = "/var/lib/redis";
|
||||
appendOnly = cfg.appendOnly;
|
||||
appendfsync = cfg.appendFsync;
|
||||
slowlog-log-slower-than = cfg.slowLogLogSlowerThan;
|
||||
slowlog-max-len = cfg.slowLogMaxLen;
|
||||
}
|
||||
(mkIf (cfg.bind != null) { bind = cfg.bind; })
|
||||
(mkIf (cfg.unixSocket != null) { unixsocket = cfg.unixSocket; unixsocketperm = "${toString cfg.unixSocketPerm}"; })
|
||||
(mkIf (cfg.slaveOf != null) { slaveof = "${cfg.slaveOf.ip} ${toString cfg.slaveOf.port}"; })
|
||||
(mkIf (cfg.masterAuth != null) { masterauth = cfg.masterAuth; })
|
||||
(mkIf (cfg.requirePass != null) { requirepass = cfg.requirePass; })
|
||||
];
|
||||
users.users = mapAttrs' (name: conf: nameValuePair (redisName name) {
|
||||
description = "System user for the redis-server instance ${name}";
|
||||
isSystemUser = true;
|
||||
group = redisName name;
|
||||
}) enabledServers;
|
||||
users.groups = mapAttrs' (name: conf: nameValuePair (redisName name) {
|
||||
}) enabledServers;
|
||||
|
||||
systemd.services.redis = {
|
||||
description = "Redis Server";
|
||||
systemd.services = mapAttrs' (name: conf: nameValuePair (redisName name) {
|
||||
description = "Redis Server - ${redisName name}";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
preStart = ''
|
||||
install -m 600 ${redisConfig} /run/redis/redis.conf
|
||||
'' + optionalString (cfg.requirePassFile != null) ''
|
||||
password=$(cat ${escapeShellArg cfg.requirePassFile})
|
||||
echo "requirePass $password" >> /run/redis/redis.conf
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package}/bin/redis-server /run/redis/redis.conf";
|
||||
ExecStart = "${cfg.package}/bin/redis-server /run/${redisName name}/redis.conf";
|
||||
ExecStartPre = [("+"+pkgs.writeShellScript "${redisName name}-credentials" (''
|
||||
install -o '${conf.user}' -m 600 ${redisConfig conf.settings} /run/${redisName name}/redis.conf
|
||||
'' + optionalString (conf.requirePassFile != null) ''
|
||||
{
|
||||
printf requirePass' '
|
||||
cat ${escapeShellArg conf.requirePassFile}
|
||||
} >>/run/${redisName name}/redis.conf
|
||||
'')
|
||||
)];
|
||||
Type = "notify";
|
||||
# User and group
|
||||
User = "redis";
|
||||
Group = "redis";
|
||||
User = conf.user;
|
||||
Group = conf.user;
|
||||
# Runtime directory and mode
|
||||
RuntimeDirectory = "redis";
|
||||
RuntimeDirectory = redisName name;
|
||||
RuntimeDirectoryMode = "0750";
|
||||
# State directory and mode
|
||||
StateDirectory = "redis";
|
||||
StateDirectory = redisName name;
|
||||
StateDirectoryMode = "0700";
|
||||
# Access write directories
|
||||
UMask = "0077";
|
||||
|
@ -309,7 +352,7 @@ in {
|
|||
# Security
|
||||
NoNewPrivileges = true;
|
||||
# Process Properties
|
||||
LimitNOFILE = "${toString ulimitNofile}";
|
||||
LimitNOFILE = mkDefault "${toString (conf.maxclients + 32)}";
|
||||
# Sandboxing
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
|
@ -322,7 +365,9 @@ in {
|
|||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||
RestrictAddressFamilies =
|
||||
optionals (conf.bind != null) ["AF_INET" "AF_INET6"] ++
|
||||
optional (conf.unixSocket != null) "AF_UNIX";
|
||||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
|
@ -333,6 +378,7 @@ in {
|
|||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "~@cpu-emulation @debug @keyring @memlock @mount @obsolete @privileged @resources @setuid";
|
||||
};
|
||||
};
|
||||
}) enabledServers;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -146,6 +146,79 @@ sub fingerprintUnit {
|
|||
return abs_path($s) . (-f "${s}.d/overrides.conf" ? " " . abs_path "${s}.d/overrides.conf" : "");
|
||||
}
|
||||
|
||||
sub handleModifiedUnit {
|
||||
my ($unit, $baseName, $newUnitFile, $activePrev, $unitsToStop, $unitsToStart, $unitsToReload, $unitsToRestart, $unitsToSkip) = @_;
|
||||
|
||||
if ($unit eq "sysinit.target" || $unit eq "basic.target" || $unit eq "multi-user.target" || $unit eq "graphical.target" || $unit =~ /\.path$/ || $unit =~ /\.slice$/) {
|
||||
# Do nothing. These cannot be restarted directly.
|
||||
|
||||
# Slices and Paths don't have to be restarted since
|
||||
# properties (resource limits and inotify watches)
|
||||
# seem to get applied on daemon-reload.
|
||||
} elsif ($unit =~ /\.mount$/) {
|
||||
# Reload the changed mount unit to force a remount.
|
||||
$unitsToReload->{$unit} = 1;
|
||||
recordUnit($reloadListFile, $unit);
|
||||
} elsif ($unit =~ /\.socket$/) {
|
||||
# FIXME: do something?
|
||||
# Attempt to fix this: https://github.com/NixOS/nixpkgs/pull/141192
|
||||
# Revert of the attempt: https://github.com/NixOS/nixpkgs/pull/147609
|
||||
# More details: https://github.com/NixOS/nixpkgs/issues/74899#issuecomment-981142430
|
||||
} else {
|
||||
my $unitInfo = parseUnit($newUnitFile);
|
||||
if (boolIsTrue($unitInfo->{'X-ReloadIfChanged'} // "no")) {
|
||||
$unitsToReload->{$unit} = 1;
|
||||
recordUnit($reloadListFile, $unit);
|
||||
}
|
||||
elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
|
||||
$unitsToSkip->{$unit} = 1;
|
||||
} else {
|
||||
# It doesn't make sense to stop and start non-services because
|
||||
# they can't have ExecStop=
|
||||
if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes") || $unit !~ /\.service$/) {
|
||||
# This unit should be restarted instead of
|
||||
# stopped and started.
|
||||
$unitsToRestart->{$unit} = 1;
|
||||
recordUnit($restartListFile, $unit);
|
||||
} else {
|
||||
# If this unit is socket-activated, then stop the
|
||||
# socket unit(s) as well, and restart the
|
||||
# socket(s) instead of the service.
|
||||
my $socketActivated = 0;
|
||||
if ($unit =~ /\.service$/) {
|
||||
my @sockets = split / /, ($unitInfo->{Sockets} // "");
|
||||
if (scalar @sockets == 0) {
|
||||
@sockets = ("$baseName.socket");
|
||||
}
|
||||
foreach my $socket (@sockets) {
|
||||
if (defined $activePrev->{$socket}) {
|
||||
$unitsToStop->{$socket} = 1;
|
||||
# Only restart sockets that actually
|
||||
# exist in new configuration:
|
||||
if (-e "$out/etc/systemd/system/$socket") {
|
||||
$unitsToStart->{$socket} = 1;
|
||||
recordUnit($startListFile, $socket);
|
||||
$socketActivated = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# If the unit is not socket-activated, record
|
||||
# that this unit needs to be started below.
|
||||
# We write this to a file to ensure that the
|
||||
# service gets restarted if we're interrupted.
|
||||
if (!$socketActivated) {
|
||||
$unitsToStart->{$unit} = 1;
|
||||
recordUnit($startListFile, $unit);
|
||||
}
|
||||
|
||||
$unitsToStop->{$unit} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Figure out what units need to be stopped, started, restarted or reloaded.
|
||||
my (%unitsToStop, %unitsToSkip, %unitsToStart, %unitsToRestart, %unitsToReload);
|
||||
|
||||
|
@ -218,69 +291,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
|
|||
}
|
||||
|
||||
elsif (fingerprintUnit($prevUnitFile) ne fingerprintUnit($newUnitFile)) {
|
||||
if ($unit eq "sysinit.target" || $unit eq "basic.target" || $unit eq "multi-user.target" || $unit eq "graphical.target" || $unit =~ /\.path$/ || $unit =~ /\.slice$/) {
|
||||
# Do nothing. These cannot be restarted directly.
|
||||
|
||||
# Slices and Paths don't have to be restarted since
|
||||
# properties (resource limits and inotify watches)
|
||||
# seem to get applied on daemon-reload.
|
||||
} elsif ($unit =~ /\.mount$/) {
|
||||
# Reload the changed mount unit to force a remount.
|
||||
$unitsToReload{$unit} = 1;
|
||||
recordUnit($reloadListFile, $unit);
|
||||
} elsif ($unit =~ /\.socket$/) {
|
||||
# FIXME: do something?
|
||||
} else {
|
||||
my $unitInfo = parseUnit($newUnitFile);
|
||||
if (boolIsTrue($unitInfo->{'X-ReloadIfChanged'} // "no")) {
|
||||
$unitsToReload{$unit} = 1;
|
||||
recordUnit($reloadListFile, $unit);
|
||||
}
|
||||
elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
|
||||
$unitsToSkip{$unit} = 1;
|
||||
} else {
|
||||
if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes")) {
|
||||
# This unit should be restarted instead of
|
||||
# stopped and started.
|
||||
$unitsToRestart{$unit} = 1;
|
||||
recordUnit($restartListFile, $unit);
|
||||
} else {
|
||||
# If this unit is socket-activated, then stop the
|
||||
# socket unit(s) as well, and restart the
|
||||
# socket(s) instead of the service.
|
||||
my $socketActivated = 0;
|
||||
if ($unit =~ /\.service$/) {
|
||||
my @sockets = split / /, ($unitInfo->{Sockets} // "");
|
||||
if (scalar @sockets == 0) {
|
||||
@sockets = ("$baseName.socket");
|
||||
}
|
||||
foreach my $socket (@sockets) {
|
||||
if (defined $activePrev->{$socket}) {
|
||||
$unitsToStop{$socket} = 1;
|
||||
# Only restart sockets that actually
|
||||
# exist in new configuration:
|
||||
if (-e "$out/etc/systemd/system/$socket") {
|
||||
$unitsToStart{$socket} = 1;
|
||||
recordUnit($startListFile, $socket);
|
||||
$socketActivated = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# If the unit is not socket-activated, record
|
||||
# that this unit needs to be started below.
|
||||
# We write this to a file to ensure that the
|
||||
# service gets restarted if we're interrupted.
|
||||
if (!$socketActivated) {
|
||||
$unitsToStart{$unit} = 1;
|
||||
recordUnit($startListFile, $unit);
|
||||
}
|
||||
|
||||
$unitsToStop{$unit} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -939,7 +939,7 @@ let
|
|||
exporterConfig = {
|
||||
enable = true;
|
||||
};
|
||||
metricProvider.services.redis.enable = true;
|
||||
metricProvider.services.redis.servers."".enable = true;
|
||||
exporterTest = ''
|
||||
wait_for_unit("redis.service")
|
||||
wait_for_unit("prometheus-redis-exporter.service")
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import ./make-test-python.nix ({ pkgs, ... }:
|
||||
let
|
||||
redisSocket = "/run/redis/redis.sock";
|
||||
in
|
||||
{
|
||||
name = "redis";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
|
@ -10,35 +7,40 @@ in
|
|||
|
||||
nodes = {
|
||||
machine =
|
||||
{ pkgs, ... }:
|
||||
{ pkgs, lib, ... }: with lib;
|
||||
|
||||
{
|
||||
services.redis.enable = true;
|
||||
services.redis.unixSocket = redisSocket;
|
||||
services.redis.servers."".enable = true;
|
||||
services.redis.servers."test".enable = true;
|
||||
|
||||
# Allow access to the unix socket for the "redis" group.
|
||||
services.redis.unixSocketPerm = 770;
|
||||
|
||||
users.users."member" = {
|
||||
users.users = listToAttrs (map (suffix: nameValuePair "member${suffix}" {
|
||||
createHome = false;
|
||||
description = "A member of the redis group";
|
||||
description = "A member of the redis${suffix} group";
|
||||
isNormalUser = true;
|
||||
extraGroups = [
|
||||
"redis"
|
||||
];
|
||||
};
|
||||
extraGroups = [ "redis${suffix}" ];
|
||||
}) ["" "-test"]);
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
testScript = { nodes, ... }: let
|
||||
inherit (nodes.machine.config.services) redis;
|
||||
in ''
|
||||
start_all()
|
||||
machine.wait_for_unit("redis")
|
||||
machine.wait_for_unit("redis-test")
|
||||
|
||||
# The unnamed Redis server still opens a port for backward-compatibility
|
||||
machine.wait_for_open_port("6379")
|
||||
|
||||
machine.wait_for_file("${redis.servers."".unixSocket}")
|
||||
machine.wait_for_file("${redis.servers."test".unixSocket}")
|
||||
|
||||
# The unix socket is accessible to the redis group
|
||||
machine.succeed('su member -c "redis-cli ping | grep PONG"')
|
||||
machine.succeed('su member-test -c "redis-cli ping | grep PONG"')
|
||||
|
||||
machine.succeed("redis-cli ping | grep PONG")
|
||||
machine.succeed("redis-cli -s ${redisSocket} ping | grep PONG")
|
||||
machine.succeed("redis-cli -s ${redis.servers."".unixSocket} ping | grep PONG")
|
||||
machine.succeed("redis-cli -s ${redis.servers."test".unixSocket} ping | grep PONG")
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -3,21 +3,138 @@
|
|||
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||
name = "switch-test";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ gleber ];
|
||||
maintainers = [ gleber das_j ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
machine = { ... }: {
|
||||
machine = { pkgs, lib, ... }: {
|
||||
users.mutableUsers = false;
|
||||
|
||||
specialisation = rec {
|
||||
simpleService.configuration = {
|
||||
systemd.services.test = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = "${pkgs.coreutils}/bin/true";
|
||||
};
|
||||
other = { ... }: {
|
||||
};
|
||||
};
|
||||
|
||||
simpleServiceModified.configuration = {
|
||||
imports = [ simpleService.configuration ];
|
||||
systemd.services.test.serviceConfig.X-Test = true;
|
||||
};
|
||||
|
||||
simpleServiceNostop.configuration = {
|
||||
imports = [ simpleService.configuration ];
|
||||
systemd.services.test.stopIfChanged = false;
|
||||
};
|
||||
|
||||
simpleServiceReload.configuration = {
|
||||
imports = [ simpleService.configuration ];
|
||||
systemd.services.test = {
|
||||
reloadIfChanged = true;
|
||||
serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true";
|
||||
};
|
||||
};
|
||||
|
||||
simpleServiceNorestart.configuration = {
|
||||
imports = [ simpleService.configuration ];
|
||||
systemd.services.test.restartIfChanged = false;
|
||||
};
|
||||
|
||||
mount.configuration = {
|
||||
systemd.mounts = [
|
||||
{
|
||||
description = "Testmount";
|
||||
what = "tmpfs";
|
||||
type = "tmpfs";
|
||||
where = "/testmount";
|
||||
options = "size=1M";
|
||||
wantedBy = [ "local-fs.target" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
mountModified.configuration = {
|
||||
systemd.mounts = [
|
||||
{
|
||||
description = "Testmount";
|
||||
what = "tmpfs";
|
||||
type = "tmpfs";
|
||||
where = "/testmount";
|
||||
options = "size=10M";
|
||||
wantedBy = [ "local-fs.target" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
timer.configuration = {
|
||||
systemd.timers.test-timer = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig.OnCalendar = "@1395716396"; # chosen by fair dice roll
|
||||
};
|
||||
systemd.services.test-timer = {
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.coreutils}/bin/true";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
timerModified.configuration = {
|
||||
imports = [ timer.configuration ];
|
||||
systemd.timers.test-timer.timerConfig.OnCalendar = lib.mkForce "Fri 2012-11-23 16:00:00";
|
||||
};
|
||||
|
||||
path.configuration = {
|
||||
systemd.paths.test-watch = {
|
||||
wantedBy = [ "paths.target" ];
|
||||
pathConfig.PathExists = "/testpath";
|
||||
};
|
||||
systemd.services.test-watch = {
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.coreutils}/bin/touch /testpath-modified";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pathModified.configuration = {
|
||||
imports = [ path.configuration ];
|
||||
systemd.paths.test-watch.pathConfig.PathExists = lib.mkForce "/testpath2";
|
||||
};
|
||||
|
||||
slice.configuration = {
|
||||
systemd.slices.testslice.sliceConfig.MemoryMax = "1"; # don't allow memory allocation
|
||||
systemd.services.testservice = {
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = "${pkgs.coreutils}/bin/true";
|
||||
Slice = "testslice.slice";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sliceModified.configuration = {
|
||||
imports = [ slice.configuration ];
|
||||
systemd.slices.testslice.sliceConfig.MemoryMax = lib.mkForce null;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
other = {
|
||||
users.mutableUsers = true;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = {nodes, ...}: let
|
||||
testScript = { nodes, ... }: let
|
||||
originalSystem = nodes.machine.config.system.build.toplevel;
|
||||
otherSystem = nodes.other.config.system.build.toplevel;
|
||||
machine = nodes.machine.config.system.build.toplevel;
|
||||
|
||||
# Ensures failures pass through using pipefail, otherwise failing to
|
||||
# switch-to-configuration is hidden by the success of `tee`.
|
||||
|
@ -27,12 +144,186 @@ import ./make-test-python.nix ({ pkgs, ...} : {
|
|||
set -o pipefail
|
||||
exec env -i "$@" | tee /dev/stderr
|
||||
'';
|
||||
in ''
|
||||
in /* python */ ''
|
||||
def switch_to_specialisation(system, name, action="test"):
|
||||
if name == "":
|
||||
stc = f"{system}/bin/switch-to-configuration"
|
||||
else:
|
||||
stc = f"{system}/specialisation/{name}/bin/switch-to-configuration"
|
||||
out = machine.succeed(f"{stc} {action} 2>&1")
|
||||
assert_lacks(out, "switch-to-configuration line") # Perl warnings
|
||||
return out
|
||||
|
||||
def assert_contains(haystack, needle):
|
||||
if needle not in haystack:
|
||||
print("The haystack that will cause the following exception is:")
|
||||
print("---")
|
||||
print(haystack)
|
||||
print("---")
|
||||
raise Exception(f"Expected string '{needle}' was not found")
|
||||
|
||||
def assert_lacks(haystack, needle):
|
||||
if needle in haystack:
|
||||
print("The haystack that will cause the following exception is:")
|
||||
print("---")
|
||||
print(haystack, end="")
|
||||
print("---")
|
||||
raise Exception(f"Unexpected string '{needle}' was found")
|
||||
|
||||
|
||||
machine.succeed(
|
||||
"${stderrRunner} ${originalSystem}/bin/switch-to-configuration test"
|
||||
)
|
||||
machine.succeed(
|
||||
"${stderrRunner} ${otherSystem}/bin/switch-to-configuration test"
|
||||
)
|
||||
|
||||
with subtest("services"):
|
||||
switch_to_specialisation("${machine}", "")
|
||||
# Nothing happens when nothing is changed
|
||||
out = switch_to_specialisation("${machine}", "")
|
||||
assert_lacks(out, "stopping the following units:")
|
||||
assert_lacks(out, "NOT restarting the following changed units:")
|
||||
assert_lacks(out, "reloading the following units:")
|
||||
assert_lacks(out, "\nrestarting the following units:")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_lacks(out, "the following new units were started:")
|
||||
assert_lacks(out, "as well:")
|
||||
|
||||
# Start a simple service
|
||||
out = switch_to_specialisation("${machine}", "simpleService")
|
||||
assert_lacks(out, "stopping the following units:")
|
||||
assert_lacks(out, "NOT restarting the following changed units:")
|
||||
assert_contains(out, "reloading the following units: dbus.service\n") # huh
|
||||
assert_lacks(out, "\nrestarting the following units:")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_contains(out, "the following new units were started: test.service\n")
|
||||
assert_lacks(out, "as well:")
|
||||
|
||||
# Not changing anything doesn't do anything
|
||||
out = switch_to_specialisation("${machine}", "simpleService")
|
||||
assert_lacks(out, "stopping the following units:")
|
||||
assert_lacks(out, "NOT restarting the following changed units:")
|
||||
assert_lacks(out, "reloading the following units:")
|
||||
assert_lacks(out, "\nrestarting the following units:")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_lacks(out, "the following new units were started:")
|
||||
assert_lacks(out, "as well:")
|
||||
|
||||
# Restart the simple service
|
||||
out = switch_to_specialisation("${machine}", "simpleServiceModified")
|
||||
assert_contains(out, "stopping the following units: test.service\n")
|
||||
assert_lacks(out, "NOT restarting the following changed units:")
|
||||
assert_lacks(out, "reloading the following units:")
|
||||
assert_lacks(out, "\nrestarting the following units:")
|
||||
assert_contains(out, "\nstarting the following units: test.service\n")
|
||||
assert_lacks(out, "the following new units were started:")
|
||||
assert_lacks(out, "as well:")
|
||||
|
||||
# Restart the service with stopIfChanged=false
|
||||
out = switch_to_specialisation("${machine}", "simpleServiceNostop")
|
||||
assert_lacks(out, "stopping the following units:")
|
||||
assert_lacks(out, "NOT restarting the following changed units:")
|
||||
assert_lacks(out, "reloading the following units:")
|
||||
assert_contains(out, "\nrestarting the following units: test.service\n")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_lacks(out, "the following new units were started:")
|
||||
assert_lacks(out, "as well:")
|
||||
|
||||
# Reload the service with reloadIfChanged=true
|
||||
out = switch_to_specialisation("${machine}", "simpleServiceReload")
|
||||
assert_lacks(out, "stopping the following units:")
|
||||
assert_lacks(out, "NOT restarting the following changed units:")
|
||||
assert_contains(out, "reloading the following units: test.service\n")
|
||||
assert_lacks(out, "\nrestarting the following units:")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_lacks(out, "the following new units were started:")
|
||||
assert_lacks(out, "as well:")
|
||||
|
||||
# Nothing happens when restartIfChanged=false
|
||||
out = switch_to_specialisation("${machine}", "simpleServiceNorestart")
|
||||
assert_lacks(out, "stopping the following units:")
|
||||
assert_contains(out, "NOT restarting the following changed units: test.service\n")
|
||||
assert_lacks(out, "reloading the following units:")
|
||||
assert_lacks(out, "\nrestarting the following units:")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_lacks(out, "the following new units were started:")
|
||||
assert_lacks(out, "as well:")
|
||||
|
||||
# Dry mode shows different messages
|
||||
out = switch_to_specialisation("${machine}", "simpleService", action="dry-activate")
|
||||
assert_lacks(out, "stopping the following units:")
|
||||
assert_lacks(out, "NOT restarting the following changed units:")
|
||||
assert_lacks(out, "reloading the following units:")
|
||||
assert_lacks(out, "\nrestarting the following units:")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_lacks(out, "the following new units were started:")
|
||||
assert_lacks(out, "as well:")
|
||||
assert_contains(out, "would start the following units: test.service\n")
|
||||
|
||||
with subtest("mounts"):
|
||||
switch_to_specialisation("${machine}", "mount")
|
||||
out = machine.succeed("mount | grep 'on /testmount'")
|
||||
assert_contains(out, "size=1024k")
|
||||
out = switch_to_specialisation("${machine}", "mountModified")
|
||||
assert_lacks(out, "stopping the following units:")
|
||||
assert_lacks(out, "NOT restarting the following changed units:")
|
||||
assert_contains(out, "reloading the following units: testmount.mount\n")
|
||||
assert_lacks(out, "\nrestarting the following units:")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_lacks(out, "the following new units were started:")
|
||||
assert_lacks(out, "as well:")
|
||||
# It changed
|
||||
out = machine.succeed("mount | grep 'on /testmount'")
|
||||
assert_contains(out, "size=10240k")
|
||||
|
||||
with subtest("timers"):
|
||||
switch_to_specialisation("${machine}", "timer")
|
||||
out = machine.succeed("systemctl show test-timer.timer")
|
||||
assert_contains(out, "OnCalendar=2014-03-25 02:59:56 UTC")
|
||||
out = switch_to_specialisation("${machine}", "timerModified")
|
||||
assert_lacks(out, "stopping the following units:")
|
||||
assert_lacks(out, "reloading the following units:")
|
||||
assert_contains(out, "restarting the following units: test-timer.timer\n")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_lacks(out, "the following new units were started:")
|
||||
assert_lacks(out, "as well:")
|
||||
# It changed
|
||||
out = machine.succeed("systemctl show test-timer.timer")
|
||||
assert_contains(out, "OnCalendar=Fri 2012-11-23 16:00:00")
|
||||
|
||||
with subtest("paths"):
|
||||
out = switch_to_specialisation("${machine}", "path")
|
||||
assert_contains(out, "stopping the following units: test-timer.timer\n")
|
||||
assert_lacks(out, "NOT restarting the following changed units:")
|
||||
assert_lacks(out, "reloading the following units:")
|
||||
assert_lacks(out, "\nrestarting the following units:")
|
||||
assert_lacks(out, "\nstarting the following units:")
|
||||
assert_contains(out, "the following new units were started: test-watch.path")
|
||||
assert_lacks(out, "as well:")
|
||||
machine.fail("test -f /testpath-modified")
|
||||
|
||||
# touch the file, unit should be triggered
|
||||
machine.succeed("touch /testpath")
|
||||
machine.wait_until_succeeds("test -f /testpath-modified")
|
||||
machine.succeed("rm /testpath /testpath-modified")
|
||||
switch_to_specialisation("${machine}", "pathModified")
|
||||
machine.succeed("touch /testpath")
|
||||
machine.fail("test -f /testpath-modified")
|
||||
machine.succeed("touch /testpath2")
|
||||
machine.wait_until_succeeds("test -f /testpath-modified")
|
||||
|
||||
# This test ensures that changes to slice configuration get applied.
|
||||
# We test this by having a slice that allows no memory allocation at
|
||||
# all and starting a service within it. If the service crashes, the slice
|
||||
# is applied and if we modify the slice to allow memory allocation, the
|
||||
# service should successfully start.
|
||||
with subtest("slices"):
|
||||
machine.succeed("echo 0 > /proc/sys/vm/panic_on_oom") # allow OOMing
|
||||
out = switch_to_specialisation("${machine}", "slice")
|
||||
machine.fail("systemctl start testservice.service")
|
||||
out = switch_to_specialisation("${machine}", "sliceModified")
|
||||
machine.succeed("systemctl start testservice.service")
|
||||
machine.succeed("echo 1 > /proc/sys/vm/panic_on_oom") # disallow OOMing
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -10,17 +10,19 @@ import ./make-test-python.nix ({ pkgs, ... }:
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
services.redis.enable = true;
|
||||
services.redis.unixSocket = "/run/redis/redis.sock";
|
||||
services.redis.servers."".enable = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [ (python38.withPackages (ps: [ ps.twisted ps.txredisapi ps.mock ]))];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
testScript = { nodes, ... }: let
|
||||
inherit (nodes.machine.config.services) redis;
|
||||
in ''
|
||||
start_all()
|
||||
machine.wait_for_unit("redis")
|
||||
machine.wait_for_open_port("6379")
|
||||
machine.wait_for_file("${redis.servers."".unixSocket}")
|
||||
machine.succeed("ln -s ${redis.servers."".unixSocket} /tmp/redis.sock")
|
||||
|
||||
tests = machine.succeed("PYTHONPATH=\"${pkgs.python3Packages.txredisapi.src}\" python -m twisted.trial ${pkgs.python3Packages.txredisapi.src}/tests")
|
||||
'';
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
, Xaw3d, libXcursor, pkg-config, gettext, libXft, dbus, libpng, libjpeg, giflib
|
||||
, libtiff, librsvg, gconf, libxml2, imagemagick, gnutls, libselinux
|
||||
, alsa-lib, cairo, acl, gpm, AppKit, GSS, ImageIO, m17n_lib, libotf
|
||||
, sigtool, jansson, harfbuzz
|
||||
, sigtool, jansson, harfbuzz, sqlite
|
||||
, dontRecurseIntoAttrs ,emacsPackagesFor
|
||||
, libgccjit, targetPlatform, makeWrapper # native-comp params
|
||||
, systemd ? null
|
||||
|
@ -20,6 +20,7 @@
|
|||
, withGTK3 ? true, gtk3-x11 ? null, gsettings-desktop-schemas ? null
|
||||
, withXwidgets ? false, webkitgtk ? null, wrapGAppsHook ? null, glib-networking ? null
|
||||
, withMotif ? false, motif ? null
|
||||
, withSQLite3 ? false
|
||||
, withCsrc ? true
|
||||
, srcRepo ? false, autoreconfHook ? null, texinfo ? null
|
||||
, siteStart ? ./site-start.el
|
||||
|
@ -116,6 +117,7 @@ let emacs = stdenv.mkDerivation (lib.optionalAttrs nativeComp {
|
|||
++ lib.optional (withX && withGTK2) gtk2-x11
|
||||
++ lib.optionals (withX && withGTK3) [ gtk3-x11 gsettings-desktop-schemas ]
|
||||
++ lib.optional (withX && withMotif) motif
|
||||
++ lib.optional withSQLite3 sqlite
|
||||
++ lib.optionals (withX && withXwidgets) [ webkitgtk glib-networking ]
|
||||
++ lib.optionals withNS [ AppKit GSS ImageIO ]
|
||||
++ lib.optionals stdenv.isDarwin [ sigtool ]
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
mkDerivation rec {
|
||||
pname = "latte-dock";
|
||||
version = "0.10.0";
|
||||
version = "0.10.4";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://download.kde.org/stable/${pname}/${pname}-${version}.tar.xz";
|
||||
sha256 = "04kq86qmrjbzidrkknj000pv1b5z0r7nfidhy2zv67ks8fdi4zln";
|
||||
sha256 = "XRop+MNcbeCcbnL2LM1i67QvMudW3CjWYEPLkT/qbGM=";
|
||||
name = "${pname}-${version}.tar.xz";
|
||||
};
|
||||
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
buildGoModule rec {
|
||||
pname = "kubelogin";
|
||||
version = "1.23.3";
|
||||
version = "1.25.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "int128";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-qhdt/j1yFlCr+CCM3VQHxRVMEelZDsjhDJW9CYNCx2U=";
|
||||
sha256 = "sha256-orclZtmkdplTRvYkN7VotbynSQ9L2kvAPqP20j8QJ2s=";
|
||||
};
|
||||
|
||||
subPackages = ["."];
|
||||
|
||||
vendorSha256 = "sha256-RxIrnwIHDi9umu9bqpz3lnpNFdIWoTP657Te9iBv4IA=";
|
||||
vendorSha256 = "sha256-i46G0lsRvh/PmM+pMYuAjoLMHWF1Uzbd8+EkjIId8KE=";
|
||||
|
||||
# Rename the binary instead of symlinking to avoid conflict with the
|
||||
# Azure version of kubelogin
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
, qtkeychain
|
||||
, qtmacextras
|
||||
, qtmultimedia
|
||||
, qtimageformats
|
||||
, qttools
|
||||
, qtquickcontrols2
|
||||
, qtgraphicaleffects
|
||||
|
@ -57,6 +58,7 @@ mkDerivation rec {
|
|||
cmark
|
||||
qtbase
|
||||
qtmultimedia
|
||||
qtimageformats
|
||||
qttools
|
||||
qtquickcontrols2
|
||||
qtgraphicaleffects
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"version": "1.9.0-sc.1",
|
||||
"srcHash": "10swz5gwz1izryzllmjm8mhhd0vqk2cp8qjcmmr5gbzspj7p3xgw",
|
||||
"webYarnHash": "134llyh0197andpnbmfcxnidcgi3xxnb9v10bwfvrqysgnhb5z8v",
|
||||
"desktopYarnHash": "150jc6p9kbdz599bdkinrhbhncpamhz35j6rcc008qxg2d9qfhwr"
|
||||
"version": "1.9.7-sc.1",
|
||||
"srcHash": "0qrjjwcxa141phsgdz325rrkfmjqdmxc3h917cs9c9kf6cblkxaq",
|
||||
"webYarnHash": "19c594pql2yz1z15phfdlkwcvrcbm8k058fcq7p0k6840dhif5fd",
|
||||
"desktopYarnHash": "058ihkljb1swjzvgf8gqci5ghvwapmpcf2bsab3yr66lhps7fhci"
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
}:
|
||||
|
||||
let
|
||||
version = "1.10.2";
|
||||
version = "1.10.3";
|
||||
|
||||
# build stimuli file for PGO build and the script to generate it
|
||||
# independently of the foot's build, so we can cache the result
|
||||
|
@ -99,7 +99,7 @@ stdenv.mkDerivation rec {
|
|||
owner = "dnkl";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "00096c2m8pn4gpafvmg9lhyprwgnsis62bq4qmagnbb49bj5kr9v";
|
||||
sha256 = "13v6xqaw3xn1x84dn4gnkiimcsllb19mrbvcdj2fnm8klnrys3gs";
|
||||
};
|
||||
|
||||
depsBuildBuild = [
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "bctoolbox";
|
||||
version = "5.0.0";
|
||||
version = "5.0.55";
|
||||
|
||||
nativeBuildInputs = [ cmake bcunit ];
|
||||
buildInputs = [ mbedtls ];
|
||||
|
@ -18,7 +18,7 @@ stdenv.mkDerivation rec {
|
|||
group = "BC";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "sha256-/jv59ZeELfP7PokzthvZNL4FS3tyzRmCHp4I/Lp8BJM=";
|
||||
sha256 = "sha256-fZ+8XBTZ6/wNd8odzg20dAXtbjRudI6Nw0hKC9bopGo=";
|
||||
};
|
||||
|
||||
# Do not build static libraries
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "olm";
|
||||
version = "3.2.6";
|
||||
version = "3.2.8";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
domain = "gitlab.matrix.org";
|
||||
owner = "matrix-org";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "1srmw36nxi0z2y5d9adks09p950qm0fscbnrq1fl37fdypvjl1sk";
|
||||
sha256 = "1jfhydfcnqpksb2bhi960v3h10prf4v5gx42mm2rp6p0jfbqcy50";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cmake ];
|
||||
|
|
28
pkgs/development/python-modules/asyncio-rlock/default.nix
Normal file
28
pkgs/development/python-modules/asyncio-rlock/default.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{ lib
|
||||
, buildPythonPackage
|
||||
, fetchPypi
|
||||
, pytestCheckHook
|
||||
}:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "asyncio-rlock";
|
||||
version = "0.1.0";
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "asyncio_rlock";
|
||||
inherit version;
|
||||
sha256 = "7e29824331619873e10d5d99dcc46d7b8f196c4a11b203f4eeccc0c091039d43";
|
||||
};
|
||||
|
||||
# no tests on PyPI, no tags on GitLab
|
||||
doCheck = false;
|
||||
|
||||
pythonImportsCheck = [ "asyncio_rlock" ];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Rlock like in threading module but for asyncio";
|
||||
homepage = "https://gitlab.com/heckad/asyncio_rlock";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ dotlambda ];
|
||||
};
|
||||
}
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
buildPythonPackage rec {
|
||||
pname = "fastecdsa";
|
||||
version = "2.2.2";
|
||||
version = "2.2.3";
|
||||
format = "setuptools";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "1eb6f3ac86ec483a10df62fcda1fb9a9d5d895a436871a8aa935dd20ccd82c6f";
|
||||
sha256 = "269bdb0f618b38f8f6aec9d23d23db518046c3cee01a954fa6aa7322a1a7db8f";
|
||||
};
|
||||
|
||||
buildInputs = [ gmp ];
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
, fetchFromGitHub
|
||||
, pythonOlder
|
||||
, anyio
|
||||
, asyncio-rlock
|
||||
, asyncio-throttle
|
||||
, dataclasses
|
||||
, ircstates
|
||||
|
@ -13,23 +14,26 @@
|
|||
|
||||
buildPythonPackage rec {
|
||||
pname = "ircrobots";
|
||||
version = "0.3.8";
|
||||
version = "0.4.6";
|
||||
disabled = pythonOlder "3.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jesopo";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "06q86dqllxvi3nssfplmjk9yxaybighwh87lrxfpfhl8yy4z68jz";
|
||||
sha256 = "sha256-+BrS1+ZkgwT/qvqD0PwRZi2LF+31biS738SzKH1dy7w=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
# too specific pins https://github.com/jesopo/ircrobots/issues/3
|
||||
sed -iE 's/anyio.*/anyio/' requirements.txt
|
||||
sed -iE 's/ircstates.*/ircstates/' requirements.txt
|
||||
sed -iE 's/async_timeout.*/async_timeout/' requirements.txt
|
||||
'';
|
||||
|
||||
propagatedBuildInputs = [
|
||||
anyio
|
||||
asyncio-rlock
|
||||
asyncio-throttle
|
||||
ircstates
|
||||
async_stagger
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
|
||||
buildPythonPackage rec {
|
||||
pname = "lsassy";
|
||||
version = "3.1.0";
|
||||
version = "3.1.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Hackndo";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "0xycpyzjbzr7836hjzcbmf7sri0r2az65yc6yrgy6kay0v75j4p6";
|
||||
sha256 = "0jd0kmp0mc8jn5qmgrspdx05vy6nyq773cj4yid1qyr8dmyx6a7n";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
buildPythonPackage rec {
|
||||
pname = "youtube-transcript-api";
|
||||
version = "0.4.2";
|
||||
version = "0.4.3";
|
||||
|
||||
# PyPI tarball is missing some test files
|
||||
src = fetchFromGitHub {
|
||||
owner = "jdepoix";
|
||||
repo = "youtube-transcript-api";
|
||||
rev = "v${version}";
|
||||
sha256 = "04x7mfp4q17w3n8dnklbxblz22496g7g4879nz0wzgijg3m6cwlp";
|
||||
sha256 = "1krak5j2faj6951cl13h7hg9i3kyp6nslcbi608k8hxlbd80hc5h";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ requests ];
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
# compilers to determine the desired target.
|
||||
, defaultTargets ? []}:
|
||||
stdenv.mkDerivation rec {
|
||||
version = "4.3.1";
|
||||
version = "4.5.2";
|
||||
pname = "rocminfo";
|
||||
src = fetchFromGitHub {
|
||||
owner = "RadeonOpenCompute";
|
||||
repo = "rocminfo";
|
||||
rev = "rocm-${version}";
|
||||
sha256 = "sha256-n80tiSVaPTFl4imZvoFENM4KhPLxgDKz5VlOvhEYlV0=";
|
||||
sha256 = "sha256-VIlHYiGLen4xmdP7kpmObj5wKy6Qq7iupJFtPa4Zd98=";
|
||||
};
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
{ stdenv
|
||||
, lib
|
||||
, nixosTests
|
||||
, fetchFromGitHub
|
||||
, fetchpatch
|
||||
, fetchzip
|
||||
|
@ -616,6 +617,10 @@ stdenv.mkDerivation {
|
|||
# runtime; otherwise we can't and we need to reboot.
|
||||
passthru.interfaceVersion = 2;
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests) switchTest;
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://www.freedesktop.org/wiki/Software/systemd/";
|
||||
description = "A system and service manager for Linux";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ lib, stdenv, fetchurl, pkg-config, libseccomp, util-linux, qemu }:
|
||||
|
||||
let
|
||||
version = "0.6.8";
|
||||
version = "0.6.9";
|
||||
# list of all theoretically available targets
|
||||
targets = [
|
||||
"genode"
|
||||
|
@ -19,9 +19,8 @@ in stdenv.mkDerivation {
|
|||
buildInputs = lib.optional (stdenv.hostPlatform.isLinux) libseccomp;
|
||||
|
||||
src = fetchurl {
|
||||
url =
|
||||
"https://github.com/Solo5/solo5/releases/download/v${version}/solo5-v${version}.tar.gz";
|
||||
sha256 = "sha256-zrxNCXJIuEbtE3YNRK8Bxu2koHsQkcF+xItoIyhj9Uc=";
|
||||
url = "https://github.com/Solo5/solo5/releases/download/v${version}/solo5-v${version}.tar.gz";
|
||||
sha256 = "03lvk9mab3yxrmi73wrvvhykqcydjrsda0wj6aasnjm5lx9jycpr";
|
||||
};
|
||||
|
||||
hardeningEnable = [ "pie" ];
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
, git, nix, nixfmt, jq, coreutils, gnused, curl, cacert }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
version = "2021-12-07";
|
||||
version = "2021-12-13";
|
||||
pname = "oh-my-zsh";
|
||||
rev = "5b987e59d0fce1a74bcfd51750c6f52d7c29c647";
|
||||
rev = "9a3d853481645ae0f961e9cc8421fc5d84e2c3c3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
inherit rev;
|
||||
owner = "ohmyzsh";
|
||||
repo = "ohmyzsh";
|
||||
sha256 = "JNAuWsD03F8fbhHwwDnDh+2pPjJsyFnT/oboZIhk3rc=";
|
||||
sha256 = "TFktV7xBm3KaRfW+cUGdwIZZD7TfU0gaq4J8cKBjtMM=";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "graylog";
|
||||
version = "3.3.14";
|
||||
version = "3.3.15";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://packages.graylog2.org/releases/graylog/graylog-${version}.tgz";
|
||||
sha256 = "04dslbvgrraacsw7wydbiv8jc753as2g54wn9sgh3lsryvzrfqfa";
|
||||
sha256 = "sha256-/ECHhgLhmLoZ9fjpwGQrGuOW5PBtkB3JUCC9Bgvxr30=";
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
|
|
|
@ -1,31 +1,40 @@
|
|||
{ lib, fetchFromGitHub, python3 }:
|
||||
{ lib
|
||||
, fetchFromGitHub
|
||||
, python3
|
||||
}:
|
||||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "fierce";
|
||||
version = "1.4.0";
|
||||
version = "1.5.0";
|
||||
format = "setuptools";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "mschwager";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "11yaz8ap9swx95j3wpqh0b6jhw6spqgfnsyn1liw9zqi4jwgiax7";
|
||||
sha256 = "sha256-9VTPD5i203BTl2nADjq131W9elgnaHNIWGIUuCiYlHg=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
substituteInPlace requirements.txt --replace 'dnspython==1.16.0' 'dnspython'
|
||||
'';
|
||||
propagatedBuildInputs = with python3.pkgs; [
|
||||
dnspython
|
||||
];
|
||||
|
||||
propagatedBuildInputs = [ python3.pkgs.dnspython ];
|
||||
postPatch = ''
|
||||
substituteInPlace requirements.txt \
|
||||
--replace 'dnspython==1.16.0' 'dnspython'
|
||||
'';
|
||||
|
||||
# tests require network access
|
||||
doCheck = false;
|
||||
pythonImportsCheck = [ "fierce" ];
|
||||
|
||||
pythonImportsCheck = [
|
||||
"fierce"
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/mschwager/fierce";
|
||||
description = "DNS reconnaissance tool for locating non-contiguous IP space";
|
||||
homepage = "https://github.com/mschwager/fierce";
|
||||
license = licenses.gpl3Plus;
|
||||
maintainers = with maintainers; [ c0bw3b ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -676,6 +676,8 @@ in {
|
|||
|
||||
asyncio-nats-client = callPackage ../development/python-modules/asyncio-nats-client { };
|
||||
|
||||
asyncio-rlock = callPackage ../development/python-modules/asyncio-rlock { };
|
||||
|
||||
asyncmy = callPackage ../development/python-modules/asyncmy { };
|
||||
|
||||
asyncio-throttle = callPackage ../development/python-modules/asyncio-throttle { };
|
||||
|
|
Loading…
Reference in a new issue