test(e2e): stabilize MariaDB 11 tests and fix restore empty-mode client selection

- add `make clean` and run it before `test-e2e` to avoid stale artifacts
- restore: do not hardcode `mysql` for --empty; use detected mariadb/mysql client
- e2e: improve subprocess error output for easier CI debugging
- e2e: adjust MariaDB readiness checks for socket-only root on MariaDB 11
- e2e: add `wait_for_mariadb_sql` and run SQL readiness checks for dedicated TCP user
- e2e: update MariaDB full/no-copy tests to use dedicated user over TCP and consistent credentials

https://chatgpt.com/share/694ecfb8-f8a8-800f-a1c9-a5f410d4ba02
This commit is contained in:
2025-12-26 19:10:55 +01:00
parent 4af15d9074
commit cf6f4d8326
5 changed files with 257 additions and 101 deletions

View File

@@ -8,14 +8,30 @@ import uuid
from pathlib import Path
def run(cmd: list[str], *, capture: bool = True, check: bool = True, cwd: str | None = None) -> subprocess.CompletedProcess:
return subprocess.run(
cmd,
check=check,
cwd=cwd,
text=True,
capture_output=capture,
)
def run(
cmd: list[str],
*,
capture: bool = True,
check: bool = True,
cwd: str | None = None,
) -> subprocess.CompletedProcess:
try:
return subprocess.run(
cmd,
check=check,
cwd=cwd,
text=True,
capture_output=capture,
)
except subprocess.CalledProcessError as e:
# Print captured output so failing E2E tests are "live" / debuggable in CI logs
print(">>> command failed:", " ".join(cmd))
print(">>> exit code:", e.returncode)
if e.stdout:
print(">>> STDOUT:\n" + e.stdout)
if e.stderr:
print(">>> STDERR:\n" + e.stderr)
raise
def sh(cmd: str, *, capture: bool = True, check: bool = True) -> subprocess.CompletedProcess:
@@ -66,13 +82,17 @@ def wait_for_postgres(container: str, *, user: str = "postgres", timeout_s: int
def wait_for_mariadb(container: str, *, root_password: str, timeout_s: int = 90) -> None:
"""
Docker-outside-of-Docker friendly readiness: check from inside the DB container.
Liveness probe for MariaDB.
IMPORTANT (MariaDB 11):
Root TCP auth is often restricted (unix_socket auth), so a TCP ping like
`mariadb-admin -uroot -p... -h localhost ping` can fail even though the server is up.
We therefore check readiness via a socket-based query.
"""
deadline = time.time() + timeout_s
while time.time() < deadline:
# mariadb-admin is present in the official mariadb image
p = run(
["docker", "exec", container, "sh", "-lc", f"mariadb-admin -uroot -p{root_password} ping -h localhost"],
["docker", "exec", container, "sh", "-lc", "mariadb -uroot --protocol=socket -e \"SELECT 1;\""],
capture=True,
check=False,
)
@@ -82,6 +102,33 @@ def wait_for_mariadb(container: str, *, root_password: str, timeout_s: int = 90)
raise TimeoutError(f"Timed out waiting for MariaDB readiness in container {container}")
def wait_for_mariadb_sql(container: str, *, user: str, password: str, timeout_s: int = 90) -> None:
"""
SQL login readiness for the *dedicated test user* over TCP.
This is separate from wait_for_mariadb(root) because root may be socket-only,
while the tests use a normal user that should work via TCP.
"""
deadline = time.time() + timeout_s
while time.time() < deadline:
p = run(
[
"docker",
"exec",
container,
"sh",
"-lc",
f"mariadb -h 127.0.0.1 -u{user} -p{password} -e \"SELECT 1;\"",
],
capture=True,
check=False,
)
if p.returncode == 0:
return
time.sleep(1)
raise TimeoutError(f"Timed out waiting for MariaDB SQL login readiness in container {container}")
def backup_run(
*,
backups_dir: str,
@@ -111,7 +158,6 @@ def backup_run(
try:
run(cmd, capture=True, check=True)
except subprocess.CalledProcessError as e:
# Print captured output so failing E2E tests are "live" / debuggable in CI logs
print(">>> baudolo failed (exit code:", e.returncode, ")")
if e.stdout:
print(">>> baudolo STDOUT:\n" + e.stdout)