add support for apprise

This commit is contained in:
Pim Kunis 2023-09-21 21:44:12 +02:00 committed by pizzapim
parent 06c2154e6a
commit f3295ccb4a
5 changed files with 208 additions and 1 deletions

View file

@ -1306,6 +1306,127 @@ properties:
example: example:
- start - start
- finish - finish
apprise:
type: object
required: ['service_urls'] # TODO
additionalProperties: false
properties:
service_urls:
type: array
items:
type: string
description: |
List of Apprise service URLs to publish to.
example:
- "mastodon://accesskey/host/?visibility=direct"
- "pagerduty://A1BRTD4JD@TIiajkdnlazkcOXrIdevi7F/node01.local/drive_sda/"
start:
type: object
properties:
title:
type: string
description: |
Specify the message title.
example: Ping!
body:
type: string
description: |
Specify the message body.
exampe: Your backups have failed.
notification_type:
type: string
description: |
The Apprise message type.
enum:
- info
- success
- failure
- warning
example:
- failure
# tags:
# type: array
# items:
# type: string
# description: |
# One or more tags to filter which services to notify.
finish:
type: object
properties:
title:
type: string
description: |
Specify the message title.
example: Ping!
body:
type: string
description: |
Specify the message body.
exampe: Your backups have failed.
notification_type:
type: string
description: |
The Apprise message type.
enum:
- info
- success
- failure
- warning
example:
- failure
# tags:
# type: array
# items:
# type: string
# description: |
# One or more tags to filter which services to notify.
fail:
type: object
properties:
title:
type: string
description: |
Specify the message title.
example: Ping!
body:
type: string
description: |
Specify the message body.
exampe: Your backups have failed.
notification_type:
type: string
description: |
The Apprise message type.
enum:
- info
- success
- failure
- warning
example:
- failure
# tags:
# type: array
# items:
# type: string
# description: |
# One or more tags to filter which services to notify.
states:
type: array
items:
type: string
enum:
- start
- finish
- fail
uniqueItems: true
description: |
List of one or more monitoring states to ping for: "start",
"finish", and/or "fail". Defaults to pinging for failure
only.
example:
- start
- finish
healthchecks: healthchecks:
type: object type: object
required: ['ping_url'] required: ['ping_url']

View file

@ -0,0 +1,83 @@
import logging
import apprise
from apprise import NotifyType, NotifyFormat
logger = logging.getLogger(__name__)
def initialize_monitor(
ping_url, config, config_filename, monitoring_log_level, dry_run
): # pragma: no cover
'''
No initialization is necessary for this monitor.
'''
pass
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run):
'''
Ping the configured Apprise service URLs.
Use the given configuration filename in any log entries.
If this is a dry run, then don't actually ping anything.
'''
run_states = hook_config.get('states', ['fail'])
if state.name.lower() not in run_states:
return
state_config = hook_config.get(
state.name.lower(),
{
'title': f'A borgmatic {state.name} event happened',
'body': f'A borgmatic {state.name} event happened',
'notification_type': 'success', # TODO: default per state.name
# 'tag': ['borgmatic'],
},
)
# TODO: Currently not very meaningful message.
# However, the Apprise service URLs can contain sensitive info.
dry_run_label = ' (dry run; not actually pinging)' if dry_run else ''
logger.info(f'{config_filename}: Pinging Apprise {dry_run_label}')
logger.debug(f'{config_filename}: Using Apprise ping')
title = state_config.get('title', '')
body = state_config.get('body')
notify_type = state_config.get('notification_type', 'success')
apobj = apprise.Apprise()
apobj.add(hook_config.get('service_urls'))
if dry_run:
return
result = apobj.notify(
title=title,
body=body,
body_format=NotifyFormat.TEXT,
notify_type=get_notify_type(notify_type)
)
if result is False:
logger.warning(f'{config_filename}: error sending some apprise notifications')
def get_notify_type(s):
if s == 'info':
return NotifyType.INFO
if s == 'success':
return NotifyType.SUCCESS
if s == 'warning':
return NotifyType.WARNING
if s == 'failure':
return NotifyType.FAILURE
def destroy_monitor(
ping_url_or_uuid, config, config_filename, monitoring_log_level, dry_run
): # pragma: no cover
'''
No destruction is necessary for this monitor.
'''
pass

View file

@ -1,6 +1,7 @@
import logging import logging
from borgmatic.hooks import ( from borgmatic.hooks import (
apprise,
cronhub, cronhub,
cronitor, cronitor,
healthchecks, healthchecks,
@ -17,6 +18,7 @@ from borgmatic.hooks import (
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
HOOK_NAME_TO_MODULE = { HOOK_NAME_TO_MODULE = {
'apprise': apprise,
'cronhub': cronhub, 'cronhub': cronhub,
'cronitor': cronitor, 'cronitor': cronitor,
'healthchecks': healthchecks, 'healthchecks': healthchecks,

View file

@ -1,6 +1,6 @@
from enum import Enum from enum import Enum
MONITOR_HOOK_NAMES = ('healthchecks', 'cronitor', 'cronhub', 'pagerduty', 'ntfy', 'loki') MONITOR_HOOK_NAMES = ('apprise', 'healthchecks', 'cronitor', 'cronhub', 'pagerduty', 'ntfy', 'loki')
class State(Enum): class State(Enum):

View file

@ -35,6 +35,7 @@ setup(
'requests', 'requests',
'ruamel.yaml>0.15.0,<0.18.0', 'ruamel.yaml>0.15.0,<0.18.0',
'setuptools', 'setuptools',
'apprise'
), ),
include_package_data=True, include_package_data=True,
python_requires='>=3.7', python_requires='>=3.7',