mirror of
https://github.com/zulip/zulip.git
synced 2025-10-25 17:14:02 +00:00
backup: Use tar --transform to arrange the tarball instead of symlinks.
This allows tar to print the real paths in error messages if something goes wrong. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
This commit is contained in:
committed by
Tim Abbott
parent
abe645f1d3
commit
e074165c1b
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -56,13 +57,16 @@ if __name__ == "__main__":
|
|||||||
os.chown(path, uid, gid)
|
os.chown(path, uid, gid)
|
||||||
os.setresuid(uid, uid, 0)
|
os.setresuid(uid, uid, 0)
|
||||||
|
|
||||||
# We create symlinks so that we can do a single `tar -x`
|
assert not any("|" in name or "|" in path for name, path in paths)
|
||||||
# command to unpack the uploads, settings, etc. to their
|
transform_args = [
|
||||||
# appropriate places.
|
r"--transform=s|^zulip-backup/{}(/.*)?$|{}\1|x".format(
|
||||||
|
re.escape(name), path.replace("\\", r"\\")
|
||||||
|
)
|
||||||
|
for name, path in paths
|
||||||
|
]
|
||||||
|
|
||||||
os.mkdir(os.path.join(tmp, "zulip-backup"))
|
os.mkdir(os.path.join(tmp, "zulip-backup"))
|
||||||
for name, path in paths:
|
run(["tar", "-C", tmp] + transform_args + ["-xPzf", args.tarball])
|
||||||
os.symlink(path, os.path.join(tmp, "zulip-backup", name))
|
|
||||||
run(["tar", "-C", tmp, "--keep-directory-symlink", "-xzf", args.tarball])
|
|
||||||
|
|
||||||
# Now, restore the the database backup using pg_restore.
|
# Now, restore the the database backup using pg_restore.
|
||||||
db_name = settings.DATABASES["default"]["NAME"]
|
db_name = settings.DATABASES["default"]["NAME"]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import tempfile
|
import tempfile
|
||||||
from argparse import ArgumentParser, RawTextHelpFormatter
|
from argparse import ArgumentParser, RawTextHelpFormatter
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@@ -33,6 +34,7 @@ class Command(ZulipBaseCommand):
|
|||||||
) as tmp:
|
) as tmp:
|
||||||
os.mkdir(os.path.join(tmp, "zulip-backup"))
|
os.mkdir(os.path.join(tmp, "zulip-backup"))
|
||||||
members = []
|
members = []
|
||||||
|
paths = []
|
||||||
|
|
||||||
with open(os.path.join(tmp, "zulip-backup", "zulip-version"), "w") as f:
|
with open(os.path.join(tmp, "zulip-backup", "zulip-version"), "w") as f:
|
||||||
print(ZULIP_VERSION, file=f)
|
print(ZULIP_VERSION, file=f)
|
||||||
@@ -53,14 +55,15 @@ class Command(ZulipBaseCommand):
|
|||||||
members.append("zulip-backup/postgres-version")
|
members.append("zulip-backup/postgres-version")
|
||||||
|
|
||||||
if settings.DEVELOPMENT:
|
if settings.DEVELOPMENT:
|
||||||
os.symlink(
|
members.append(
|
||||||
os.path.join(settings.DEPLOY_ROOT, "zproject"),
|
os.path.join(settings.DEPLOY_ROOT, "zproject", "dev-secrets.conf")
|
||||||
os.path.join(tmp, "zulip-backup", "zproject"),
|
)
|
||||||
|
paths.append(
|
||||||
|
("zproject", os.path.join(settings.DEPLOY_ROOT, "zproject"))
|
||||||
)
|
)
|
||||||
members.append("zulip-backup/zproject/dev-secrets.conf")
|
|
||||||
else:
|
else:
|
||||||
os.symlink("/etc/zulip", os.path.join(tmp, "zulip-backup", "settings"))
|
members.append("/etc/zulip")
|
||||||
members.append("zulip-backup/settings")
|
paths.append(("settings", "/etc/zulip"))
|
||||||
|
|
||||||
db_name = settings.DATABASES["default"]["NAME"]
|
db_name = settings.DATABASES["default"]["NAME"]
|
||||||
db_dir = os.path.join(tmp, "zulip-backup", "database")
|
db_dir = os.path.join(tmp, "zulip-backup", "database")
|
||||||
@@ -73,11 +76,23 @@ class Command(ZulipBaseCommand):
|
|||||||
if settings.LOCAL_UPLOADS_DIR is not None and os.path.exists(
|
if settings.LOCAL_UPLOADS_DIR is not None and os.path.exists(
|
||||||
os.path.join(settings.DEPLOY_ROOT, settings.LOCAL_UPLOADS_DIR)
|
os.path.join(settings.DEPLOY_ROOT, settings.LOCAL_UPLOADS_DIR)
|
||||||
):
|
):
|
||||||
os.symlink(
|
members.append(
|
||||||
os.path.join(settings.DEPLOY_ROOT, settings.LOCAL_UPLOADS_DIR),
|
os.path.join(settings.DEPLOY_ROOT, settings.LOCAL_UPLOADS_DIR)
|
||||||
os.path.join(tmp, "zulip-backup", "uploads"),
|
|
||||||
)
|
)
|
||||||
members.append("zulip-backup/uploads")
|
paths.append(
|
||||||
|
(
|
||||||
|
"uploads",
|
||||||
|
os.path.join(settings.DEPLOY_ROOT, settings.LOCAL_UPLOADS_DIR),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not any("|" in name or "|" in path for name, path in paths)
|
||||||
|
transform_args = [
|
||||||
|
r"--transform=s|^{}(/.*)?$|zulip-backup/{}\1|x".format(
|
||||||
|
re.escape(path), name.replace("\\", r"\\")
|
||||||
|
)
|
||||||
|
for name, path in paths
|
||||||
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if options["output"] is None:
|
if options["output"] is None:
|
||||||
@@ -89,7 +104,12 @@ class Command(ZulipBaseCommand):
|
|||||||
else:
|
else:
|
||||||
tarball_path = options["output"]
|
tarball_path = options["output"]
|
||||||
|
|
||||||
run(["tar", "-C", tmp, "-chzf", tarball_path, "--"] + members)
|
run(
|
||||||
|
["tar", "-C", tmp, "-cPzf", tarball_path]
|
||||||
|
+ transform_args
|
||||||
|
+ ["--"]
|
||||||
|
+ members
|
||||||
|
)
|
||||||
print("Backup tarball written to %s" % (tarball_path,))
|
print("Backup tarball written to %s" % (tarball_path,))
|
||||||
except BaseException:
|
except BaseException:
|
||||||
if options["output"] is None:
|
if options["output"] is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user