2021-11-22 19:21:43 +03:00
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -ex
set -o pipefail
# Wait for a service to enter a state within a timeout period, if it doesn't
# enter the desired state within the timeout period then this function will
# exit the test case with a non zero exit code.
wait_on_state_or_fail ( ) {
service = $1
expected_state = $2
timeout = $3
state = $( systemctl show " $service " --property= ActiveState --value)
while [ " $state " != " $expected_state " ] ; do
if [ " $timeout " = "0" ] ; then
systemd-analyze log-level info
exit 1
fi
timeout = $(( timeout - 1 ))
sleep 1
state = $( systemctl show " $service " --property= ActiveState --value)
done
}
systemd-analyze log-level debug
systemd-analyze log-target console
# Trigger testservice-failure-exit-handler-68.service
cat >/run/systemd/system/testservice-failure-68.service <<EOF
[ Unit]
Description = TEST-68-PROPAGATE-EXIT-STATUS with OnFailure = trigger
OnFailure = testservice-failure-exit-handler-68.service
[ Service]
ExecStart = /bin/bash -c "exit 1"
EOF
# Another service which triggers testservice-failure-exit-handler-68.service
cat >/run/systemd/system/testservice-failure-68-additional.service <<EOF
[ Unit]
2021-12-25 12:08:39 +03:00
Description = TEST-68-PROPAGATE-EXIT-STATUS Additional service with OnFailure = trigger
2021-11-22 19:21:43 +03:00
OnFailure = testservice-failure-exit-handler-68.service
[ Service]
ExecStart = /bin/bash -c "exit 1"
EOF
# Trigger testservice-success-exit-handler-68.service
cat >/run/systemd/system/testservice-success-68.service <<EOF
[ Unit]
Description = TEST-68-PROPAGATE-EXIT-STATUS with OnSuccess = trigger
OnSuccess = testservice-success-exit-handler-68.service
[ Service]
ExecStart = /bin/bash -c "exit 0"
EOF
# Trigger testservice-success-exit-handler-68.service
cat >/run/systemd/system/testservice-success-68-additional.service <<EOF
[ Unit]
Description = TEST-68-PROPAGATE-EXIT-STATUS Addition service with OnSuccess = trigger
OnSuccess = testservice-success-exit-handler-68.service
[ Service]
ExecStart = /bin/bash -c "exit 0"
EOF
# Script to check that when an OnSuccess= dependency fires, the correct
# MONITOR* env variables are passed. This script handles the case where
# multiple services triggered the unit that calls this script. In this
# case we need to check the MONITOR_METADATA variable for >= 1 service
# details since jobs may merge.
cat >/tmp/check_on_success.sh <<EOF
#!/usr/bin/env bash
set -ex
echo "MONITOR_METADATA=\$MONITOR_METADATA"
IFS = ';' read -ra ALL_SERVICE_MD <<< "\$MONITOR_METADATA"
for SERVICE_MD in "\${ALL_SERVICE_MD[@]}" ; do
IFS = ',' read -ra METADATA <<< "\$SERVICE_MD"
IFS = '=' read -ra SERVICE_RESULT <<< "\${METADATA[0]}"
SERVICE_RESULT = \$ { SERVICE_RESULT[ 1] }
IFS = '=' read -ra EXIT_CODE <<< "\${METADATA[1]}"
EXIT_CODE = \$ { EXIT_CODE[ 1] }
IFS = '=' read -ra EXIT_STATUS <<< "\${METADATA[2]}"
EXIT_STATUS = \$ { EXIT_STATUS[ 1] }
IFS = '=' read -ra INVOCATION_ID <<< "\${METADATA[3]}"
INVOCATION_ID = \$ { INVOCATION_ID[ 1] }
IFS = '=' read -ra UNIT <<< "\${METADATA[4]}"
UNIT = \$ { UNIT[ 1] }
if [ "\$SERVICE_RESULT" != "success" ] ; then
echo 'SERVICE_RESULT was "\$SERVICE_RESULT", expected "success"' ;
exit 1;
fi
if [ "\$EXIT_CODE" != "exited" ] ; then
echo 'EXIT_CODE was "\$EXIT_CODE", expected "exited"' ;
exit 1;
fi
if [ "\$EXIT_STATUS" != "0" ] ; then
echo 'EXIT_STATUS was "\$EXIT_STATUS", expected "0"' ;
exit 1;
fi
if [ -z "\$INVOCATION_ID" ] ; then
echo 'INVOCATION_ID unset' ;
exit 1;
fi
if [ [ "\$UNIT" != "testservice-success-68.service" && "\$UNIT" != "testservice-success-68-additional.service" && "\$UNIT" != "testservice-transient-success-68.service" ] ] ; then
echo 'UNIT was "\$UNIT", expected "testservice-success-68{-additional,-transient}.service"' ;
exit 1;
fi
done
exit 0;
EOF
chmod +x /tmp/check_on_success.sh
# Handle testservice-failure-exit-handler-68.service exiting with success.
cat >/run/systemd/system/testservice-success-exit-handler-68.service <<EOF
[ Unit]
Description = TEST-68-PROPAGATE-EXIT-STATUS handle service exiting in success
[ Service]
ExecStartPre = /tmp/check_on_success.sh
ExecStart = /tmp/check_on_success.sh
EOF
# Script to check that when an OnFailure= dependency fires, the correct
# MONITOR* env variables are passed. This script handles the case where
# multiple services triggered the unit that calls this script. In this
# case we need to check the MONITOR_METADATA variable for >=1 service
# details since jobs may merge.
cat >/tmp/check_on_failure.sh <<EOF
#!/usr/bin/env bash
set -ex
echo "MONITOR_METADATA=\$MONITOR_METADATA"
IFS = ';' read -ra ALL_SERVICE_MD <<< "\$MONITOR_METADATA"
for SERVICE_MD in "\${ALL_SERVICE_MD[@]}" ; do
IFS = ',' read -ra METADATA <<< "\$SERVICE_MD"
IFS = '=' read -ra SERVICE_RESULT <<< "\${METADATA[0]}"
SERVICE_RESULT = \$ { SERVICE_RESULT[ 1] }
IFS = '=' read -ra EXIT_CODE <<< "\${METADATA[1]}"
EXIT_CODE = \$ { EXIT_CODE[ 1] }
IFS = '=' read -ra EXIT_STATUS <<< "\${METADATA[2]}"
EXIT_STATUS = \$ { EXIT_STATUS[ 1] }
IFS = '=' read -ra INVOCATION_ID <<< "\${METADATA[3]}"
INVOCATION_ID = \$ { INVOCATION_ID[ 1] }
IFS = '=' read -ra UNIT <<< "\${METADATA[4]}"
UNIT = \$ { UNIT[ 1] }
if [ "\$SERVICE_RESULT" != "exit-code" ] ; then
echo 'SERVICE_RESULT was "\$SERVICE_RESULT", expected "exit-code"' ;
exit 1;
fi
if [ "\$EXIT_CODE" != "exited" ] ; then
echo 'EXIT_CODE was "\$EXIT_CODE", expected "exited"' ;
exit 1;
fi
if [ "\$EXIT_STATUS" != "1" ] ; then
echo 'EXIT_STATUS was "\$EXIT_STATUS", expected "1"' ;
exit 1;
fi
if [ -z "\$INVOCATION_ID" ] ; then
echo 'INVOCATION_ID unset' ;
exit 1;
fi
if [ [ "\$UNIT" != "testservice-failure-68.service" && "\$UNIT" != "testservice-failure-68-additional.service" && "\$UNIT" != "testservice-transient-failure-68.service" ] ] ; then
echo 'UNIT was "\$UNIT", expected "testservice-failure-68{-additional,-transient}.service"' ;
exit 1;
fi
done
exit 0;
EOF
chmod +x /tmp/check_on_failure.sh
# Handle testservice-failure-exit-handler-68.service exiting with failure.
cat >/run/systemd/system/testservice-failure-exit-handler-68.service <<EOF
[ Unit]
Description = TEST-68-PROPAGATE-EXIT-STATUS handle service exiting in failure
[ Service]
ExecStartPre = /tmp/check_on_failure.sh
ExecStart = /tmp/check_on_failure.sh
EOF
systemctl daemon-reload
# The running of the OnFailure= and OnSuccess= jobs for all of these services
# may result in jobs being merged.
systemctl start testservice-failure-68.service
wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
systemctl start testservice-failure-68-additional.service
wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
systemctl start testservice-success-68.service
wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
systemctl start testservice-success-68-additional.service
wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
# Test some transient units since these exit very quickly.
systemd-run --unit= testservice-transient-success-68 --property= OnSuccess = testservice-success-exit-handler-68.service /bin/bash -c "exit 0;"
wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
systemd-run --unit= testservice-transient-failure-68 --property= OnFailure = testservice-failure-exit-handler-68.service /bin/bash -c "exit 1;"
wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
# These yield a higher chance of resulting in jobs merging.
systemctl start testservice-failure-68.service testservice-failure-68-additional.service --no-block
wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
systemctl start testservice-success-68.service testservice-success-68-additional.service --no-block
wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
systemd-analyze log-level info
echo OK >/testok
exit 0