mirror of
https://github.com/kevinveenbirkenbach/docker-volume-backup.git
synced 2026-07-17 06:05:13 +00:00
fix(backup,restore): make restore drills replayable and leave swarm tasks alone
Restore fixes, both hit by the infinito svc-bkp e2e drill: - mariadb --empty dropped tables one docker exec at a time with SET FOREIGN_KEY_CHECKS=0 issued in a separate client session, so the session-scoped toggle never applied and any FK-referenced parent table (mailu.users) died with ERROR 1451. Issue the toggle and all DROPs in one session. - postgres --empty now drops only current_user-owned objects (extension members like pg_trgm's set_limit are superuser-owned) with IF EXISTS absorbing CASCADE fallout, and the replay skips superuser-only dump lines (COMMENT ON EXTENSION, ALTER DEFAULT PRIVILEGES) that abort an app-user psql run under ON_ERROR_STOP. Backup fixes: - pg_dump now runs with --no-owner --no-privileges so future dumps are replayable by the owning app user in the first place. - Swarm task containers are never stopped or started manually: the orchestrator replaces a stopped task and a later docker start fails on the detached overlay network. filter_stoppable skips them visibly and the whitelist stop check ignores them. Validated end to end against a live infinito compose stack: the full svc-bkp-volume-2-local drill (verify, restore cycle, sql replay for mailu, keycloak and one more db) passes with these patches applied. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -59,15 +59,24 @@ class TestE2EMariaDBAnonymousPreemption(unittest.TestCase):
|
||||
# Boot WITHOUT MARIADB_USER/MARIADB_PASSWORD/MARIADB_DATABASE so the
|
||||
# entrypoint does not auto-create '<u>'@'%'. We provision the user
|
||||
# explicitly below to mirror the SQL path used by svc-db-mariadb.
|
||||
run([
|
||||
"docker", "run", "-d",
|
||||
"--name", cls.db_container,
|
||||
"-e", f"MARIADB_ROOT_PASSWORD={cls.root_password}",
|
||||
"-v", f"{cls.db_volume}:/var/lib/mysql",
|
||||
"mariadb:12.2",
|
||||
])
|
||||
run(
|
||||
[
|
||||
"docker",
|
||||
"run",
|
||||
"-d",
|
||||
"--name",
|
||||
cls.db_container,
|
||||
"-e",
|
||||
f"MARIADB_ROOT_PASSWORD={cls.root_password}",
|
||||
"-v",
|
||||
f"{cls.db_volume}:/var/lib/mysql",
|
||||
"mariadb:12.2",
|
||||
]
|
||||
)
|
||||
|
||||
wait_for_mariadb(cls.db_container, root_password=cls.root_password, timeout_s=120)
|
||||
wait_for_mariadb(
|
||||
cls.db_container, root_password=cls.root_password, timeout_s=120
|
||||
)
|
||||
|
||||
# Provision: '<u>'@'%' (the app/backup grant) + anonymous ''@'localhost'
|
||||
# (the preemption trigger). Mirrors the production state that produced
|
||||
@@ -81,10 +90,16 @@ class TestE2EMariaDBAnonymousPreemption(unittest.TestCase):
|
||||
f"CREATE TABLE {cls.db_name}.t (id INT PRIMARY KEY, v VARCHAR(50));"
|
||||
f"INSERT INTO {cls.db_name}.t VALUES (1,'ok');"
|
||||
)
|
||||
run([
|
||||
"docker", "exec", cls.db_container, "sh", "-lc",
|
||||
f'mariadb -uroot --protocol=socket -e "{bootstrap_sql}"',
|
||||
])
|
||||
run(
|
||||
[
|
||||
"docker",
|
||||
"exec",
|
||||
cls.db_container,
|
||||
"sh",
|
||||
"-lc",
|
||||
f'mariadb -uroot --protocol=socket -e "{bootstrap_sql}"',
|
||||
]
|
||||
)
|
||||
|
||||
# Sanity: '<u>' can log in over TCP (matches '%'). If THIS fails,
|
||||
# the precondition for the fix to even apply is broken.
|
||||
@@ -104,7 +119,11 @@ class TestE2EMariaDBAnonymousPreemption(unittest.TestCase):
|
||||
# ability to discriminate "fix works" vs "bug never reproduced".
|
||||
p = run(
|
||||
[
|
||||
"docker", "exec", self.db_container, "sh", "-lc",
|
||||
"docker",
|
||||
"exec",
|
||||
self.db_container,
|
||||
"sh",
|
||||
"-lc",
|
||||
f"mariadb-dump -u{self.db_user} -p{self.db_password} {self.db_name}",
|
||||
],
|
||||
capture=True,
|
||||
|
||||
@@ -44,7 +44,9 @@ class TestMariaDBDumpUsesTCP(unittest.TestCase):
|
||||
container="mariadb",
|
||||
)
|
||||
dump_cmds = [c for c in captured if "mariadb-dump" in c]
|
||||
self.assertEqual(len(dump_cmds), 1, f"expected one dump command, got: {captured}")
|
||||
self.assertEqual(
|
||||
len(dump_cmds), 1, f"expected one dump command, got: {captured}"
|
||||
)
|
||||
|
||||
cmd = dump_cmds[0]
|
||||
self.assertIn("-h 127.0.0.1", cmd)
|
||||
|
||||
Reference in New Issue
Block a user