Prepare MariaDB restore tests and recover backup disk space safely
This commit is contained in:
1 parent
f0c761213d
commit
b0416461bc
23 files changed
+918
-129
No files matched your search
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
# Root-only installer preparation. No production SQL writes or credentials in Docker.
|
||||
set -Eeuo pipefail
|
||||
LIB_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=lib/common.sh
|
||||
source "$LIB_DIR/common.sh"
|
||||
CONFIG_FILE=${1:?Configuration required}
|
||||
load_config
|
||||
[[ $ENABLE_RESTORE_TEST == true ]] || exit 0
|
||||
guard_workspaces
|
||||
# shellcheck source=lib/locking.sh
|
||||
source "$LIB_DIR/locking.sh"
|
||||
acquire_backup_lock 1
|
||||
export APP_BACKUP_INHERIT_LOCK=1
|
||||
build_plan
|
||||
(( ${#DB_NAMES[@]} )) || exit 0
|
||||
need docker; need timeout
|
||||
docker_cmd=(docker --host=unix:///var/run/docker.sock)
|
||||
if ! "${docker_cmd[@]}" info --format '{{.DockerRootDir}}' >/dev/null 2>&1; then
|
||||
systemctl start docker.service
|
||||
fi
|
||||
docker_root=$("${docker_cmd[@]}" info --format '{{.DockerRootDir}}')
|
||||
[[ $docker_root == /* ]] || die 'Cannot determine local Docker storage'
|
||||
version=''
|
||||
for i in "${!DB_NAMES[@]}"; do
|
||||
secure_file "${DB_CNFS[i]}"
|
||||
server=$("$DB_CLIENT_BIN" --defaults-extra-file="${DB_CNFS[i]}" --database="${DB_NAMES[i]}" --batch --skip-column-names --execute='SELECT VERSION()')
|
||||
[[ $server =~ ^([0-9]+\.[0-9]+)\.[0-9]+.*MariaDB ]] || die 'Automatic restore-test preparation requires MariaDB; no production server changes made'
|
||||
found=${BASH_REMATCH[1]}
|
||||
[[ -z $version || $version == "$found" ]] || die 'Different production MariaDB series require separate restore-test configurations'
|
||||
version=$found
|
||||
done
|
||||
image=${RESTORE_TEST_DB_IMAGE:-mariadb:$version}
|
||||
[[ $image =~ ^[a-zA-Z0-9][a-zA-Z0-9._/:@-]*$ ]] || die 'Invalid restore-test image reference'
|
||||
if ! "${docker_cmd[@]}" image inspect "$image" >/dev/null 2>&1; then
|
||||
# Image layers are stored on Docker's filesystem, not necessarily WORKDIR.
|
||||
[[ -d $docker_root ]] || die 'Docker storage is not accessible for the space check'
|
||||
# shellcheck source=lib/space.sh
|
||||
source "$LIB_DIR/space.sh"
|
||||
ensure_space "$docker_root" 2147483648
|
||||
echo "-- Preparing isolated MariaDB image: $image"
|
||||
timeout --kill-after=30s 1800 "${docker_cmd[@]}" pull "$image"
|
||||
fi
|
||||
# Pin the probe to an immutable local image ID; never pull during monthly jobs.
|
||||
image_id=$("${docker_cmd[@]}" image inspect --format '{{.Id}}' "$image")
|
||||
"${docker_cmd[@]}" image inspect "$image_id" | python3 -c 'import json,sys; info=json.load(sys.stdin)[0]; assert not set(info.get("Config",{}).get("Volumes") or {}) - {"/var/lib/mysql"}, "Unexpected image volumes"'
|
||||
probe=$(timeout --kill-after=10s 60 "${docker_cmd[@]}" run --rm --pull=never --network=none --read-only \
|
||||
--cap-drop=ALL --security-opt=no-new-privileges --memory=128m --pids-limit=64 \
|
||||
--entrypoint=mariadbd "$image_id" --no-defaults --version)
|
||||
[[ $probe == *" $version."* && $probe == *MariaDB* ]] || die 'Restore-test image does not match production MariaDB series'
|
||||
echo "-- MariaDB $version image verified; testing isolated initialization/import/cleanup"
|
||||
# Use a private temporary config; publish the image selection only after success.
|
||||
prepared=$(mktemp "${CONFIG_FILE}.prepare-XXXXXX")
|
||||
trap 'rm -f -- "$prepared"' EXIT
|
||||
cp -- "$CONFIG_FILE" "$prepared"
|
||||
printf '\nRESTORE_TEST_DB_IMAGE=%q\n' "$image" >> "$prepared"
|
||||
script="$LIB_DIR/../usr-local-sbin/app-restore-test.sh"
|
||||
[[ -f $script ]] || script=/usr/local/sbin/app-restore-test.sh
|
||||
bash "$script" --config "$prepared" --prepare-db
|
||||
if [[ $RESTORE_TEST_DB_IMAGE != "$image" ]]; then
|
||||
chmod 600 "$prepared"
|
||||
mv -fT -- "$prepared" "$CONFIG_FILE"
|
||||
fi
|
||||
echo '-- MariaDB restore-test preparation passed; temporary database removed'
|
||||
Reference in new issue
Block a user