#!/bin/bash set -euo pipefail PLUGIN_DIR="$(cd "$(dirname "$0")/.." && pwd)" SCRIPT="$PLUGIN_DIR/scripts/setup/native_mariadb_port_takeover.sh" TMP_DIR="$(mktemp -d)" trap 'rm -rf "$TMP_DIR"' EXIT fail() { echo "FAIL: $*" >&2 exit 1 } setup_fixture() { local dir="$1" mkdir -p "$dir/bin" "$dir/my.cnf.d" cat > "$dir/my.cnf" <<'EOF' [client] port=3306 [mysqld] datadir=/var/lib/mysql port=3306 socket=/var/lib/mysql/mysql.sock EOF cat > "$dir/mysql.conf" <<'EOF' user=da_admin passwd=secret port=3306 socket=/var/lib/mysql/mysql.sock host= EOF cat > "$dir/options.conf" <<'EOF' mysql_inst=mariadb mariadb=10.6 EOF cat > "$dir/os-release" <<'EOF' ID="almalinux" VERSION_ID="9.4" EOF } # run_takeover DIR # Runs the script under test against the fixture already prepared at DIR # (by a prior call to setup_fixture, possibly customized further by the # scenario since) - writes stdout+stderr to "$DIR/run.out". Does NOT touch # the fixture itself, so scenario-specific customizations made after # setup_fixture (e.g. editing mysql.conf, swapping os-release) are preserved. run_takeover() { local dir="$1" env \ NATIVE_TAKEOVER_LOG="$dir/takeover.log" \ NATIVE_MY_CNF="$dir/my.cnf" \ NATIVE_MY_CNF_D="$dir/my.cnf.d" \ NATIVE_MYSQL_CONF="$dir/mysql.conf" \ CUSTOMBUILD_OPTIONS_CONF="$dir/options.conf" \ OS_RELEASE_FILE="$dir/os-release" \ NEW_NATIVE_PORT="3307" \ DA_CLI_BIN="$dir/bin/da" \ PATH="$dir/bin:$PATH" \ bash "$SCRIPT" > "$dir/run.out" 2>&1 } # --- Fake command stubs shared by scenarios; each scenario builds its own copies --- write_common_stubs() { local dir="$1" local mode="${2:-happy}" cat > "$dir/bin/da" <> "$dir/da_calls.log" exit 0 EOF chmod 755 "$dir/bin/da" cat > "$dir/bin/mysql" </dev/null || echo 3306)" ]; then exit 0 fi exit 1 EOF chmod 755 "$dir/bin/mysql" echo "3306" > "$dir/current_port" cat > "$dir/bin/systemctl" <.service' and picks the first # that succeeds - only mariadb.service "exists" here, matching a real # AlmaLinux+MariaDB box where mysqld.service does not exist. if [ "\$1" = "list-unit-files" ]; then case "\$2" in mariadb.service) exit 0 ;; *) exit 1 ;; esac fi echo "systemctl \$*" >> "$dir/systemctl_calls.log" if [ "\$1" = "restart" ] && [ "\$2" = "mariadb" ] && [ "$mode" = "restart-fail" ]; then exit 1 fi if [ "\$1" = "restart" ] && [ "\$2" = "mariadb" ]; then echo "3307" > "$dir/current_port" fi if [ "\$1" = "restart" ] && [ "\$2" = "directadmin" ] && [ "$mode" = "da-restart-fail" ]; then exit 1 fi exit 0 EOF chmod 755 "$dir/bin/systemctl" cat > "$dir/bin/ss" </dev/null || echo 3306)" for arg in "\$@"; do case "\$arg" in *":\$current"*) echo header; echo occupied; exit 0 ;; esac done exit 0 EOF chmod 755 "$dir/bin/ss" } # --- Scenario 1: happy path --- DIR="$TMP_DIR/happy" setup_fixture "$DIR" write_common_stubs "$DIR" happy run_takeover "$DIR" STATUS=$? [ "$STATUS" -eq 0 ] || fail "happy path should exit 0, got $STATUS: $(cat "$DIR/run.out")" grep -Fxq "port=3307" "$DIR/mysql.conf" || fail "happy path should leave mysql.conf on port 3307" grep -Fq "build set mysql_inst no" "$DIR/da_calls.log" || fail "happy path should call da build set mysql_inst no" grep -Fq "restart mariadb" "$DIR/systemctl_calls.log" || fail "happy path should restart mariadb" grep -Fq "restart directadmin" "$DIR/systemctl_calls.log" || fail "happy path should restart directadmin" # --- Scenario 2: already migrated (idempotent no-op) --- DIR="$TMP_DIR/already" setup_fixture "$DIR" write_common_stubs "$DIR" happy sed -i.orig 's/^port=3306$/port=3307/' "$DIR/mysql.conf" run_takeover "$DIR" STATUS=$? [ "$STATUS" -eq 0 ] || fail "already-migrated case should exit 0, got $STATUS" grep -Fq "build set" "$DIR/da_calls.log" 2>/dev/null && fail "already-migrated case should not touch CustomBuild settings" # --- Scenario 3: OS guard rejection --- DIR="$TMP_DIR/badose" setup_fixture "$DIR" write_common_stubs "$DIR" happy cat > "$DIR/os-release" <<'EOF' ID="cloudlinux" VERSION_ID="8.9" EOF set +e run_takeover "$DIR" STATUS=$? set -e [ "$STATUS" -ne 0 ] || fail "CloudLinux should be refused, not exit 0" grep -Fq "build set" "$DIR/da_calls.log" 2>/dev/null && fail "OS-guard rejection must not touch CustomBuild settings" # --- Scenario 4: rollback when native restart fails --- DIR="$TMP_DIR/restartfail" setup_fixture "$DIR" write_common_stubs "$DIR" restart-fail set +e run_takeover "$DIR" STATUS=$? set -e [ "$STATUS" -ne 0 ] || fail "a failed native restart should not exit 0" grep -Fxq "port=3306" "$DIR/mysql.conf" \ || fail "mysql.conf should be rolled back to port 3306 after a failed native restart" grep -Fq "build set mysql_inst mariadb" "$DIR/da_calls.log" \ || fail "mysql_inst should be restored to mariadb after a failed native restart" # --- Scenario 5: rollback when DirectAdmin restart fails --- DIR="$TMP_DIR/darestartfail" setup_fixture "$DIR" write_common_stubs "$DIR" da-restart-fail set +e run_takeover "$DIR" STATUS=$? set -e [ "$STATUS" -ne 0 ] || fail "a failed directadmin restart should not exit 0" grep -Fxq "port=3306" "$DIR/mysql.conf" \ || fail "mysql.conf should be rolled back to port 3306 after a failed directadmin restart" grep -Fq "build set mysql_inst mariadb" "$DIR/da_calls.log" \ || fail "mysql_inst should be restored to mariadb after a failed directadmin restart" echo "native_mariadb_port_takeover_e2e_test: OK"