Merge pull request #160458 from helsinki-systems/fix/stc-backslashes

nixos/switch-to-configuration: Fix backslashes in unit names
This commit is contained in:
Janne Heß 2022-02-17 19:08:02 +01:00 committed by GitHub
commit dcbacb0f62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 10 deletions

View file

@ -173,13 +173,18 @@ sub parseSystemdIni {
#
# If a directory with the same basename ending in .d exists next to the unit file, it will be
# assumed to contain override files which will be parsed as well and handled properly.
sub parseUnit {
my ($unitPath) = @_;
sub parse_unit {
my ($unit_path) = @_;
# Parse the main unit and all overrides
my %unitData;
parseSystemdIni(\%unitData, $_) for glob("${unitPath}{,.d/*.conf}");
return %unitData;
my %unit_data;
# Replace \ with \\ so glob() still works with units that have a \ in them
# Valid characters in unit names are ASCII letters, digits, ":", "-", "_", ".", and "\"
$unit_path =~ s/\\/\\\\/gmsx;
foreach (glob "${unit_path}{,.d/*.conf}") {
parseSystemdIni(\%unit_data, "$_")
}
return %unit_data;
}
# Checks whether a specified boolean in a systemd unit is true
@ -310,7 +315,7 @@ sub handleModifiedUnit {
# 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 = $newUnitInfo ? %{$newUnitInfo} : parseUnit($newUnitFile);
my %unitInfo = $newUnitInfo ? %{$newUnitInfo} : parse_unit($newUnitFile);
if (parseSystemdBool(\%unitInfo, "Service", "X-ReloadIfChanged", 0) and not $unitsToRestart->{$unit} and not $unitsToStop->{$unit}) {
$unitsToReload->{$unit} = 1;
recordUnit($reloadListFile, $unit);
@ -412,12 +417,12 @@ while (my ($unit, $state) = each %{$activePrev}) {
if (-e $prevUnitFile && ($state->{state} eq "active" || $state->{state} eq "activating")) {
if (! -e $newUnitFile || abs_path($newUnitFile) eq "/dev/null") {
my %unitInfo = parseUnit($prevUnitFile);
my %unitInfo = parse_unit($prevUnitFile);
$unitsToStop{$unit} = 1 if parseSystemdBool(\%unitInfo, "Unit", "X-StopOnRemoval", 1);
}
elsif ($unit =~ /\.target$/) {
my %unitInfo = parseUnit($newUnitFile);
my %unitInfo = parse_unit($newUnitFile);
# Cause all active target units to be restarted below.
# This should start most changed units we stop here as
@ -451,8 +456,8 @@ while (my ($unit, $state) = each %{$activePrev}) {
}
else {
my %old_unit_info = parseUnit($prevUnitFile);
my %new_unit_info = parseUnit($newUnitFile);
my %old_unit_info = parse_unit($prevUnitFile);
my %new_unit_info = parse_unit($newUnitFile);
my $diff = compare_units(\%old_unit_info, \%new_unit_info);
if ($diff eq 1) {
handleModifiedUnit($unit, $baseName, $newUnitFile, \%new_unit_info, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);

View file

@ -145,6 +145,23 @@ import ./make-test-python.nix ({ pkgs, ...} : {
systemd.services.test.serviceConfig."X-Test" = "test";
};
unitWithBackslash.configuration = {
systemd.services."escaped\\x2ddash" = {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${pkgs.coreutils}/bin/true";
ExecReload = "${pkgs.coreutils}/bin/true";
};
};
};
unitWithBackslashModified.configuration = {
imports = [ unitWithBackslash.configuration ];
systemd.services."escaped\\x2ddash".serviceConfig.X-Test = "test";
};
restart-and-reload-by-activation-script.configuration = {
systemd.services = rec {
simple-service = {
@ -433,6 +450,25 @@ import ./make-test-python.nix ({ pkgs, ...} : {
assert_lacks(out, "as well:")
assert_contains(out, "would start the following units: test.service\n")
# Ensure \ works in unit names
out = switch_to_specialisation("${machine}", "unitWithBackslash")
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_lacks(out, "\nstarting the following units:")
assert_contains(out, "the following new units were started: escaped\\x2ddash.service\n")
assert_lacks(out, "as well:")
out = switch_to_specialisation("${machine}", "unitWithBackslashModified")
assert_contains(out, "stopping the following units: escaped\\x2ddash.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: escaped\\x2ddash.service\n")
assert_lacks(out, "the following new units were started:")
assert_lacks(out, "as well:")
with subtest("failing units"):
# Let the simple service fail
switch_to_specialisation("${machine}", "simpleServiceModified")