This commit is contained in:
parent
86511deac4
commit
f1a98d82c6
7 changed files with 68 additions and 17 deletions
1
AUTHORS
1
AUTHORS
|
@ -5,3 +5,4 @@ Henning Schroeder: Copy editing
|
|||
Michele Lazzeri: Custom archive names
|
||||
Robin `ypid` Schneider: Support additional options of Borg
|
||||
Scott Squires: Custom archive names
|
||||
Johannes Feichtner: Support for user hooks
|
||||
|
|
|
@ -5,6 +5,7 @@ from subprocess import CalledProcessError
|
|||
import sys
|
||||
|
||||
from borgmatic.borg import check, create, prune
|
||||
from borgmatic.commands import hook
|
||||
from borgmatic.config import collect, convert, validate
|
||||
|
||||
|
||||
|
@ -84,26 +85,33 @@ def main(): # pragma: no cover
|
|||
|
||||
for config_filename in config_filenames:
|
||||
config = validate.parse_configuration(config_filename, validate.schema_filename())
|
||||
(location, storage, retention, consistency) = (
|
||||
(location, storage, retention, consistency, hooks) = (
|
||||
config.get(section_name, {})
|
||||
for section_name in ('location', 'storage', 'retention', 'consistency')
|
||||
for section_name in ('location', 'storage', 'retention', 'consistency', 'hooks')
|
||||
)
|
||||
remote_path = location.get('remote_path')
|
||||
|
||||
create.initialize(storage)
|
||||
try:
|
||||
create.initialize(storage)
|
||||
hook.execute_hook(hooks.get('before_backup'))
|
||||
|
||||
for repository in location['repositories']:
|
||||
if args.prune:
|
||||
prune.prune_archives(args.verbosity, repository, retention, remote_path=remote_path)
|
||||
if args.create:
|
||||
create.create_archive(
|
||||
args.verbosity,
|
||||
repository,
|
||||
location,
|
||||
storage,
|
||||
)
|
||||
if args.check:
|
||||
check.check_archives(args.verbosity, repository, consistency, remote_path=remote_path)
|
||||
for repository in location['repositories']:
|
||||
if args.prune:
|
||||
prune.prune_archives(args.verbosity, repository, retention, remote_path=remote_path)
|
||||
if args.create:
|
||||
create.create_archive(
|
||||
args.verbosity,
|
||||
repository,
|
||||
location,
|
||||
storage,
|
||||
)
|
||||
if args.check:
|
||||
check.check_archives(args.verbosity, repository, consistency, remote_path=remote_path)
|
||||
|
||||
hook.execute_hook(hooks.get('after_backup'))
|
||||
except (OSError, CalledProcessError):
|
||||
hook.execute_hook(hooks.get('on_error'))
|
||||
raise
|
||||
except (ValueError, OSError, CalledProcessError) as error:
|
||||
print(error, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
|
7
borgmatic/commands/hook.py
Normal file
7
borgmatic/commands/hook.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
import subprocess
|
||||
|
||||
|
||||
def execute_hook(commands):
|
||||
if commands:
|
||||
for cmd in commands:
|
||||
subprocess.check_call(cmd, shell=True)
|
|
@ -24,7 +24,7 @@ def _schema_to_sample_configuration(schema, level=0):
|
|||
for each section based on the schema "desc" description.
|
||||
'''
|
||||
example = schema.get('example')
|
||||
if example:
|
||||
if example is not None:
|
||||
return example
|
||||
|
||||
config = yaml.comments.CommentedMap([
|
||||
|
|
|
@ -157,3 +157,28 @@ map:
|
|||
desc: Restrict the number of checked archives to the last n. Applies only to the
|
||||
"archives" check.
|
||||
example: 3
|
||||
hooks:
|
||||
desc: |
|
||||
Shell commands or scripts to execute before and after a backup or if an error has occurred.
|
||||
IMPORTANT: All provided commands and scripts are executed with user permissions of borgmatic.
|
||||
Do not forget to set secure permissions on this file as well as on any script listed (chmod 0700) to
|
||||
prevent potential shell injection or privilege escalation.
|
||||
map:
|
||||
before_backup:
|
||||
seq:
|
||||
- type: scalar
|
||||
desc: List of one or more shell commands or scripts to execute before creating a backup.
|
||||
example:
|
||||
- echo "`date` - Starting a backup job."
|
||||
after_backup:
|
||||
seq:
|
||||
- type: scalar
|
||||
desc: List of one or more shell commands or scripts to execute after creating a backup.
|
||||
example:
|
||||
- echo "`date` - Backup created."
|
||||
on_error:
|
||||
seq:
|
||||
- type: scalar
|
||||
desc: List of one or more shell commands or scripts to execute in case an exception has occurred.
|
||||
example:
|
||||
- echo "`date` - Error while creating a backup."
|
||||
|
|
|
@ -48,7 +48,7 @@ def parse_configuration(config_filename, schema_filename):
|
|||
# simply remove all examples before passing the schema to pykwalify.
|
||||
for section_name, section_schema in schema['map'].items():
|
||||
for field_name, field_schema in section_schema['map'].items():
|
||||
field_schema.pop('example')
|
||||
field_schema.pop('example', None)
|
||||
|
||||
validator = pykwalify.core.Core(source_data=config, schema_data=schema)
|
||||
parsed_result = validator.validate(raise_exception=False)
|
||||
|
|
10
borgmatic/tests/unit/borg/test_hook.py
Normal file
10
borgmatic/tests/unit/borg/test_hook.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.commands import hook as module
|
||||
|
||||
|
||||
def test_execute_hook_invokes_each_command():
|
||||
subprocess = flexmock(module.subprocess)
|
||||
subprocess.should_receive('check_call').with_args(':', shell=True).once()
|
||||
|
||||
module.execute_hook([':'])
|
Loading…
Reference in a new issue