backup-docker-to-local 1.1.0__tar.gz → 1.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {backup_docker_to_local-1.1.0/src/backup_docker_to_local.egg-info → backup_docker_to_local-1.1.1}/PKG-INFO +1 -1
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/pyproject.toml +1 -1
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1/src/backup_docker_to_local.egg-info}/PKG-INFO +1 -1
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/app.py +29 -17
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/db.py +21 -13
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/LICENSE +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/README.md +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/setup.cfg +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/backup_docker_to_local.egg-info/SOURCES.txt +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/backup_docker_to_local.egg-info/dependency_links.txt +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/backup_docker_to_local.egg-info/entry_points.txt +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/backup_docker_to_local.egg-info/requires.txt +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/backup_docker_to_local.egg-info/top_level.txt +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/__init__.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/__init__.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/__main__.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/cli.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/compose.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/docker.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/shell.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/volume.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/__init__.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/__main__.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/db/__init__.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/db/mariadb.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/db/postgres.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/files.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/paths.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/run.py +0 -0
- {backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/seed/__main__.py +0 -0
|
@@ -72,28 +72,27 @@ def requires_stop(containers: list[str], images_no_stop_required: list[str]) ->
|
|
|
72
72
|
return True
|
|
73
73
|
return False
|
|
74
74
|
|
|
75
|
-
|
|
76
75
|
def backup_mariadb_or_postgres(
|
|
77
76
|
*,
|
|
78
77
|
container: str,
|
|
79
78
|
volume_dir: str,
|
|
80
79
|
databases_df: "pandas.DataFrame",
|
|
81
80
|
database_containers: list[str],
|
|
82
|
-
) -> bool:
|
|
81
|
+
) -> tuple[bool, bool]:
|
|
83
82
|
"""
|
|
84
|
-
Returns
|
|
83
|
+
Returns (is_db_container, dumped_any)
|
|
85
84
|
"""
|
|
86
85
|
for img in ["mariadb", "postgres"]:
|
|
87
86
|
if has_image(container, img):
|
|
88
|
-
backup_database(
|
|
87
|
+
dumped = backup_database(
|
|
89
88
|
container=container,
|
|
90
89
|
volume_dir=volume_dir,
|
|
91
90
|
db_type=img,
|
|
92
91
|
databases_df=databases_df,
|
|
93
92
|
database_containers=database_containers,
|
|
94
93
|
)
|
|
95
|
-
return True
|
|
96
|
-
return False
|
|
94
|
+
return True, dumped
|
|
95
|
+
return False, False
|
|
97
96
|
|
|
98
97
|
|
|
99
98
|
def _backup_dumps_for_volume(
|
|
@@ -102,21 +101,26 @@ def _backup_dumps_for_volume(
|
|
|
102
101
|
vol_dir: str,
|
|
103
102
|
databases_df: "pandas.DataFrame",
|
|
104
103
|
database_containers: list[str],
|
|
105
|
-
) -> bool:
|
|
104
|
+
) -> tuple[bool, bool]:
|
|
106
105
|
"""
|
|
107
|
-
|
|
108
|
-
Returns True if at least one dump was produced.
|
|
106
|
+
Returns (found_db_container, dumped_any)
|
|
109
107
|
"""
|
|
108
|
+
found_db = False
|
|
110
109
|
dumped_any = False
|
|
110
|
+
|
|
111
111
|
for c in containers:
|
|
112
|
-
|
|
112
|
+
is_db, dumped = backup_mariadb_or_postgres(
|
|
113
113
|
container=c,
|
|
114
114
|
volume_dir=vol_dir,
|
|
115
115
|
databases_df=databases_df,
|
|
116
116
|
database_containers=database_containers,
|
|
117
|
-
)
|
|
117
|
+
)
|
|
118
|
+
if is_db:
|
|
119
|
+
found_db = True
|
|
120
|
+
if dumped:
|
|
118
121
|
dumped_any = True
|
|
119
|
-
|
|
122
|
+
|
|
123
|
+
return found_db, dumped_any
|
|
120
124
|
|
|
121
125
|
|
|
122
126
|
def main() -> int:
|
|
@@ -137,18 +141,26 @@ def main() -> int:
|
|
|
137
141
|
containers = containers_using_volume(volume_name)
|
|
138
142
|
|
|
139
143
|
vol_dir = create_volume_directory(version_dir, volume_name)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
_backup_dumps_for_volume(
|
|
144
|
+
|
|
145
|
+
found_db, dumped_any = _backup_dumps_for_volume(
|
|
143
146
|
containers=containers,
|
|
144
147
|
vol_dir=vol_dir,
|
|
145
148
|
databases_df=databases_df,
|
|
146
149
|
database_containers=args.database_containers,
|
|
147
150
|
)
|
|
148
151
|
|
|
149
|
-
# dump-only:
|
|
152
|
+
# dump-only logic:
|
|
150
153
|
if args.dump_only:
|
|
151
|
-
|
|
154
|
+
if found_db and not dumped_any:
|
|
155
|
+
print(
|
|
156
|
+
f"WARNING: dump-only requested but no DB dump was produced for DB volume '{volume_name}'. Falling back to file backup.",
|
|
157
|
+
flush=True,
|
|
158
|
+
)
|
|
159
|
+
# continue to file backup below
|
|
160
|
+
else:
|
|
161
|
+
# keep old behavior: skip file backups
|
|
162
|
+
continue
|
|
163
|
+
|
|
152
164
|
|
|
153
165
|
# skip file backup if all linked containers are ignored
|
|
154
166
|
if volume_is_fully_ignored(containers, args.images_no_backup_required):
|
|
@@ -3,9 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import os
|
|
4
4
|
import pathlib
|
|
5
5
|
import re
|
|
6
|
-
|
|
7
|
-
import pandas
|
|
8
6
|
import logging
|
|
7
|
+
import pandas
|
|
9
8
|
|
|
10
9
|
from .shell import BackupException, execute_shell_command
|
|
11
10
|
|
|
@@ -18,9 +17,7 @@ def get_instance(container: str, database_containers: list[str]) -> str:
|
|
|
18
17
|
return re.split(r"(_|-)(database|db|postgres)", container)[0]
|
|
19
18
|
|
|
20
19
|
|
|
21
|
-
def fallback_pg_dumpall(
|
|
22
|
-
container: str, username: str, password: str, out_file: str
|
|
23
|
-
) -> None:
|
|
20
|
+
def fallback_pg_dumpall(container: str, username: str, password: str, out_file: str) -> None:
|
|
24
21
|
cmd = (
|
|
25
22
|
f"PGPASSWORD={password} docker exec -i {container} "
|
|
26
23
|
f"pg_dumpall -U {username} -h localhost > {out_file}"
|
|
@@ -35,20 +32,25 @@ def backup_database(
|
|
|
35
32
|
db_type: str,
|
|
36
33
|
databases_df: "pandas.DataFrame",
|
|
37
34
|
database_containers: list[str],
|
|
38
|
-
) ->
|
|
35
|
+
) -> bool:
|
|
36
|
+
"""
|
|
37
|
+
Returns True if at least one dump file was produced, else False.
|
|
38
|
+
"""
|
|
39
39
|
instance_name = get_instance(container, database_containers)
|
|
40
40
|
entries = databases_df.loc[databases_df["instance"] == instance_name]
|
|
41
41
|
if entries.empty:
|
|
42
|
-
log.warning("No entry found for instance '%s'", instance_name)
|
|
43
|
-
return
|
|
42
|
+
log.warning("No entry found for instance '%s' (skipping DB dump)", instance_name)
|
|
43
|
+
return False
|
|
44
44
|
|
|
45
45
|
out_dir = os.path.join(volume_dir, "sql")
|
|
46
46
|
pathlib.Path(out_dir).mkdir(parents=True, exist_ok=True)
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
produced = False
|
|
49
|
+
|
|
50
|
+
for row in entries.itertuples(index=False):
|
|
51
|
+
db_name = row.database
|
|
52
|
+
user = row.username
|
|
53
|
+
password = row.password
|
|
52
54
|
|
|
53
55
|
dump_file = os.path.join(out_dir, f"{db_name}.backup.sql")
|
|
54
56
|
|
|
@@ -58,13 +60,15 @@ def backup_database(
|
|
|
58
60
|
f"-u {user} -p{password} {db_name} > {dump_file}"
|
|
59
61
|
)
|
|
60
62
|
execute_shell_command(cmd)
|
|
63
|
+
produced = True
|
|
61
64
|
continue
|
|
62
65
|
|
|
63
66
|
if db_type == "postgres":
|
|
64
67
|
cluster_file = os.path.join(out_dir, f"{instance_name}.cluster.backup.sql")
|
|
68
|
+
|
|
65
69
|
if not db_name:
|
|
66
70
|
fallback_pg_dumpall(container, user, password, cluster_file)
|
|
67
|
-
return
|
|
71
|
+
return True
|
|
68
72
|
|
|
69
73
|
try:
|
|
70
74
|
cmd = (
|
|
@@ -72,6 +76,7 @@ def backup_database(
|
|
|
72
76
|
f"pg_dump -U {user} -d {db_name} -h localhost > {dump_file}"
|
|
73
77
|
)
|
|
74
78
|
execute_shell_command(cmd)
|
|
79
|
+
produced = True
|
|
75
80
|
except BackupException as e:
|
|
76
81
|
print(f"pg_dump failed: {e}", flush=True)
|
|
77
82
|
print(
|
|
@@ -79,4 +84,7 @@ def backup_database(
|
|
|
79
84
|
flush=True,
|
|
80
85
|
)
|
|
81
86
|
fallback_pg_dumpall(container, user, password, cluster_file)
|
|
87
|
+
produced = True
|
|
82
88
|
continue
|
|
89
|
+
|
|
90
|
+
return produced
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/__init__.py
RENAMED
|
File without changes
|
{backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/backup/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/__init__.py
RENAMED
|
File without changes
|
{backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/__main__.py
RENAMED
|
File without changes
|
{backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/db/__init__.py
RENAMED
|
File without changes
|
{backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/db/mariadb.py
RENAMED
|
File without changes
|
{backup_docker_to_local-1.1.0 → backup_docker_to_local-1.1.1}/src/baudolo/restore/db/postgres.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|