Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ for five minutes around the apply; the changed ceiling must still appear within
Control-phase requests pass the temporary bearer token through curl's stdin configuration,
keeping it out of process arguments. Each POST uses its own securely allocated response file,
removed after reading the change identifier.
The drop-in is written in a private staging file and published atomically with `link` only after the
write succeeds. A partial write fails setup and cleanup removes the staging file. Publication refuses
an existing or competing destination, including symlinks, without claiming or removing it.
Cleanup quiesces the timer and instrumented pass, emits only measurement records from the journal, removes
the drop-in, reloads systemd and restores the timer’s prior active state before config/runtime restoration.
the owned drop-in, reloads systemd and restores the timer’s prior active state before config/runtime restoration.
The job fails if journal collection or measurement export fails, no profiled refresh completes
successfully, or cleanup fails. Begin events from unfinished helpers are retained to locate stalled
operations, including a pass stopped by cleanup.
Expand Down
19 changes: 12 additions & 7 deletions tests/e2e-refresh-window.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# shellcheck shell=bash
# Reserved control-phase lifecycle; overrides only ExecStart, retaining the real service policy.
REFRESH_PROFILE_DROPIN="" REFRESH_PROFILE_SINCE="" REFRESH_PROFILE_TIMER_ACTIVE=""
REFRESH_PROFILE_STAGING="" REFRESH_PROFILE_DROPIN="" REFRESH_PROFILE_SINCE="" REFRESH_PROFILE_TIMER_ACTIVE=""
refresh_profile_start() {
local dir="${REFRESH_PROFILE_UNIT_ROOT:-/run/systemd/system}/rigforge-api-refresh.service.d"
local script
Expand All @@ -13,12 +13,14 @@ refresh_profile_start() {
systemctl is-active --quiet rigforge-api-refresh.timer && REFRESH_PROFILE_TIMER_ACTIVE=1
REFRESH_PROFILE_SINCE=$(date -u '+%Y-%m-%d %H:%M:%S')
local dropin="$dir/rigforge-profile.conf"
(
umask 077
set -o noclobber
printf '[Service]\nExecStart=\nExecStart=/bin/bash %s %s\n' "$script" "$RIGFORGE" >"$dropin"
) || return 1
# Stage privately: failed writes must never expose an incomplete service policy.
REFRESH_PROFILE_STAGING=$(mktemp "$dir/.rigforge-profile.XXXXXX") || return 1
printf '[Service]\nExecStart=\nExecStart=/bin/bash %s %s\n' "$script" "$RIGFORGE" >|"$REFRESH_PROFILE_STAGING" || return 1
# POSIX link uses the exact destination (unlike ln's directory handling) and never replaces it.
link "$REFRESH_PROFILE_STAGING" "$dropin" || return 1
REFRESH_PROFILE_DROPIN="$dropin"
rm -f "$REFRESH_PROFILE_STAGING" || return 1
REFRESH_PROFILE_STAGING=""
systemctl daemon-reload
}
refresh_profile_state() {
Expand All @@ -29,8 +31,11 @@ refresh_profile_state() {
-p ExecMainStartTimestamp -p ExecMainExitTimestamp -p ExecMainStatus
}
refresh_profile_finish() {
[ -n "$REFRESH_PROFILE_DROPIN" ] || return 0
local log rc=0
if [ -n "$REFRESH_PROFILE_STAGING" ]; then
if rm -f "$REFRESH_PROFILE_STAGING"; then REFRESH_PROFILE_STAGING=""; else rc=1; fi
fi
[ -n "$REFRESH_PROFILE_DROPIN" ] || return "$rc"
refresh_profile_state || rc=1
# Quiesce both units before collecting: the timer could otherwise dispatch during cleanup.
systemctl stop rigforge-api-refresh.timer || rc=1
Expand Down
85 changes: 84 additions & 1 deletion tests/test-refresh-profile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,90 @@ printf 'existing override\n' >"$owned"
if refresh_profile_start; then exit 1; fi
refresh_profile_finish
check test "$(cat "$owned")" = 'existing override'
rm "$owned"
command rm "$owned"
# A failed partial write must remain owned until cleanup removes it.
saved_umask=$(umask)
umask 027
exec 9>"$CASE_DIR/caller-fd"
printf() {
if [[ "$1" == '[Service]'* ]]; then
builtin printf '[Service]\nExecStart=\n'
return 7
fi
builtin printf "$@"
}
if refresh_profile_start; then exit 1; fi
unset -f printf
check test "$(umask)" = 0027
case $- in *C*) exit 1 ;; esac
builtin printf 'caller descriptor preserved\n' >&9
exec 9>&-
check test "$(cat "$CASE_DIR/caller-fd")" = 'caller descriptor preserved'
umask "$saved_umask"
check test -z "$REFRESH_PROFILE_DROPIN"
check test ! -e "$owned"
staged="$REFRESH_PROFILE_STAGING"
check test "$(cat "$staged")" = "$(builtin printf '[Service]\nExecStart=')"
rm() { return 7; }
if refresh_profile_finish; then exit 1; fi
check test "$REFRESH_PROFILE_STAGING" = "$staged"
check test -e "$staged"
unset -f rm
refresh_profile_finish >"$CASE_DIR/partial-write-collected"
check test ! -e "$owned"
check test ! -e "$staged"
check test -z "$REFRESH_PROFILE_STAGING"
check test -z "$REFRESH_PROFILE_DROPIN"
# A competitor arriving after the initial existence check must not be claimed or removed.
mkdir() {
command mkdir "$@" || return
builtin printf 'competing override\n' >"$owned"
}
set -o noclobber
if refresh_profile_start 2>"$CASE_DIR/collision-error"; then exit 1; fi
unset -f mkdir
case $- in *C*) : ;; *) exit 1 ;; esac
set +o noclobber
check test "$(umask)" = "$saved_umask"
check test -z "$REFRESH_PROFILE_DROPIN"
refresh_profile_finish
check test "$(cat "$owned")" = 'competing override'
command rm "$owned"
# A raced symlink to a nonregular target must also remain untouched.
mkdir() {
command mkdir "$@" || return
ln -s /dev/null "$owned"
}
if refresh_profile_start 2>"$CASE_DIR/symlink-collision-error"; then exit 1; fi
unset -f mkdir
check test -z "$REFRESH_PROFILE_DROPIN"
refresh_profile_finish
check test -L "$owned"
check test "$(readlink "$owned")" = /dev/null
command rm "$owned"
# Staging allocation failure must fail setup without claiming any override.
mktemp() { return 7; }
if refresh_profile_start; then exit 1; fi
unset -f mktemp
check test -z "$REFRESH_PROFILE_STAGING"
check test -z "$REFRESH_PROFILE_DROPIN"
refresh_profile_finish
check test ! -e "$owned"
# Failure to unlink staging after publication must not prevent live-override cleanup.
rm() {
if [ "${2:-}" = "$REFRESH_PROFILE_STAGING" ]; then return 7; fi
command rm "$@"
}
if refresh_profile_start; then exit 1; fi
staged="$REFRESH_PROFILE_STAGING"
check test -n "$REFRESH_PROFILE_DROPIN"
if refresh_profile_finish >"$CASE_DIR/staging-unlink-failed"; then exit 1; fi
check test ! -e "$owned"
check test -e "$staged"
unset -f rm
refresh_profile_finish
check test ! -e "$staged"
check test -z "$REFRESH_PROFILE_STAGING"
# A window without a completed profiled refresh cannot report successful diagnostics.
refresh_profile_start
journalctl() { :; }
Expand Down