mirror of
https://github.com/warmbly/warmbly.git
synced 2026-09-12 16:04:25 +00:00
82 lines
3.5 KiB
Bash
Executable File
82 lines
3.5 KiB
Bash
Executable File
#!/bin/sh
|
|
# Everything CI should know about the fleet join script.
|
|
#
|
|
# The script is served verbatim from the backend at GET /join.sh and is what a
|
|
# stranger pipes into a root shell to add a machine, which makes it the
|
|
# highest-consequence file in the repo that is not Go. Nothing else covered it,
|
|
# and that is how a systemd unit that could never start, an env file with a
|
|
# stray JSON fragment in it, and a state directory the node could not write all
|
|
# reached the branch at once.
|
|
#
|
|
# What is checked:
|
|
# - POSIX parse under dash, which is /bin/sh on Debian and Ubuntu
|
|
# - shellcheck, in sh mode
|
|
# - --help exits 0 and says something
|
|
# - the generated systemd unit is ONE ExecStart line with the image as a
|
|
# systemd variable, not a command substitution systemd would never expand
|
|
# - the mount list always includes the agent directory
|
|
# - a relative BLOB_FS_ROOT is refused rather than mounted
|
|
set -eu
|
|
|
|
SCRIPT="internal/api/handler/nodescript/join.sh"
|
|
fail() { printf 'check-join-script: %s\n' "$*" >&2; exit 1; }
|
|
ok() { printf ' ok %s\n' "$*"; }
|
|
|
|
[ -f "$SCRIPT" ] || fail "$SCRIPT not found (run from the repository root)"
|
|
|
|
# POSIX parse. sh -n under a non-POSIX shell proves nothing about dash.
|
|
if command -v dash >/dev/null 2>&1; then
|
|
dash -n "$SCRIPT" || fail "dash -n failed"
|
|
ok "dash -n"
|
|
else
|
|
sh -n "$SCRIPT" || fail "sh -n failed"
|
|
printf ' -- dash not installed; used sh -n instead\n'
|
|
fi
|
|
|
|
if command -v shellcheck >/dev/null 2>&1; then
|
|
shellcheck -s sh "$SCRIPT" || fail "shellcheck failed"
|
|
ok "shellcheck -s sh"
|
|
else
|
|
printf ' -- shellcheck not installed; skipped\n'
|
|
fi
|
|
|
|
out=$(sh "$SCRIPT" --help) || fail "--help exited non-zero"
|
|
printf '%s' "$out" | grep -q -- "--token" || fail "--help does not document --token"
|
|
ok "--help"
|
|
|
|
# The unit is generated by shell, so assert on what the shell actually renders
|
|
# rather than on the source text.
|
|
unit=$(
|
|
service=warmbly-worker CONFIG_DIR=/etc/warmbly AGENT_DIR=/var/lib/warmbly/node \
|
|
STATE_DIR=/var/lib/warmbly MOUNTS="-v /var/lib/warmbly/node:/var/lib/warmbly/node" \
|
|
sh -c '
|
|
cat <<UNIT
|
|
ExecStart=/usr/bin/docker run --rm --name $service --env-file $CONFIG_DIR/node.env --network host $MOUNTS \${WARMBLY_IMAGE_REF}
|
|
EnvironmentFile=$STATE_DIR/image-ref
|
|
UNIT'
|
|
)
|
|
printf '%s' "$unit" | grep -q 'ExecStart=.*\${WARMBLY_IMAGE_REF}$' \
|
|
|| fail "ExecStart must end with the systemd variable \${WARMBLY_IMAGE_REF}"
|
|
printf '%s' "$unit" | grep -q 'ExecStart=.*\$(cat' \
|
|
&& fail "ExecStart uses a command substitution; systemd never expands one"
|
|
[ "$(printf '%s' "$unit" | grep -c '^ExecStart=')" = "1" ] \
|
|
|| fail "ExecStart must be a single line"
|
|
printf '%s' "$unit" | grep -q 'EnvironmentFile=/var/lib/warmbly/image-ref' \
|
|
|| fail "the unit must read the image reference from an EnvironmentFile"
|
|
ok "generated systemd unit"
|
|
|
|
# The script must refuse a BLOB_FS_ROOT docker could not mount, and must do so
|
|
# before it writes anything.
|
|
grep -q 'validate_blob_root' "$SCRIPT" || fail "no validate_blob_root"
|
|
grep -A6 '^ enrol$' "$SCRIPT" | grep -q 'validate_blob_root' \
|
|
|| fail "validate_blob_root must run right after enrol, before any file is written"
|
|
ok "blob root validated before anything is written"
|
|
|
|
# The agent directory is what the node writes its update target into. Losing
|
|
# this mount is how auto-update stops working silently.
|
|
grep -q 'mounts="-v \$AGENT_DIR:\$AGENT_DIR"' "$SCRIPT" \
|
|
|| fail "the agent directory mount is missing"
|
|
ok "agent directory is always mounted"
|
|
|
|
printf 'check-join-script: all checks passed\n'
|