#!/usr/bin/env bash # SPDX-License-Identifier: LGPL-2.1-or-later set -eux set -o pipefail clear_unit () { local UNIT_NAME="${1:?}" systemctl stop "$UNIT_NAME" 2>/dev/null || : rm -f /{etc,run,usr/lib}/systemd/system/"$UNIT_NAME" rm -fr /{etc,run,usr/lib}/systemd/system/"$UNIT_NAME".d rm -fr /{etc,run,usr/lib}/systemd/system/"$UNIT_NAME".{wants,requires} if [[ $UNIT_NAME == *@ ]]; then local base="${UNIT_NAME%@*}" local suffix="${UNIT_NAME##*.}" systemctl stop "$base@"*."$suffix" 2>/dev/null || : rm -f /{etc,run,usr/lib}/systemd/system/"$base@"*."$suffix" rm -fr /{etc,run,usr/lib}/systemd/system/"$base@"*."$suffix".d rm -fr /{etc,run,usr/lib}/systemd/system/"$base@"*."$suffix".{wants,requires} fi } clear_units () { for u in "$@"; do clear_unit "$u" done systemctl daemon-reload } create_service () { local SERVICE_NAME="${1:?}" clear_units "${SERVICE_NAME}".service cat >/etc/systemd/system/"$SERVICE_NAME".service </usr/lib/systemd/system/service.d/override.conf </usr/lib/systemd/system/$dropin/override.conf systemctl daemon-reload check_ok a-b-c ExecCondition "echo $dropin" # Check that we can start a transient service in presence of the drop-ins systemd-run -u a-b-c2.service -p Description='sleepy' sleep infinity # The transient setting replaces the default check_ok a-b-c2.service Description "sleepy" # The override takes precedence for ExecCondition # (except the last iteration when it only applies to the other service) if [ "$dropin" != "a-b-c.service.d" ]; then check_ok a-b-c2.service ExecCondition "echo $dropin" fi # Check that things are the same after a reload systemctl daemon-reload check_ok a-b-c2.service Description "sleepy" if [ "$dropin" != "a-b-c.service.d" ]; then check_ok a-b-c2.service ExecCondition "echo $dropin" fi systemctl stop a-b-c2.service done for dropin in service.d a-.service.d a-b-.service.d a-b-c.service.d; do rm -rf /usr/lib/systemd/system/$dropin done clear_units a-b-c.service } test_hierarchical_slice_dropins () { echo "Testing hierarchical slice dropins..." echo "*** test slice.d/ top level drop-in" # Slice units don't even need a fragment, so we test the defaults here check_ok a-b-c.slice Description "Slice /a/b/c" check_ok a-b-c.slice MemoryMax "infinity" # Test drop-ins for dropin in slice.d a-.slice.d a-b-.slice.d a-b-c.slice.d; do mkdir -p /usr/lib/systemd/system/$dropin echo " [Slice] MemoryMax=1000000000 " >/usr/lib/systemd/system/$dropin/override.conf systemctl daemon-reload check_ok a-b-c.slice MemoryMax "1000000000" busctl call \ org.freedesktop.systemd1 \ /org/freedesktop/systemd1 \ org.freedesktop.systemd1.Manager \ StartTransientUnit 'ssa(sv)a(sa(sv))' \ 'a-b-c.slice' 'replace' \ 2 \ 'Description' s 'slice too' \ 'MemoryMax' t 1000000002 \ 0 # The override takes precedence for MemoryMax check_ok a-b-c.slice MemoryMax "1000000000" # The transient setting replaces the default check_ok a-b-c.slice Description "slice too" # Check that things are the same after a reload systemctl daemon-reload check_ok a-b-c.slice MemoryMax "1000000000" check_ok a-b-c.slice Description "slice too" busctl call \ org.freedesktop.systemd1 \ /org/freedesktop/systemd1 \ org.freedesktop.systemd1.Manager \ StopUnit 'ss' \ 'a-b-c.slice' 'replace' rm /usr/lib/systemd/system/$dropin/override.conf done # Test unit with a fragment echo " [Slice] MemoryMax=1000000001 " >/usr/lib/systemd/system/a-b-c.slice systemctl daemon-reload check_ok a-b-c.slice MemoryMax "1000000001" clear_units a-b-c.slice } test_transient_service_dropins () { echo "Testing dropins for a transient service..." echo "*** test transient service drop-ins" mkdir -p /etc/systemd/system/service.d mkdir -p /etc/systemd/system/a-.service.d mkdir -p /etc/systemd/system/a-b-.service.d mkdir -p /etc/systemd/system/a-b-c.service.d echo -e '[Service]\nStandardInputText=aaa' >/etc/systemd/system/service.d/drop1.conf echo -e '[Service]\nStandardInputText=bbb' >/etc/systemd/system/a-.service.d/drop2.conf echo -e '[Service]\nStandardInputText=ccc' >/etc/systemd/system/a-b-.service.d/drop3.conf echo -e '[Service]\nStandardInputText=ddd' >/etc/systemd/system/a-b-c.service.d/drop4.conf # There's no fragment yet, so this fails systemctl cat a-b-c.service && exit 1 # xxx → eHh4Cg== systemd-run -u a-b-c.service -p StandardInputData=eHh4Cg== sleep infinity data=$(systemctl show -P StandardInputData a-b-c.service) # xxx\naaa\n\bbb\nccc\nddd\n → eHh4… test "$data" = "eHh4CmFhYQpiYmIKY2NjCmRkZAo=" # Do a reload and check again systemctl daemon-reload data=$(systemctl show -P StandardInputData a-b-c.service) test "$data" = "eHh4CmFhYQpiYmIKY2NjCmRkZAo=" clear_units a-b-c.service rm /etc/systemd/system/service.d/drop1.conf \ /etc/systemd/system/a-.service.d/drop2.conf \ /etc/systemd/system/a-b-.service.d/drop3.conf } test_transient_slice_dropins () { echo "Testing dropins for a transient slice..." echo "*** test transient slice drop-ins" # FIXME: implement reloading of individual units. # # The settings here are loaded twice. For most settings it doesn't matter, # but Documentation is not deduplicated, so we current get repeated entried # which is a bug. mkdir -p /etc/systemd/system/slice.d mkdir -p /etc/systemd/system/a-.slice.d mkdir -p /etc/systemd/system/a-b-.slice.d mkdir -p /etc/systemd/system/a-b-c.slice.d echo -e '[Unit]\nDocumentation=man:drop1' >/etc/systemd/system/slice.d/drop1.conf echo -e '[Unit]\nDocumentation=man:drop2' >/etc/systemd/system/a-.slice.d/drop2.conf echo -e '[Unit]\nDocumentation=man:drop3' >/etc/systemd/system/a-b-.slice.d/drop3.conf echo -e '[Unit]\nDocumentation=man:drop4' >/etc/systemd/system/a-b-c.slice.d/drop4.conf # Invoke daemon-reload to make sure that the call below doesn't fail systemctl daemon-reload # No fragment is required, so this works systemctl cat a-b-c.slice busctl call \ org.freedesktop.systemd1 \ /org/freedesktop/systemd1 \ org.freedesktop.systemd1.Manager \ StartTransientUnit 'ssa(sv)a(sa(sv))' \ 'a-b-c.slice' 'replace' \ 1 \ 'Documentation' as 1 'man:drop5' \ 0 data=$(systemctl show -P Documentation a-b-c.slice) test "$data" = "man:drop1 man:drop2 man:drop3 man:drop4 man:drop5 man:drop1 man:drop2 man:drop3 man:drop4" # Do a reload and check again systemctl daemon-reload data=$(systemctl show -P Documentation a-b-c.slice) test "$data" = "man:drop5 man:drop1 man:drop2 man:drop3 man:drop4" clear_units a-b-c.slice rm /etc/systemd/system/slice.d/drop1.conf \ /etc/systemd/system/a-.slice.d/drop2.conf \ /etc/systemd/system/a-b-.slice.d/drop3.conf } test_template_dropins () { echo "Testing template dropins..." create_services foo bar@ yup@ # Declare some deps to check if the body was loaded cat >>/etc/systemd/system/bar@.service <>/etc/systemd/system/yup@.service </usr/lib/systemd/system/test15-a.service.d/override.conf </usr/lib/systemd/system/test15-a.service.d/wants-b.conf</tmp/testsuite-15-test15-a-dropin-directory/override.conf <