From e3b90b6ccc4cf4147fd01df1ed8779b1c85744bd Mon Sep 17 00:00:00 2001 From: "Adrian Parvin D. Ouano" Date: Tue, 9 Mar 2021 23:04:58 +0800 Subject: [PATCH] nixos/systemd: Handle template overrides Adding template overrides allows for custom behavior for specific instances of a template. Previously, it was not possible to provide bind mounts for systemd-nspawn. This change allows it. --- nixos/modules/system/boot/systemd-lib.nix | 13 ++++++- nixos/tests/systemd-template-override.nix | 41 +++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 nixos/tests/systemd-template-override.nix diff --git a/nixos/modules/system/boot/systemd-lib.nix b/nixos/modules/system/boot/systemd-lib.nix index 2dbf15031a08..6051a4285749 100644 --- a/nixos/modules/system/boot/systemd-lib.nix +++ b/nixos/modules/system/boot/systemd-lib.nix @@ -182,7 +182,18 @@ in rec { # upstream unit. for i in ${toString (mapAttrsToList (n: v: v.unit) units)}; do fn=$(basename $i/*) - if [ -e $out/$fn ]; then + + case $fn in + # if file name is a template specialization, use the template's name + *@?*.service) + # remove @foo.service and replace it with @.service + ofn="''${fn%@*.service}@.service" + ;; + *) + ofn="$fn" + esac + + if [ -e $out/$ofn ]; then if [ "$(readlink -f $i/$fn)" = /dev/null ]; then ln -sfn /dev/null $out/$fn else diff --git a/nixos/tests/systemd-template-override.nix b/nixos/tests/systemd-template-override.nix new file mode 100644 index 000000000000..d8ef4a6c1c9b --- /dev/null +++ b/nixos/tests/systemd-template-override.nix @@ -0,0 +1,41 @@ +import ./make-test-python.nix { + name = "systemd-template-override"; + + machine = { pkgs, lib, ... }: let + touchTmp = pkgs.writeTextFile { + name = "touch-tmp@.service"; + text = '' + [Service] + Type=oneshot + ExecStart=${pkgs.coreutils}/bin/touch /tmp/%I + ''; + destination = "/etc/systemd/system/touch-tmp@.service"; + }; + in { + systemd.packages = [ touchTmp ]; + + systemd.services."touch-tmp@forbidden" = { + serviceConfig.ExecStart = [ "" '' + ${pkgs.coreutils}/bin/true + '']; + }; + + systemd.services."touch-tmp@intercept" = { + serviceConfig.ExecStart = [ "" '' + ${pkgs.coreutils}/bin/touch /tmp/renamed + '']; + }; + }; + + testScript = '' + machine.wait_for_unit("default.target") + + machine.succeed("systemctl start touch-tmp@normal") + machine.succeed("systemctl start touch-tmp@forbbidden") + machine.succeed("systemctl start touch-tmp@intercept") + + machine.succeed("[ -e /tmp/normal ]") + machine.succeed("[ ! -e /tmp/forbidden ]") + machine.succeed("[ -e /tmp/renamed ]") + ''; +}