From 2e4c0cc7e72a5521b76fb459e41f01f85a6ec1ba Mon Sep 17 00:00:00 2001 From: estebanthi Date: Fri, 19 Apr 2024 10:36:40 +0200 Subject: [PATCH] Support for healthchecks auto provisionning --- borgmatic/config/schema.yaml | 7 ++++ borgmatic/hooks/healthchecks.py | 6 ++++ tests/unit/hooks/test_healthchecks.py | 52 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/borgmatic/config/schema.yaml b/borgmatic/config/schema.yaml index dacc410..7ca317a 100644 --- a/borgmatic/config/schema.yaml +++ b/borgmatic/config/schema.yaml @@ -1662,6 +1662,13 @@ properties: states. example: - finish + create_slug: + type: boolean + description: | + Create the check if it does not exist. Only works with + the slug URL scheme (https://hc-ping.com// + as opposed to https://hc-ping.com/). Defaults to false. + example: true description: | Configuration for a monitoring integration with Healthchecks. Create an account at https://healthchecks.io (or self-host Healthchecks) if diff --git a/borgmatic/hooks/healthchecks.py b/borgmatic/hooks/healthchecks.py index 8c63f21..c36143d 100644 --- a/borgmatic/hooks/healthchecks.py +++ b/borgmatic/hooks/healthchecks.py @@ -1,4 +1,5 @@ import logging +import re import requests @@ -59,10 +60,15 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev ) return + ping_url_is_uuid = re.match(r'(\w{4}-?){4}$', hook_config['ping_url']) + healthchecks_state = MONITOR_STATE_TO_HEALTHCHECKS.get(state) if healthchecks_state: ping_url = f'{ping_url}/{healthchecks_state}' + if hook_config.get('create_slug') and not ping_url_is_uuid: + ping_url = f'{ping_url}?create=1' + logger.info(f'{config_filename}: Pinging Healthchecks {state.name.lower()}{dry_run_label}') logger.debug(f'{config_filename}: Using Healthchecks ping URL {ping_url}') diff --git a/tests/unit/hooks/test_healthchecks.py b/tests/unit/hooks/test_healthchecks.py index 479b0e3..f53c0f5 100644 --- a/tests/unit/hooks/test_healthchecks.py +++ b/tests/unit/hooks/test_healthchecks.py @@ -264,6 +264,58 @@ def test_ping_monitor_hits_ping_url_when_states_matching(): ) +def test_ping_monitor_adds_create_query_parameter_when_create_slug_true(): + flexmock(module.borgmatic.hooks.logs).should_receive('Forgetful_buffering_handler').never() + hook_config = {'ping_url': 'https://example.com', 'create_slug': True} + flexmock(module.requests).should_receive('post').with_args( + 'https://example.com/start?create=1', data=''.encode('utf-8'), verify=True + ).and_return(flexmock(ok=True)) + + module.ping_monitor( + hook_config, + {}, + 'config.yaml', + state=module.monitor.State.START, + monitoring_log_level=1, + dry_run=False, + ) + + +def test_ping_monitor_does_not_add_create_query_parameter_when_create_slug_false(): + flexmock(module.borgmatic.hooks.logs).should_receive('Forgetful_buffering_handler').never() + hook_config = {'ping_url': 'https://example.com', 'create_slug': False} + flexmock(module.requests).should_receive('post').with_args( + 'https://example.com/start', data=''.encode('utf-8'), verify=True + ).and_return(flexmock(ok=True)) + + module.ping_monitor( + hook_config, + {}, + 'config.yaml', + state=module.monitor.State.START, + monitoring_log_level=1, + dry_run=False, + ) + + +def test_ping_monitor_does_not_add_create_query_parameter_when_ping_url_is_uuid(): + hook_config = {'ping_url': 'abcd-efgh-ijkl-mnop', 'create_slug': True} + flexmock(module.requests).should_receive('post').with_args( + f"https://hc-ping.com/{hook_config['ping_url']}", + data=''.encode('utf-8'), + verify=True, + ).and_return(flexmock(ok=True)) + + module.ping_monitor( + hook_config, + {}, + 'config.yaml', + state=module.monitor.State.FINISH, + monitoring_log_level=1, + dry_run=False, + ) + + def test_ping_monitor_with_connection_error_logs_warning(): flexmock(module.borgmatic.hooks.logs).should_receive('Forgetful_buffering_handler').never() hook_config = {'ping_url': 'https://example.com'}