Update Healthchecks/Cronitor/Cronhub monitoring integrations to fire for "check" and "prune" actions, not just "create" (#249).

This commit is contained in:
Dan Helfman 2019-12-12 22:54:45 -08:00
parent f1358d52aa
commit e009bfeaa2
4 changed files with 87 additions and 46 deletions

2
NEWS
View file

@ -1,5 +1,7 @@
1.4.20 1.4.20
* Fix repository probing during "borgmatic init" to respect verbosity flag and remote_path option. * Fix repository probing during "borgmatic init" to respect verbosity flag and remote_path option.
* #249: Update Healthchecks/Cronitor/Cronhub monitoring integrations to fire for "check" and
"prune" actions, not just "create".
1.4.19 1.4.19
* #259: Optionally change the internal database dump path via "borgmatic_source_directory" option * #259: Optionally change the internal database dump path via "borgmatic_source_directory" option

View file

@ -53,8 +53,8 @@ def run_configuration(config_filename, config, arguments):
encountered_error = None encountered_error = None
error_repository = '' error_repository = ''
if 'create' in arguments: try:
try: if {'prune', 'create', 'check'}.intersection(arguments):
dispatch.call_hooks( dispatch.call_hooks(
'ping_monitor', 'ping_monitor',
hooks, hooks,
@ -63,6 +63,7 @@ def run_configuration(config_filename, config, arguments):
monitor.State.START, monitor.State.START,
global_arguments.dry_run, global_arguments.dry_run,
) )
if 'create' in arguments:
command.execute_hook( command.execute_hook(
hooks.get('before_backup'), hooks.get('before_backup'),
hooks.get('umask'), hooks.get('umask'),
@ -78,11 +79,11 @@ def run_configuration(config_filename, config, arguments):
location, location,
global_arguments.dry_run, global_arguments.dry_run,
) )
except (OSError, CalledProcessError) as error: except (OSError, CalledProcessError) as error:
encountered_error = error encountered_error = error
yield from make_error_log_records( yield from make_error_log_records(
'{}: Error running pre-backup hook'.format(config_filename), error '{}: Error running pre-backup hook'.format(config_filename), error
) )
if not encountered_error: if not encountered_error:
for repository_path in location['repositories']: for repository_path in location['repositories']:
@ -105,31 +106,33 @@ def run_configuration(config_filename, config, arguments):
'{}: Error running actions for repository'.format(repository_path), error '{}: Error running actions for repository'.format(repository_path), error
) )
if 'create' in arguments and not encountered_error: if not encountered_error:
try: try:
dispatch.call_hooks( if 'create' in arguments:
'remove_database_dumps', dispatch.call_hooks(
hooks, 'remove_database_dumps',
config_filename, hooks,
dump.DATABASE_HOOK_NAMES, config_filename,
location, dump.DATABASE_HOOK_NAMES,
global_arguments.dry_run, location,
) global_arguments.dry_run,
command.execute_hook( )
hooks.get('after_backup'), command.execute_hook(
hooks.get('umask'), hooks.get('after_backup'),
config_filename, hooks.get('umask'),
'post-backup', config_filename,
global_arguments.dry_run, 'post-backup',
) global_arguments.dry_run,
dispatch.call_hooks( )
'ping_monitor', if {'prune', 'create', 'check'}.intersection(arguments):
hooks, dispatch.call_hooks(
config_filename, 'ping_monitor',
monitor.MONITOR_HOOK_NAMES, hooks,
monitor.State.FINISH, config_filename,
global_arguments.dry_run, monitor.MONITOR_HOOK_NAMES,
) monitor.State.FINISH,
global_arguments.dry_run,
)
except (OSError, CalledProcessError) as error: except (OSError, CalledProcessError) as error:
encountered_error = error encountered_error = error
yield from make_error_log_records( yield from make_error_log_records(

View file

@ -116,21 +116,22 @@ hooks:
With this hook in place, borgmatic pings your Healthchecks project when a With this hook in place, borgmatic pings your Healthchecks project when a
backup begins, ends, or errors. Specifically, before the <a backup begins, ends, or errors. Specifically, before 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 a backup has started. hooks</a> run, borgmatic lets Healthchecks know that it has started if any of
the `prune`, `create`, or `check` actions are run.
Then, if the backup completes 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
the payload data sent to Healthchecks. This means that borgmatic logs show up the payload data sent to Healthchecks. This means that borgmatic logs show up
in the Healthchecks UI, although be aware that Healthchecks currently has a in the Healthchecks UI, although be aware that Healthchecks currently has a
10-kilobyte limit for the logs in each ping. 10-kilobyte limit for the logs in each ping.
If an error occurs during the backup, borgmatic notifies Healthchecks after If an error occurs during any action, borgmatic notifies Healthchecks after
the `on_error` hooks run, also tacking on logs including the error itself. But the `on_error` hooks run, also tacking on logs including the error itself. But
the logs are only included for errors that occur within the borgmatic `create` the logs are only included for errors that occur when a `prune`, `create`, or
action (and not other actions). `check` action is run.
Note that borgmatic sends logs to Healthchecks by applying the maximum of any Note that borgmatic sends logs to Healthchecks by applying the maximum of any
other borgmatic verbosity level (`--verbosity`, `--syslog-verbosity`, etc.), other borgmatic verbosity levels (`--verbosity`, `--syslog-verbosity`, etc.),
as there is not currently a dedicated Healthchecks verbosity setting. as there is not currently a dedicated Healthchecks verbosity setting.
You can configure Healthchecks to notify you by a [variety of You can configure Healthchecks to notify you by a [variety of
@ -155,10 +156,11 @@ hooks:
With this hook in place, borgmatic pings your Cronitor monitor when a backup With this hook in place, borgmatic pings your Cronitor monitor when a backup
begins, ends, or errors. Specifically, before the <a begins, ends, or errors. Specifically, before 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 Cronitor know that a backup has started. Then, hooks</a> run, borgmatic lets Cronitor know that it has started if any of the
if the backup completes successfully, borgmatic notifies Cronitor of the `prune`, `create`, or `check` actions are run. Then, if the actions complete
success after the `after_backup` hooks run. And if an error occurs during the successfully, borgmatic notifies Cronitor of the success after the
backup, borgmatic notifies Cronitor after the `on_error` hooks run. `after_backup` hooks run. And if an error occurs during any action, borgmatic
notifies Cronitor after the `on_error` hooks run.
You can configure Cronitor to notify you by a [variety of You can configure Cronitor to notify you by a [variety of
mechanisms](https://cronitor.io/docs/cron-job-notifications) when backups fail mechanisms](https://cronitor.io/docs/cron-job-notifications) when backups fail
@ -182,10 +184,11 @@ hooks:
With this hook in place, borgmatic pings your Cronhub monitor when a backup With this hook in place, borgmatic pings your Cronhub monitor when a backup
begins, ends, or errors. Specifically, before the <a begins, ends, or errors. Specifically, before 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 Cronhub know that a backup has started. Then, hooks</a> run, borgmatic lets Cronhub know that it has started if any of the
if the backup completes successfully, borgmatic notifies Cronhub of the `prune`, `create`, or `check` actions are run. Then, if the actions complete
success after the `after_backup` hooks run. And if an error occurs during the successfully, borgmatic notifies Cronhub of the success after the
backup, borgmatic notifies Cronhub after the `on_error` hooks run. `after_backup` hooks run. And if an error occurs during any action, borgmatic
notifies Cronhub after the `on_error` hooks run.
Note that even though you configure borgmatic with the "start" variant of the Note that even though you configure borgmatic with the "start" variant of the
ping URL, borgmatic substitutes the correct state into the URL when pinging ping URL, borgmatic substitutes the correct state into the URL when pinging

View file

@ -20,7 +20,18 @@ def test_run_configuration_runs_actions_for_each_repository():
assert results == expected_results assert results == expected_results
def test_run_configuration_executes_hooks_for_create_action(): def test_run_configuration_calls_hooks_for_prune_action():
flexmock(module.borg_environment).should_receive('initialize')
flexmock(module.command).should_receive('execute_hook').never()
flexmock(module.dispatch).should_receive('call_hooks').at_least().twice()
flexmock(module).should_receive('run_actions').and_return([])
config = {'location': {'repositories': ['foo']}}
arguments = {'global': flexmock(dry_run=False), 'prune': flexmock()}
list(module.run_configuration('test.yaml', config, arguments))
def test_run_configuration_executes_and_calls_hooks_for_create_action():
flexmock(module.borg_environment).should_receive('initialize') flexmock(module.borg_environment).should_receive('initialize')
flexmock(module.command).should_receive('execute_hook').twice() flexmock(module.command).should_receive('execute_hook').twice()
flexmock(module.dispatch).should_receive('call_hooks').at_least().twice() flexmock(module.dispatch).should_receive('call_hooks').at_least().twice()
@ -31,6 +42,28 @@ def test_run_configuration_executes_hooks_for_create_action():
list(module.run_configuration('test.yaml', config, arguments)) list(module.run_configuration('test.yaml', config, arguments))
def test_run_configuration_calls_hooks_for_check_action():
flexmock(module.borg_environment).should_receive('initialize')
flexmock(module.command).should_receive('execute_hook').never()
flexmock(module.dispatch).should_receive('call_hooks').at_least().twice()
flexmock(module).should_receive('run_actions').and_return([])
config = {'location': {'repositories': ['foo']}}
arguments = {'global': flexmock(dry_run=False), 'check': flexmock()}
list(module.run_configuration('test.yaml', config, arguments))
def test_run_configuration_does_not_trigger_hooks_for_list_action():
flexmock(module.borg_environment).should_receive('initialize')
flexmock(module.command).should_receive('execute_hook').never()
flexmock(module.dispatch).should_receive('call_hooks').never()
flexmock(module).should_receive('run_actions').and_return([])
config = {'location': {'repositories': ['foo']}}
arguments = {'global': flexmock(dry_run=False), 'list': flexmock()}
list(module.run_configuration('test.yaml', config, arguments))
def test_run_configuration_logs_actions_error(): def test_run_configuration_logs_actions_error():
flexmock(module.borg_environment).should_receive('initialize') flexmock(module.borg_environment).should_receive('initialize')
flexmock(module.command).should_receive('execute_hook') flexmock(module.command).should_receive('execute_hook')