mirror of
https://github.com/kevinveenbirkenbach/docker-volume-backup.git
synced 2026-07-18 14:45:11 +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:
@@ -24,6 +24,31 @@ def containers_using_volume(volume_name: str) -> list[str]:
|
||||
)
|
||||
|
||||
|
||||
def is_swarm_task(container: str) -> bool:
|
||||
"""Swarm-managed task containers must never be stopped or started
|
||||
manually: the orchestrator replaces the stopped task and a later
|
||||
`docker start` fails on the detached overlay network."""
|
||||
out = execute_shell_command(
|
||||
"docker inspect --format "
|
||||
f"'{{{{index .Config.Labels \"com.docker.swarm.task.id\"}}}}' {container}"
|
||||
)
|
||||
return bool(out and out[0].strip())
|
||||
|
||||
|
||||
def filter_stoppable(containers: list[str]) -> list[str]:
|
||||
"""Containers baudolo may stop/start itself (everything but swarm tasks)."""
|
||||
stoppable = []
|
||||
for container in containers:
|
||||
if is_swarm_task(container):
|
||||
print(
|
||||
f"Skipping stop/start for swarm task container '{container}'.",
|
||||
flush=True,
|
||||
)
|
||||
continue
|
||||
stoppable.append(container)
|
||||
return stoppable
|
||||
|
||||
|
||||
def change_containers_status(containers: list[str], status: str) -> None:
|
||||
"""Stop or start a list of containers."""
|
||||
if not containers:
|
||||
|
||||
Reference in New Issue
Block a user