Merge.
This commit is contained in:
commit
7458769cb3
8 changed files with 78 additions and 20 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
|
||||
|
|
|
@ -66,6 +66,12 @@ To install borgmatic, run the following command to download and install it:
|
|||
Note that your pip binary may have a different name than "pip3". Make sure
|
||||
you're using Python 3, as borgmatic does not support Python 2.
|
||||
|
||||
### Docker
|
||||
|
||||
If you would like to run borgmatic within Docker, please take a look at
|
||||
[b3vis/borgmatic](https://hub.docker.com/r/b3vis/borgmatic/) for more
|
||||
information.
|
||||
|
||||
## Configuration
|
||||
|
||||
After you install borgmatic, generate a sample configuration file:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
from argparse import ArgumentParser
|
||||
import logging
|
||||
import os
|
||||
|
@ -5,6 +6,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
|
||||
from borgmatic.verbosity import VERBOSITY_SOME, VERBOSITY_LOTS, verbosity_to_log_level
|
||||
|
||||
|
@ -92,13 +94,15 @@ def main(): # pragma: no cover
|
|||
for config_filename in config_filenames:
|
||||
logger.info('{}: Parsing configuration file'.format(config_filename))
|
||||
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')
|
||||
|
||||
try:
|
||||
create.initialize(storage)
|
||||
hook.execute_hook(hooks.get('before_backup'))
|
||||
|
||||
for repository in location['repositories']:
|
||||
if args.prune:
|
||||
|
@ -115,6 +119,11 @@ def main(): # pragma: no cover
|
|||
if args.check:
|
||||
logger.info('{}: Running consistency checks'.format(repository))
|
||||
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."
|
||||
|
|
|
@ -50,7 +50,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