Change the default action order to: "create", "prune", "compact", "check" (#304).
This commit is contained in:
parent
9db31bd1e9
commit
b343363bb8
7 changed files with 79 additions and 72 deletions
3
NEWS
3
NEWS
|
@ -1,5 +1,8 @@
|
||||||
1.7.9.dev0
|
1.7.9.dev0
|
||||||
* #295: Add a SQLite database dump/restore hook.
|
* #295: Add a SQLite database dump/restore hook.
|
||||||
|
* #304: Change the default action order when no actions are specified on the command-line to:
|
||||||
|
"create", "prune", "compact", "check". If you'd like to retain the old ordering ("prune" and
|
||||||
|
"compact" first), then specify actions explicitly on the command-line.
|
||||||
* #304: Run any command-line actions in the order specified instead of using a fixed ordering.
|
* #304: Run any command-line actions in the order specified instead of using a fixed ordering.
|
||||||
* #628: Add a Healthchecks "log" state to send borgmatic logs to Healthchecks without signalling
|
* #628: Add a Healthchecks "log" state to send borgmatic logs to Healthchecks without signalling
|
||||||
success or failure.
|
success or failure.
|
||||||
|
|
|
@ -68,9 +68,9 @@ def parse_subparser_arguments(unparsed_arguments, subparsers):
|
||||||
|
|
||||||
arguments[canonical_name] = parsed
|
arguments[canonical_name] = parsed
|
||||||
|
|
||||||
# If no actions are explicitly requested, assume defaults: prune, compact, create, and check.
|
# If no actions are explicitly requested, assume defaults.
|
||||||
if not arguments and '--help' not in unparsed_arguments and '-h' not in unparsed_arguments:
|
if not arguments and '--help' not in unparsed_arguments and '-h' not in unparsed_arguments:
|
||||||
for subparser_name in ('prune', 'compact', 'create', 'check'):
|
for subparser_name in ('create', 'prune', 'compact', 'check'):
|
||||||
subparser = subparsers[subparser_name]
|
subparser = subparsers[subparser_name]
|
||||||
parsed, unused_remaining = subparser.parse_known_args(unparsed_arguments)
|
parsed, unused_remaining = subparser.parse_known_args(unparsed_arguments)
|
||||||
arguments[subparser_name] = parsed
|
arguments[subparser_name] = parsed
|
||||||
|
@ -216,7 +216,7 @@ def make_parsers():
|
||||||
top_level_parser = ArgumentParser(
|
top_level_parser = ArgumentParser(
|
||||||
description='''
|
description='''
|
||||||
Simple, configuration-driven backup software for servers and workstations. If none of
|
Simple, configuration-driven backup software for servers and workstations. If none of
|
||||||
the action options are given, then borgmatic defaults to: prune, compact, create, and
|
the action options are given, then borgmatic defaults to: create, prune, compact, and
|
||||||
check.
|
check.
|
||||||
''',
|
''',
|
||||||
parents=[global_parser],
|
parents=[global_parser],
|
||||||
|
@ -225,7 +225,7 @@ def make_parsers():
|
||||||
subparsers = top_level_parser.add_subparsers(
|
subparsers = top_level_parser.add_subparsers(
|
||||||
title='actions',
|
title='actions',
|
||||||
metavar='',
|
metavar='',
|
||||||
help='Specify zero or more actions. Defaults to prune, compact, create, and check. Use --help with action for details:',
|
help='Specify zero or more actions. Defaults to creat, prune, compact, and check. Use --help with action for details:',
|
||||||
)
|
)
|
||||||
rcreate_parser = subparsers.add_parser(
|
rcreate_parser = subparsers.add_parser(
|
||||||
'rcreate',
|
'rcreate',
|
||||||
|
|
|
@ -44,8 +44,8 @@ LEGACY_CONFIG_PATH = '/etc/borgmatic/config'
|
||||||
def run_configuration(config_filename, config, arguments):
|
def run_configuration(config_filename, config, arguments):
|
||||||
'''
|
'''
|
||||||
Given a config filename, the corresponding parsed config dict, and command-line arguments as a
|
Given a config filename, the corresponding parsed config dict, and command-line arguments as a
|
||||||
dict from subparser name to a namespace of parsed arguments, execute the defined prune, compact,
|
dict from subparser name to a namespace of parsed arguments, execute the defined create, prune,
|
||||||
create, check, and/or other actions.
|
compact, check, and/or other actions.
|
||||||
|
|
||||||
Yield a combination of:
|
Yield a combination of:
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ def run_configuration(config_filename, config, arguments):
|
||||||
retry_wait = storage.get('retry_wait', 0)
|
retry_wait = storage.get('retry_wait', 0)
|
||||||
encountered_error = None
|
encountered_error = None
|
||||||
error_repository = ''
|
error_repository = ''
|
||||||
using_primary_action = {'prune', 'compact', 'create', 'check'}.intersection(arguments)
|
using_primary_action = {'create', 'prune', 'compact', 'check'}.intersection(arguments)
|
||||||
monitoring_log_level = verbosity_to_log_level(global_arguments.monitoring_verbosity)
|
monitoring_log_level = verbosity_to_log_level(global_arguments.monitoring_verbosity)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -302,6 +302,21 @@ def run_actions(
|
||||||
local_path,
|
local_path,
|
||||||
remote_path,
|
remote_path,
|
||||||
)
|
)
|
||||||
|
elif action_name == 'create':
|
||||||
|
yield from borgmatic.actions.create.run_create(
|
||||||
|
config_filename,
|
||||||
|
repository,
|
||||||
|
location,
|
||||||
|
storage,
|
||||||
|
hooks,
|
||||||
|
hook_context,
|
||||||
|
local_borg_version,
|
||||||
|
action_arguments,
|
||||||
|
global_arguments,
|
||||||
|
dry_run_label,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
|
)
|
||||||
elif action_name == 'prune':
|
elif action_name == 'prune':
|
||||||
borgmatic.actions.prune.run_prune(
|
borgmatic.actions.prune.run_prune(
|
||||||
config_filename,
|
config_filename,
|
||||||
|
@ -332,21 +347,6 @@ def run_actions(
|
||||||
local_path,
|
local_path,
|
||||||
remote_path,
|
remote_path,
|
||||||
)
|
)
|
||||||
elif action_name == 'create':
|
|
||||||
yield from borgmatic.actions.create.run_create(
|
|
||||||
config_filename,
|
|
||||||
repository,
|
|
||||||
location,
|
|
||||||
storage,
|
|
||||||
hooks,
|
|
||||||
hook_context,
|
|
||||||
local_borg_version,
|
|
||||||
action_arguments,
|
|
||||||
global_arguments,
|
|
||||||
dry_run_label,
|
|
||||||
local_path,
|
|
||||||
remote_path,
|
|
||||||
)
|
|
||||||
elif action_name == 'check':
|
elif action_name == 'check':
|
||||||
if checks.repository_enabled_for_checks(repository, consistency):
|
if checks.repository_enabled_for_checks(repository, consistency):
|
||||||
borgmatic.actions.check.run_check(
|
borgmatic.actions.check.run_check(
|
||||||
|
|
|
@ -369,6 +369,11 @@ properties:
|
||||||
description: |
|
description: |
|
||||||
Extra command-line options to pass to "borg init".
|
Extra command-line options to pass to "borg init".
|
||||||
example: "--extra-option"
|
example: "--extra-option"
|
||||||
|
create:
|
||||||
|
type: string
|
||||||
|
description: |
|
||||||
|
Extra command-line options to pass to "borg create".
|
||||||
|
example: "--extra-option"
|
||||||
prune:
|
prune:
|
||||||
type: string
|
type: string
|
||||||
description: |
|
description: |
|
||||||
|
@ -379,11 +384,6 @@ properties:
|
||||||
description: |
|
description: |
|
||||||
Extra command-line options to pass to "borg compact".
|
Extra command-line options to pass to "borg compact".
|
||||||
example: "--extra-option"
|
example: "--extra-option"
|
||||||
create:
|
|
||||||
type: string
|
|
||||||
description: |
|
|
||||||
Extra command-line options to pass to "borg create".
|
|
||||||
example: "--extra-option"
|
|
||||||
check:
|
check:
|
||||||
type: string
|
type: string
|
||||||
description: |
|
description: |
|
||||||
|
@ -663,11 +663,11 @@ properties:
|
||||||
type: string
|
type: string
|
||||||
description: |
|
description: |
|
||||||
List of one or more shell commands or scripts to execute
|
List of one or more shell commands or scripts to execute
|
||||||
when an exception occurs during a "prune", "compact",
|
when an exception occurs during a "create", "prune",
|
||||||
"create", or "check" action or an associated before/after
|
"compact", or "check" action or an associated before/after
|
||||||
hook.
|
hook.
|
||||||
example:
|
example:
|
||||||
- echo "Error during prune/compact/create/check."
|
- echo "Error during create/prune/compact/check."
|
||||||
before_everything:
|
before_everything:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
|
|
@ -9,28 +9,32 @@ eleventyNavigation:
|
||||||
|
|
||||||
Borg itself is great for efficiently de-duplicating data across successive
|
Borg itself is great for efficiently de-duplicating data across successive
|
||||||
backup archives, even when dealing with very large repositories. But you may
|
backup archives, even when dealing with very large repositories. But you may
|
||||||
find that while borgmatic's default mode of `prune`, `compact`, `create`, and
|
find that while borgmatic's default actions of `create`, `prune`, `compact`,
|
||||||
`check` works well on small repositories, it's not so great on larger ones.
|
and `check` works well on small repositories, it's not so great on larger
|
||||||
That's because running the default pruning, compact, and consistency checks
|
ones. That's because running the default pruning, compact, and consistency
|
||||||
take a long time on large repositories.
|
checks take a long time on large repositories.
|
||||||
|
|
||||||
|
<span class="minilink minilink-addedin">Prior to version 1.7.9</span> The
|
||||||
|
default action ordering was `prune`, `compact`, `create`, and `check`.
|
||||||
|
|
||||||
### A la carte actions
|
### A la carte actions
|
||||||
|
|
||||||
If you find yourself in this situation, you have some options. First, you can
|
If you find yourself wanting to customize the actions, you have some options.
|
||||||
run borgmatic's `prune`, `compact`, `create`, or `check` actions separately.
|
First, you can run borgmatic's `prune`, `compact`, `create`, or `check`
|
||||||
For instance, the following optional actions are available:
|
actions separately. For instance, the following optional actions are
|
||||||
|
available (among others):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
borgmatic create
|
||||||
borgmatic prune
|
borgmatic prune
|
||||||
borgmatic compact
|
borgmatic compact
|
||||||
borgmatic create
|
|
||||||
borgmatic check
|
borgmatic check
|
||||||
```
|
```
|
||||||
|
|
||||||
You can run with only one of these actions provided, or you can mix and match
|
You can run borgmatic with only one of these actions provided, or you can mix
|
||||||
any number of them in a single borgmatic run. This supports approaches like
|
and match any number of them in a single borgmatic run. This supports
|
||||||
skipping certain actions while running others. For instance, this skips
|
approaches like skipping certain actions while running others. For instance,
|
||||||
`prune` and `compact` and only runs `create` and `check`:
|
this skips `prune` and `compact` and only runs `create` and `check`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
borgmatic create check
|
borgmatic create check
|
||||||
|
|
|
@ -83,7 +83,7 @@ tests](https://torsion.org/borgmatic/docs/how-to/extract-a-backup/).
|
||||||
|
|
||||||
## Error hooks
|
## Error hooks
|
||||||
|
|
||||||
When an error occurs during a `prune`, `compact`, `create`, or `check` action,
|
When an error occurs during a `create`, `prune`, `compact`, or `check` action,
|
||||||
borgmatic can run configurable shell commands to fire off custom error
|
borgmatic can run configurable shell commands to fire off custom error
|
||||||
notifications or take other actions, so you can get alerted as soon as
|
notifications or take other actions, so you can get alerted as soon as
|
||||||
something goes wrong. Here's a not-so-useful example:
|
something goes wrong. Here's a not-so-useful example:
|
||||||
|
@ -116,8 +116,8 @@ the repository. Here's the full set of supported variables you can use here:
|
||||||
* `output`: output of the command that failed (may be blank if an error
|
* `output`: output of the command that failed (may be blank if an error
|
||||||
occurred without running a command)
|
occurred without running a command)
|
||||||
|
|
||||||
Note that borgmatic runs the `on_error` hooks only for `prune`, `compact`,
|
Note that borgmatic runs the `on_error` hooks only for `create`, `prune`,
|
||||||
`create`, or `check` actions or hooks in which an error occurs, and not other
|
`compact`, or `check` actions or hooks in which an error occurs, and not other
|
||||||
actions. borgmatic does not run `on_error` hooks if an error occurs within a
|
actions. borgmatic does not run `on_error` hooks if an error occurs within a
|
||||||
`before_everything` or `after_everything` hook. For more about hooks, see the
|
`before_everything` or `after_everything` hook. For more about hooks, see the
|
||||||
[borgmatic hooks
|
[borgmatic hooks
|
||||||
|
@ -144,7 +144,7 @@ With this hook in place, borgmatic pings your Healthchecks project when a
|
||||||
backup begins, ends, or errors. Specifically, after the <a
|
backup begins, ends, or errors. Specifically, after the <a
|
||||||
href="https://torsion.org/borgmatic/docs/how-to/add-preparation-and-cleanup-steps-to-backups/">`before_backup`
|
href="https://torsion.org/borgmatic/docs/how-to/add-preparation-and-cleanup-steps-to-backups/">`before_backup`
|
||||||
hooks</a> run, borgmatic lets Healthchecks know that it has started if any of
|
hooks</a> run, borgmatic lets Healthchecks know that it has started if any of
|
||||||
the `prune`, `compact`, `create`, or `check` actions are run.
|
the `create`, `prune`, `compact`, or `check` actions are run.
|
||||||
|
|
||||||
Then, if the actions complete successfully, borgmatic notifies Healthchecks of
|
Then, if the actions complete successfully, borgmatic notifies Healthchecks of
|
||||||
the success after the `after_backup` hooks run, and includes borgmatic logs in
|
the success after the `after_backup` hooks run, and includes borgmatic logs in
|
||||||
|
@ -154,8 +154,8 @@ in the Healthchecks UI, although be aware that Healthchecks currently has a
|
||||||
|
|
||||||
If an error occurs during any action or hook, borgmatic notifies Healthchecks
|
If an error occurs during any action or hook, borgmatic notifies Healthchecks
|
||||||
after the `on_error` hooks run, also tacking on logs including the error
|
after the `on_error` hooks run, also tacking on logs including the error
|
||||||
itself. But the logs are only included for errors that occur when a `prune`,
|
itself. But the logs are only included for errors that occur when a `create`,
|
||||||
`compact`, `create`, or `check` action is run.
|
`prune`, `compact`, or `check` action is run.
|
||||||
|
|
||||||
You can customize the verbosity of the logs that are sent to Healthchecks with
|
You can customize the verbosity of the logs that are sent to Healthchecks with
|
||||||
borgmatic's `--monitoring-verbosity` flag. The `--list` and `--stats` flags
|
borgmatic's `--monitoring-verbosity` flag. The `--list` and `--stats` flags
|
||||||
|
|
|
@ -436,6 +436,30 @@ def test_run_actions_runs_transfer():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_actions_runs_create():
|
||||||
|
flexmock(module).should_receive('add_custom_log_levels')
|
||||||
|
flexmock(module.command).should_receive('execute_hook')
|
||||||
|
expected = flexmock()
|
||||||
|
flexmock(borgmatic.actions.create).should_receive('run_create').and_yield(expected).once()
|
||||||
|
|
||||||
|
result = tuple(
|
||||||
|
module.run_actions(
|
||||||
|
arguments={'global': flexmock(dry_run=False), 'create': flexmock()},
|
||||||
|
config_filename=flexmock(),
|
||||||
|
location={'repositories': []},
|
||||||
|
storage=flexmock(),
|
||||||
|
retention=flexmock(),
|
||||||
|
consistency=flexmock(),
|
||||||
|
hooks={},
|
||||||
|
local_path=flexmock(),
|
||||||
|
remote_path=flexmock(),
|
||||||
|
local_borg_version=flexmock(),
|
||||||
|
repository_path='repo',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assert result == (expected,)
|
||||||
|
|
||||||
|
|
||||||
def test_run_actions_runs_prune():
|
def test_run_actions_runs_prune():
|
||||||
flexmock(module).should_receive('add_custom_log_levels')
|
flexmock(module).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.command).should_receive('execute_hook')
|
flexmock(module.command).should_receive('execute_hook')
|
||||||
|
@ -480,30 +504,6 @@ def test_run_actions_runs_compact():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_actions_runs_create():
|
|
||||||
flexmock(module).should_receive('add_custom_log_levels')
|
|
||||||
flexmock(module.command).should_receive('execute_hook')
|
|
||||||
expected = flexmock()
|
|
||||||
flexmock(borgmatic.actions.create).should_receive('run_create').and_yield(expected).once()
|
|
||||||
|
|
||||||
result = tuple(
|
|
||||||
module.run_actions(
|
|
||||||
arguments={'global': flexmock(dry_run=False), 'create': flexmock()},
|
|
||||||
config_filename=flexmock(),
|
|
||||||
location={'repositories': []},
|
|
||||||
storage=flexmock(),
|
|
||||||
retention=flexmock(),
|
|
||||||
consistency=flexmock(),
|
|
||||||
hooks={},
|
|
||||||
local_path=flexmock(),
|
|
||||||
remote_path=flexmock(),
|
|
||||||
local_borg_version=flexmock(),
|
|
||||||
repository_path='repo',
|
|
||||||
)
|
|
||||||
)
|
|
||||||
assert result == (expected,)
|
|
||||||
|
|
||||||
|
|
||||||
def test_run_actions_runs_check_when_repository_enabled_for_checks():
|
def test_run_actions_runs_check_when_repository_enabled_for_checks():
|
||||||
flexmock(module).should_receive('add_custom_log_levels')
|
flexmock(module).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.command).should_receive('execute_hook')
|
flexmock(module.command).should_receive('execute_hook')
|
||||||
|
|
Loading…
Reference in a new issue