mirror of
https://github.com/kevinveenbirkenbach/docker-volume-backup.git
synced 2025-12-29 03:42:08 +00:00
- Use module logger in backup/db.py - Skip db dump when no databases.csv entry is present - Apply black/formatting cleanup across backup/restore/tests https://chatgpt.com/share/69519d45-b0dc-800f-acb6-6fb8504e9b46
108 lines
2.7 KiB
Python
108 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
|
|
from ..run import docker_exec, docker_exec_sh
|
|
|
|
|
|
def _pick_client(container: str) -> str:
|
|
"""
|
|
Prefer 'mariadb', fallback to 'mysql'.
|
|
Some MariaDB images no longer ship a 'mysql' binary, so we must not assume it exists.
|
|
"""
|
|
script = r"""
|
|
set -eu
|
|
if command -v mariadb >/dev/null 2>&1; then echo mariadb; exit 0; fi
|
|
if command -v mysql >/dev/null 2>&1; then echo mysql; exit 0; fi
|
|
exit 42
|
|
"""
|
|
try:
|
|
out = docker_exec_sh(container, script, capture=True).stdout.decode().strip()
|
|
if not out:
|
|
raise RuntimeError("empty client detection output")
|
|
return out
|
|
except Exception as e:
|
|
print(
|
|
"ERROR: neither 'mariadb' nor 'mysql' found in container.", file=sys.stderr
|
|
)
|
|
raise e
|
|
|
|
|
|
def restore_mariadb_sql(
|
|
*,
|
|
container: str,
|
|
db_name: str,
|
|
user: str,
|
|
password: str,
|
|
sql_path: str,
|
|
empty: bool,
|
|
) -> None:
|
|
client = _pick_client(container)
|
|
|
|
if not os.path.isfile(sql_path):
|
|
raise FileNotFoundError(sql_path)
|
|
|
|
if empty:
|
|
# IMPORTANT:
|
|
# Do NOT hardcode 'mysql' here. Use the detected client.
|
|
# MariaDB 11 images may not contain the mysql binary at all.
|
|
docker_exec(
|
|
container,
|
|
[
|
|
client,
|
|
"-u",
|
|
user,
|
|
f"--password={password}",
|
|
"-e",
|
|
"SET FOREIGN_KEY_CHECKS=0;",
|
|
],
|
|
)
|
|
|
|
result = docker_exec(
|
|
container,
|
|
[
|
|
client,
|
|
"-u",
|
|
user,
|
|
f"--password={password}",
|
|
"-N",
|
|
"-e",
|
|
f"SELECT table_name FROM information_schema.tables WHERE table_schema = '{db_name}';",
|
|
],
|
|
capture=True,
|
|
)
|
|
tables = result.stdout.decode().split()
|
|
|
|
for tbl in tables:
|
|
docker_exec(
|
|
container,
|
|
[
|
|
client,
|
|
"-u",
|
|
user,
|
|
f"--password={password}",
|
|
"-e",
|
|
f"DROP TABLE IF EXISTS `{db_name}`.`{tbl}`;",
|
|
],
|
|
)
|
|
|
|
docker_exec(
|
|
container,
|
|
[
|
|
client,
|
|
"-u",
|
|
user,
|
|
f"--password={password}",
|
|
"-e",
|
|
"SET FOREIGN_KEY_CHECKS=1;",
|
|
],
|
|
)
|
|
|
|
with open(sql_path, "rb") as f:
|
|
docker_exec(
|
|
container, [client, "-u", user, f"--password={password}", db_name], stdin=f
|
|
)
|
|
|
|
print(f"MariaDB/MySQL restore complete for db '{db_name}'.")
|