When making HTTP requests in monitoring hooks, set "borgmatic" as the user agent (#1139).

This commit is contained in:
Dan Helfman
2025-09-01 16:51:33 -07:00
parent 36d6619099
commit 563cb8441e
19 changed files with 77 additions and 20 deletions
+1
View File
@@ -4,6 +4,7 @@
use.
* #1126: Create LVM snapshots as read-write to avoid an error when snapshotting ext4 filesystems
with orphaned files that need recovery.
* #1139: When making HTTP requests in monitoring hooks, set "borgmatic" as the user agent.
* When running tests, use Ruff for faster and more comprehensive code linting and formatting,
replacing Flake8, Black, isort, etc.
* Switch from pipx to uv for installing development tools, and added tox-uv for speeding up test
+5 -1
View File
@@ -49,7 +49,11 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
if not dry_run:
logging.getLogger('urllib3').setLevel(logging.ERROR)
try:
response = requests.get(ping_url, timeout=TIMEOUT_SECONDS)
response = requests.get(
ping_url,
timeout=TIMEOUT_SECONDS,
headers={'User-Agent': 'borgmatic'},
)
if not response.ok:
response.raise_for_status()
except requests.exceptions.RequestException as error:
+5 -1
View File
@@ -44,7 +44,11 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
if not dry_run:
logging.getLogger('urllib3').setLevel(logging.ERROR)
try:
response = requests.get(ping_url, timeout=TIMEOUT_SECONDS)
response = requests.get(
ping_url,
timeout=TIMEOUT_SECONDS,
headers={'User-Agent': 'borgmatic'},
)
if not response.ok:
response.raise_for_status()
except requests.exceptions.RequestException as error:
@@ -91,6 +91,7 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
data=payload.encode('utf-8'),
verify=hook_config.get('verify_tls', True),
timeout=TIMEOUT_SECONDS,
headers={'User-Agent': 'borgmatic'},
)
if not response.ok:
response.raise_for_status()
+5 -4
View File
@@ -65,16 +65,17 @@ class Loki_log_buffer:
# Skip as there are not logs to send yet
return
request_body = self.to_request()
self.root['streams'][0]['values'] = []
request_header = {'Content-Type': 'application/json'}
try:
result = requests.post(
self.url,
headers=request_header,
data=request_body,
data=self.to_request(),
timeout=TIMEOUT_SECONDS,
headers={
'Content-Type': 'application/json',
'User-Agent': 'borgmatic',
},
)
result.raise_for_status()
except requests.RequestException:
+2 -1
View File
@@ -49,6 +49,7 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
logger.debug(f'Using Ntfy ping URL {base_url}/{topic}')
headers = {
'User-Agent': 'borgmatic',
'X-Title': state_config.get('title'),
'X-Message': state_config.get('message'),
'X-Priority': state_config.get('priority'),
@@ -94,9 +95,9 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
try:
response = requests.post(
f'{base_url}/{topic}',
headers=headers,
auth=auth,
timeout=TIMEOUT_SECONDS,
headers=headers,
)
if not response.ok:
response.raise_for_status()
+1
View File
@@ -102,6 +102,7 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
EVENTS_API_URL,
data=payload.encode('utf-8'),
timeout=TIMEOUT_SECONDS,
headers={'User-Agent': 'borgmatic'},
)
if not response.ok:
response.raise_for_status()
+4 -1
View File
@@ -82,9 +82,12 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
try:
response = requests.post(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
data=data,
timeout=TIMEOUT_SECONDS,
headers={
'Content-type': 'application/x-www-form-urlencoded',
'User-Agent': 'borgmatic',
},
)
if not response.ok:
response.raise_for_status()
+5 -1
View File
@@ -67,7 +67,11 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
logging.getLogger('urllib3').setLevel(logging.ERROR)
try:
response = requests.post(f'{cron_url}?status={status}', timeout=TIMEOUT_SECONDS)
response = requests.post(
f'{cron_url}?status={status}',
timeout=TIMEOUT_SECONDS,
headers={'User-Agent': 'borgmatic'},
)
if not response.ok:
response.raise_for_status()
except requests.exceptions.RequestException as error:
@@ -47,6 +47,7 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
f'{push_url}?{query}',
verify=hook_config.get('verify_tls', True),
timeout=TIMEOUT_SECONDS,
headers={'User-Agent': 'borgmatic'},
)
if not response.ok:
response.raise_for_status()
+1 -1
View File
@@ -101,7 +101,7 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
host = hook_config.get('host')
key = hook_config.get('key')
value = state_config.get('value')
headers = {'Content-Type': 'application/json-rpc'}
headers = {'Content-Type': 'application/json-rpc', 'User-Agent': 'borgmatic'}
logger.info(f'Pinging Zabbix{dry_run_label}')
logger.debug(f'Using Zabbix URL: {server}')
@@ -8,6 +8,7 @@ def test_ping_monitor_rewrites_ping_url_for_start_state():
flexmock(module.requests).should_receive('get').with_args(
'https://example.com/start/abcdef',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -25,6 +26,7 @@ def test_ping_monitor_rewrites_ping_url_and_state_for_start_state():
flexmock(module.requests).should_receive('get').with_args(
'https://example.com/start/abcdef',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -42,6 +44,7 @@ def test_ping_monitor_rewrites_ping_url_for_finish_state():
flexmock(module.requests).should_receive('get').with_args(
'https://example.com/finish/abcdef',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -59,6 +62,7 @@ def test_ping_monitor_rewrites_ping_url_for_fail_state():
flexmock(module.requests).should_receive('get').with_args(
'https://example.com/fail/abcdef',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -111,6 +115,7 @@ def test_ping_monitor_with_other_error_logs_warning():
flexmock(module.requests).should_receive('get').with_args(
'https://example.com/start/abcdef',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(response)
flexmock(module.logger).should_receive('warning').once()
@@ -8,6 +8,7 @@ def test_ping_monitor_hits_ping_url_for_start_state():
flexmock(module.requests).should_receive('get').with_args(
'https://example.com/run',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -25,6 +26,7 @@ def test_ping_monitor_hits_ping_url_for_finish_state():
flexmock(module.requests).should_receive('get').with_args(
'https://example.com/complete',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -42,6 +44,7 @@ def test_ping_monitor_hits_ping_url_for_fail_state():
flexmock(module.requests).should_receive('get').with_args(
'https://example.com/fail',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -94,6 +97,7 @@ def test_ping_monitor_with_other_error_logs_warning():
flexmock(module.requests).should_receive('get').with_args(
'https://example.com/run',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(response)
flexmock(module.logger).should_receive('warning').once()
@@ -99,6 +99,7 @@ def test_ping_monitor_hits_ping_url_for_start_state():
data=b'',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -123,6 +124,7 @@ def test_ping_monitor_hits_ping_url_for_finish_state():
data=payload.encode('utf-8'),
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -147,6 +149,7 @@ def test_ping_monitor_hits_ping_url_for_fail_state():
data=payload.encode('utf'),
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -171,6 +174,7 @@ def test_ping_monitor_hits_ping_url_for_log_state():
data=payload.encode('utf'),
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -195,6 +199,7 @@ def test_ping_monitor_with_ping_uuid_hits_corresponding_url():
data=payload.encode('utf-8'),
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -219,6 +224,7 @@ def test_ping_monitor_skips_ssl_verification_when_verify_tls_false():
data=payload.encode('utf-8'),
verify=False,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -243,6 +249,7 @@ def test_ping_monitor_executes_ssl_verification_when_verify_tls_true():
data=payload.encode('utf-8'),
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -299,6 +306,7 @@ def test_ping_monitor_hits_ping_url_when_states_matching():
data=b'',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -321,6 +329,7 @@ def test_ping_monitor_adds_create_query_parameter_when_create_slug_true():
data=b'',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -343,6 +352,7 @@ def test_ping_monitor_does_not_add_create_query_parameter_when_create_slug_false
data=b'',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -362,6 +372,7 @@ def test_ping_monitor_does_not_add_create_query_parameter_when_ping_url_is_uuid(
data=b'',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True))
module.ping_monitor(
@@ -401,6 +412,7 @@ def test_ping_monitor_with_connection_error_logs_warning():
data=b'',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_raise(module.requests.exceptions.ConnectionError)
flexmock(module.logger).should_receive('warning').once()
@@ -428,6 +440,7 @@ def test_ping_monitor_with_other_error_logs_warning():
data=b'',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(response)
flexmock(module.logger).should_receive('warning').once()
+2
View File
@@ -17,6 +17,7 @@ custom_message_config = {
}
custom_message_headers = {
'User-Agent': 'borgmatic',
'X-Title': custom_message_config['title'],
'X-Message': custom_message_config['message'],
'X-Priority': custom_message_config['priority'],
@@ -26,6 +27,7 @@ custom_message_headers = {
def return_default_message_headers(state=Enum):
return {
'User-Agent': 'borgmatic',
'X-Title': f'A borgmatic {state.name} event happened',
'X-Message': f'A borgmatic {state.name} event happened',
'X-Priority': 'default',
+10 -10
View File
@@ -17,7 +17,7 @@ def test_ping_monitor_config_with_minimum_config_fail_state_backup_successfully_
flexmock(module.logger).should_receive('warning').never()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -76,7 +76,7 @@ def test_ping_monitor_start_state_backup_default_message_successfully_send_to_pu
flexmock(module.logger).should_receive('warning').never()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -113,7 +113,7 @@ def test_ping_monitor_start_state_backup_custom_message_successfully_send_to_pus
flexmock(module.logger).should_receive('warning').never()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -149,7 +149,7 @@ def test_ping_monitor_start_state_backup_default_message_with_priority_emergency
flexmock(module.logger).should_receive('warning').never()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -188,7 +188,7 @@ def test_ping_monitor_start_state_backup_default_message_with_priority_emergency
flexmock(module.logger).should_receive('warning').never()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -227,7 +227,7 @@ def test_ping_monitor_start_state_backup_default_message_with_priority_emergency
flexmock(module.logger).should_receive('warning').never()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -324,7 +324,7 @@ def test_ping_monitor_start_state_backup_based_on_documentation_advanced_example
flexmock(module.logger).should_receive('warning').never()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -391,7 +391,7 @@ def test_ping_monitor_fail_state_backup_based_on_documentation_advanced_example_
flexmock(module.logger).should_receive('warning').never()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -463,7 +463,7 @@ def test_ping_monitor_finish_state_backup_based_on_documentation_advanced_exampl
flexmock(module.logger).should_receive('warning').never()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -553,7 +553,7 @@ def test_ping_monitor_push_post_error_bails():
).once()
flexmock(module.requests).should_receive('post').with_args(
'https://api.pushover.net/1/messages.json',
headers={'Content-type': 'application/x-www-form-urlencoded'},
headers={'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'borgmatic'},
data={
'token': 'ksdjfwoweijfvwoeifvjmwghagy92',
'user': '983hfe0of902lkjfa2amanfgui',
@@ -31,6 +31,7 @@ def test_ping_monitor_constructs_cron_url_and_pings_it(state, configured_states,
flexmock(module.requests).should_receive('post').with_args(
f'https://o294220.ingest.us.sentry.io/api/203069/cron/test/5f80ec/?status={expected_status}',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True)).once()
module.ping_monitor(
@@ -137,6 +138,7 @@ def test_ping_monitor_with_network_error_does_not_raise():
flexmock(module.requests).should_receive('post').with_args(
'https://o294220.ingest.us.sentry.io/api/203069/cron/test/5f80ec/?status=in_progress',
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(response).once()
module.ping_monitor(
@@ -13,6 +13,7 @@ def test_ping_monitor_hits_default_uptimekuma_on_fail():
f'{DEFAULT_PUSH_URL}?status=down&msg=fail',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True)).once()
module.ping_monitor(
@@ -31,6 +32,7 @@ def test_ping_monitor_hits_custom_uptimekuma_on_fail():
f'{CUSTOM_PUSH_URL}?status=down&msg=fail',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True)).once()
module.ping_monitor(
@@ -49,6 +51,7 @@ def test_ping_monitor_custom_uptimekuma_on_start():
f'{CUSTOM_PUSH_URL}?status=up&msg=start',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True)).once()
module.ping_monitor(
@@ -67,6 +70,7 @@ def test_ping_monitor_custom_uptimekuma_on_finish():
f'{CUSTOM_PUSH_URL}?status=up&msg=finish',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True)).once()
module.ping_monitor(
@@ -127,6 +131,7 @@ def test_ping_monitor_with_connection_error_logs_warning():
f'{CUSTOM_PUSH_URL}?status=down&msg=fail',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_raise(module.requests.exceptions.ConnectionError)
flexmock(module.logger).should_receive('warning').once()
@@ -150,6 +155,7 @@ def test_ping_monitor_with_other_error_logs_warning():
f'{CUSTOM_PUSH_URL}?status=down&msg=fail',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(response)
flexmock(module.logger).should_receive('warning').once()
@@ -183,6 +189,7 @@ def test_ping_monitor_skips_ssl_verification_when_verify_tls_false():
f'{CUSTOM_PUSH_URL}?status=down&msg=fail',
verify=False,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True)).once()
module.ping_monitor(
@@ -201,6 +208,7 @@ def test_ping_monitor_executes_ssl_verification_when_verify_tls_true():
f'{CUSTOM_PUSH_URL}?status=down&msg=fail',
verify=True,
timeout=int,
headers={'User-Agent': 'borgmatic'},
).and_return(flexmock(ok=True)).once()
module.ping_monitor(
@@ -56,11 +56,13 @@ DATA_USER_LOGOUT = {
AUTH_HEADERS_LOGIN = {
'Content-Type': 'application/json-rpc',
'User-Agent': 'borgmatic',
}
AUTH_HEADERS = {
'Content-Type': 'application/json-rpc',
'Authorization': f'Bearer {API_KEY}',
'User-Agent': 'borgmatic',
}