collective.backup 1.0.0a1__py3-none-any.whl

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.
Files changed (33) hide show
  1. collective/backup/__init__.py +1 -0
  2. collective/backup/__main__.py +5 -0
  3. collective/backup/cli.py +115 -0
  4. collective/backup/config.py +5 -0
  5. collective/backup/copyblobs.py +1643 -0
  6. collective/backup/main.py +359 -0
  7. collective/backup/repozorunner.py +393 -0
  8. collective/backup/scripts.py +757 -0
  9. collective/backup/tests/__init__.py +1 -0
  10. collective/backup/tests/altrestore.rst +291 -0
  11. collective/backup/tests/backup_blobs_archive.rst +273 -0
  12. collective/backup/tests/backup_blobs_dir.rst +240 -0
  13. collective/backup/tests/backup_blobs_dir_hard_links.rst +256 -0
  14. collective/backup/tests/base.rst +158 -0
  15. collective/backup/tests/blob_timestamps.rst +361 -0
  16. collective/backup/tests/blobs.rst +619 -0
  17. collective/backup/tests/cleanup_archives.rst +186 -0
  18. collective/backup/tests/cleanup_dir.rst +147 -0
  19. collective/backup/tests/incremental_blobs.rst +192 -0
  20. collective/backup/tests/location.rst +67 -0
  21. collective/backup/tests/no_rsync.rst +150 -0
  22. collective/backup/tests/options.rst +142 -0
  23. collective/backup/tests/prefix.rst +316 -0
  24. collective/backup/tests/test_docs.py +196 -0
  25. collective/backup/tests/test_unit.py +827 -0
  26. collective/backup/tests/zipbackup.rst +132 -0
  27. collective/backup/utils.py +235 -0
  28. collective_backup-1.0.0a1.dist-info/METADATA +773 -0
  29. collective_backup-1.0.0a1.dist-info/RECORD +33 -0
  30. collective_backup-1.0.0a1.dist-info/WHEEL +5 -0
  31. collective_backup-1.0.0a1.dist-info/entry_points.txt +2 -0
  32. collective_backup-1.0.0a1.dist-info/licenses/LICENSE +339 -0
  33. collective_backup-1.0.0a1.dist-info/top_level.txt +1 -0
@@ -0,0 +1 @@
1
+ """Backup and restore scripts for Plone, around repozo."""
@@ -0,0 +1,5 @@
1
+ from collective.backup.cli import main
2
+
3
+ import sys
4
+
5
+ sys.exit(main())
@@ -0,0 +1,115 @@
1
+ """The collective-backup command."""
2
+
3
+ from collective.backup import scripts
4
+
5
+ import argparse
6
+ import logging
7
+ import os
8
+ import pprint
9
+ import shlex
10
+ import shutil
11
+ import sys
12
+
13
+
14
+ def main(argv=None):
15
+ parser = argparse.ArgumentParser(
16
+ prog="collective-backup",
17
+ description=(
18
+ "Backup and restore a Plone/Zope filestorage and blobstorage "
19
+ "with sensible defaults around repozo. Run one of the backup or "
20
+ "restore commands directly, or generate scripts for them. "
21
+ f"Configure it in the [tool.{scripts.PYPROJECT_TABLE}] table of "
22
+ f"pyproject.toml, or with {scripts.ENV_PREFIX}* variables in a "
23
+ ".env file or in the environment."
24
+ ),
25
+ )
26
+ parser.add_argument(
27
+ "-c",
28
+ "--config",
29
+ help=(
30
+ f"read the [tool.{scripts.PYPROJECT_TABLE}] table from this file, "
31
+ f"default: {scripts.PYPROJECT} in the current directory, if it has "
32
+ "this table. Relative paths are relative to its directory."
33
+ ),
34
+ )
35
+ parser.add_argument(
36
+ "-e",
37
+ "--env-file",
38
+ help=(
39
+ f"read {scripts.ENV_PREFIX}* variables from this file, "
40
+ f"default: {scripts.ENV_FILE} next to the configuration file, or in "
41
+ "the current directory. These variables win over the configuration "
42
+ "file, and variables in the environment win over both."
43
+ ),
44
+ )
45
+ subparsers = parser.add_subparsers(dest="command", required=True)
46
+ generate = subparsers.add_parser(
47
+ "generate", help="generate the backup and restore scripts"
48
+ )
49
+ generate.add_argument(
50
+ "--bin-dir",
51
+ help=f"directory for the scripts, default: {scripts.ENV_PREFIX}BIN_DIR or 'bin'",
52
+ )
53
+ subparsers.add_parser("show", help="show the computed options")
54
+ subparsers.add_parser(
55
+ "crontab",
56
+ help=(
57
+ "print a crontab using the cron option for backup and the "
58
+ "snapshot_cron option for snapshotbackup"
59
+ ),
60
+ )
61
+ for command, description in scripts.DESCRIPTIONS.items():
62
+ subparser = subparsers.add_parser(command, help=description)
63
+ scripts.add_script_arguments(subparser, command)
64
+ args = parser.parse_args(argv)
65
+ # Show warnings while computing the options.
66
+ logging.basicConfig(level=logging.INFO, format="%(name)s: %(message)s")
67
+
68
+ try:
69
+ config = scripts.Config(config=args.config, env_file=args.env_file)
70
+ if args.command == "crontab":
71
+ print(crontab(config, explicit=args), end="")
72
+ return 0
73
+ part = config.part()
74
+ if args.command == "generate":
75
+ scripts.generate(part, bin_dir=args.bin_dir)
76
+ return 0
77
+ if args.command == "show":
78
+ print(f"name = {part.name!r}")
79
+ print(f"scripts = {sorted(part.commands().values())!r}")
80
+ print(pprint.pformat(part.arguments))
81
+ return 0
82
+ if args.command not in part.commands():
83
+ raise scripts.ConfigError(f"The {args.command} command is not enabled.")
84
+ except scripts.ConfigError as exc:
85
+ print(f"Error: {exc}", file=sys.stderr)
86
+ return 1
87
+ return scripts.execute(args.command, part.arguments, args)
88
+
89
+
90
+ def crontab(config, explicit=None):
91
+ """Return a crontab for the scheduled backups.
92
+
93
+ We first change to the directory of the configuration,
94
+ so the job finds the same configuration and .env file.
95
+ Options that were given explicitly on the command line are passed on.
96
+ """
97
+ program = shutil.which("collective-backup") or os.path.join(
98
+ os.path.dirname(sys.executable), "collective-backup"
99
+ )
100
+ command = f"cd {shlex.quote(config.directory)} && {shlex.quote(program)}"
101
+ if explicit is not None and explicit.config:
102
+ command += f" --config {shlex.quote(config.config_path)}"
103
+ if explicit is not None and explicit.env_file:
104
+ command += f" --env-file {shlex.quote(config.env_file)}"
105
+ lines = []
106
+ for option, name in (("cron", "backup"), ("snapshot_cron", "snapshotbackup")):
107
+ schedule = config.options.get(option, "").strip()
108
+ if schedule:
109
+ lines.append(f"{schedule} {command} {name}\n")
110
+ if not lines:
111
+ raise scripts.ConfigError(
112
+ "Set the cron and/or snapshot_cron option to a cron schedule, "
113
+ f"for example {scripts.ENV_PREFIX}CRON='0 3 * * *'."
114
+ )
115
+ return "".join(lines)
@@ -0,0 +1,5 @@
1
+ # Backup methods.
2
+ STANDARD_BACKUP = 1
3
+ SNAPSHOT_BACKUP = 2
4
+ ZIP_BACKUP = 3
5
+ BACKUP_METHODS = [STANDARD_BACKUP, SNAPSHOT_BACKUP, ZIP_BACKUP]