diff --git a/scripts/setup/native_mariadb_port_takeover.sh b/scripts/setup/native_mariadb_port_takeover.sh index 5496d00..6102773 100755 --- a/scripts/setup/native_mariadb_port_takeover.sh +++ b/scripts/setup/native_mariadb_port_takeover.sh @@ -107,6 +107,133 @@ preflight_new_port_free() { log "Port docelowy $NEW_NATIVE_PORT jest wolny." } +DID_SET_MYSQL_INST_NO=0 +CONFIG_BACKUPS=() + +disable_custombuild_mysql_management() { + if [ "$NATIVE_CURRENT_MYSQL_INST" = "no" ]; then + log "mysql_inst jest już ustawione na 'no' - pomijam." + return 0 + fi + "$DA_CLI_BIN" build set mysql_inst no >>"$LOG_FILE" 2>&1 \ + || die "Nie udało się ustawić mysql_inst=no przez '$DA_CLI_BIN build set mysql_inst no'." + DID_SET_MYSQL_INST_NO=1 + log "Ustawiono mysql_inst=no przez CustomBuild." +} + +restore_custombuild_mysql_management() { + [ "$DID_SET_MYSQL_INST_NO" -eq 1 ] || return 0 + "$DA_CLI_BIN" build set mysql_inst "$NATIVE_CURRENT_MYSQL_INST" >>"$LOG_FILE" 2>&1 \ + || log "OSTRZEŻENIE: nie udało się przywrócić mysql_inst=$NATIVE_CURRENT_MYSQL_INST." + log "Przywrócono mysql_inst=$NATIVE_CURRENT_MYSQL_INST." +} + +backup_config_file() { + local file="$1" + local backup + backup="${file}.bak.$(date +%Y%m%d%H%M%S)" + cp -a "$file" "$backup" + CONFIG_BACKUPS+=("$file:$backup") + log "Utworzono kopię zapasową $file jako $backup." +} + +rewrite_port_in_file() { + local file="$1" new_port="$2" + local tmp changed=0 + + [ -r "$file" ] || return 1 + tmp="$(mktemp)" + + awk -v new_port="$new_port" ' + BEGIN { in_section = 0; changed = 0 } + /^[[:space:]]*\[[^]]+\][[:space:]]*$/ { + section = tolower($0) + gsub(/^[[:space:]]*\[[[:space:]]*/, "", section) + gsub(/[[:space:]]*\][[:space:]]*$/, "", section) + in_section = (section == "mysqld" || section == "mariadb" || section == "server") + print + next + } + in_section && /^[[:space:]]*port[[:space:]]*=/ { + print "port=" new_port + changed = 1 + next + } + { print } + END { if (changed) exit 0; else exit 1 } + ' "$file" > "$tmp" + local awk_status=$? + + if [ "$awk_status" -eq 0 ]; then + cp "$tmp" "$file" + changed=1 + fi + rm -f "$tmp" + [ "$changed" -eq 1 ] +} + +find_and_rewrite_native_port_configs() { + local any_changed=0 + local f + + for f in "$NATIVE_MY_CNF" "$NATIVE_MY_CNF_D"/*.cnf; do + [ -f "$f" ] || continue + if grep -Eq '^[[:space:]]*port[[:space:]]*=[[:space:]]*3306[[:space:]]*$' "$f"; then + backup_config_file "$f" + if rewrite_port_in_file "$f" "$NEW_NATIVE_PORT"; then + any_changed=1 + log "Zaktualizowano port w $f." + fi + fi + done + + if [ "$any_changed" -eq 0 ]; then + backup_config_file "$NATIVE_MY_CNF" + if grep -Eq '^[[:space:]]*\[mysqld\][[:space:]]*$' "$NATIVE_MY_CNF"; then + awk -v new_port="$NEW_NATIVE_PORT" ' + { print } + /^[[:space:]]*\[mysqld\][[:space:]]*$/ && !done { print "port=" new_port; done=1 } + ' "$NATIVE_MY_CNF" > "${NATIVE_MY_CNF}.tmp" && mv "${NATIVE_MY_CNF}.tmp" "$NATIVE_MY_CNF" + else + printf '\n[mysqld]\nport=%s\n' "$NEW_NATIVE_PORT" >> "$NATIVE_MY_CNF" + fi + log "Brak istniejącej dyrektywy port= w sekcji serwera - dodano port=$NEW_NATIVE_PORT do $NATIVE_MY_CNF." + fi +} + +update_native_mysql_conf_port() { + local target_port="$1" + local tmp + tmp="$(mktemp)" + awk -v new_port="$target_port" ' + BEGIN { done = 0 } + /^[[:space:]]*port[[:space:]]*=/ { print "port=" new_port; done=1; next } + { print } + END { if (!done) print "port=" new_port } + ' "$NATIVE_MYSQL_CONF" > "$tmp" + cp "$tmp" "$NATIVE_MYSQL_CONF" + rm -f "$tmp" +} + +apply_config_mutations() { + backup_config_file "$NATIVE_MYSQL_CONF" + find_and_rewrite_native_port_configs + update_native_mysql_conf_port "$NEW_NATIVE_PORT" + log "Zaktualizowano $NATIVE_MYSQL_CONF na port $NEW_NATIVE_PORT." +} + +rollback_config_changes() { + local pair file backup + for pair in "${CONFIG_BACKUPS[@]}"; do + file="${pair%%:*}" + backup="${pair#*:}" + if [ -r "$backup" ]; then + cp -a "$backup" "$file" + log "Przywrócono $file z kopii zapasowej $backup." + fi + done +} + [ -r "$COMMON_FILE" ] || die "missing helper: $COMMON_FILE" # shellcheck source=./mysql_common.sh source "$COMMON_FILE" diff --git a/tests/native_mariadb_port_takeover_mutation_test.sh b/tests/native_mariadb_port_takeover_mutation_test.sh new file mode 100644 index 0000000..0327c86 --- /dev/null +++ b/tests/native_mariadb_port_takeover_mutation_test.sh @@ -0,0 +1,100 @@ +#!/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 +} + +mkdir -p "$TMP_DIR/bin" "$TMP_DIR/my.cnf.d" +CALL_LOG="$TMP_DIR/calls.log" + +cat > "$TMP_DIR/bin/da" <> "$CALL_LOG" +exit 0 +EOF +chmod 755 "$TMP_DIR/bin/da" + +cat > "$TMP_DIR/my.cnf" <<'EOF' +[client] +port=3306 + +[mysqld] +datadir=/var/lib/mysql +port=3306 +socket=/var/lib/mysql/mysql.sock +EOF + +cat > "$TMP_DIR/mysql.conf" <<'EOF' +user=da_admin +passwd=secret +port=3306 +socket=/var/lib/mysql/mysql.sock +host= +EOF + +NATIVE_TAKEOVER_LOG="$TMP_DIR/takeover.log" \ + source "$SCRIPT" + +NATIVE_MY_CNF="$TMP_DIR/my.cnf" +NATIVE_MY_CNF_D="$TMP_DIR/my.cnf.d" +NATIVE_MYSQL_CONF="$TMP_DIR/mysql.conf" +NEW_NATIVE_PORT="3307" +DA_CLI_BIN="$TMP_DIR/bin/da" +NATIVE_CURRENT_MYSQL_INST="mariadb" + +# --- disable_custombuild_mysql_management --- +: > "$CALL_LOG" +disable_custombuild_mysql_management +grep -Fxq "build set mysql_inst no" "$CALL_LOG" \ + || fail "expected 'da build set mysql_inst no' to be called, got: $(cat "$CALL_LOG")" +[ "$DID_SET_MYSQL_INST_NO" -eq 1 ] || fail "expected DID_SET_MYSQL_INST_NO to be set" + +# --- idempotency: already "no" must skip calling da --- +: > "$CALL_LOG" +DID_SET_MYSQL_INST_NO=0 +NATIVE_CURRENT_MYSQL_INST="no" +disable_custombuild_mysql_management +[ ! -s "$CALL_LOG" ] || fail "expected no 'da' call when mysql_inst is already 'no'" +[ "$DID_SET_MYSQL_INST_NO" -eq 0 ] || fail "DID_SET_MYSQL_INST_NO should stay 0 when already 'no'" +NATIVE_CURRENT_MYSQL_INST="mariadb" + +# --- apply_config_mutations --- +CONFIG_BACKUPS=() +apply_config_mutations + +grep -Fxq "port=3307" "$TMP_DIR/mysql.conf" \ + || fail "expected mysql.conf port to be rewritten to 3307, got: $(cat "$TMP_DIR/mysql.conf")" +grep -Fxq "passwd=secret" "$TMP_DIR/mysql.conf" \ + || fail "expected mysql.conf passwd to be preserved untouched" + +grep -A2 '^\[mysqld\]' "$TMP_DIR/my.cnf" | grep -Fxq "port=3307" \ + || fail "expected [mysqld] port in my.cnf to be rewritten to 3307" +grep -A1 '^\[client\]' "$TMP_DIR/my.cnf" | grep -Fxq "port=3306" \ + || fail "expected [client] port in my.cnf to be left at 3306 (only server sections rewritten)" + +[ "${#CONFIG_BACKUPS[@]}" -ge 2 ] \ + || fail "expected at least 2 backup entries (my.cnf + mysql.conf), got ${#CONFIG_BACKUPS[@]}" + +# --- rollback_config_changes --- +rollback_config_changes + +grep -A2 '^\[mysqld\]' "$TMP_DIR/my.cnf" | grep -Fxq "port=3306" \ + || fail "expected [mysqld] port in my.cnf to be restored to 3306 after rollback" +grep -Fxq "port=3306" "$TMP_DIR/mysql.conf" \ + || fail "expected mysql.conf port to be restored to 3306 after rollback" + +# --- restore_custombuild_mysql_management --- +: > "$CALL_LOG" +DID_SET_MYSQL_INST_NO=1 +restore_custombuild_mysql_management +grep -Fxq "build set mysql_inst mariadb" "$CALL_LOG" \ + || fail "expected 'da build set mysql_inst mariadb' to be called on rollback, got: $(cat "$CALL_LOG")" + +echo "native_mariadb_port_takeover_mutation_test: OK"