mirror of
https://framagit.org/framasoft/framaspace/argos.git
synced 2025-04-28 09:52:38 +02:00
✨ — Add Apprise as notification way (fix #50)
This commit is contained in:
parent
7998333fc1
commit
6c3c44f5be
7 changed files with 166 additions and 15 deletions
|
@ -5,6 +5,7 @@
|
|||
- 💄 — Improve email and gotify notifications
|
||||
- ✨ — Add command to test gotify configuration
|
||||
- ✨ — Add nagios command to use as a Nagios probe
|
||||
- ✨ — Add Apprise as notification way (#50)
|
||||
|
||||
## 0.3.1
|
||||
|
||||
|
|
|
@ -678,6 +678,73 @@ async def test_gotify(config, domain, severity):
|
|||
)
|
||||
|
||||
|
||||
@server.command()
|
||||
@click.option(
|
||||
"--config",
|
||||
default="argos-config.yaml",
|
||||
help="Path of the configuration file. "
|
||||
"If ARGOS_YAML_FILE environment variable is set, its value will be used instead.",
|
||||
envvar="ARGOS_YAML_FILE",
|
||||
callback=validate_config_access,
|
||||
)
|
||||
@click.option("--domain", help="Domain for the notification", default="example.org")
|
||||
@click.option("--severity", help="Severity", default="CRITICAL")
|
||||
@click.option(
|
||||
"--apprise-group", help="Apprise group for the notification", required=True
|
||||
)
|
||||
@coroutine
|
||||
async def test_apprise(config, domain, severity, apprise_group):
|
||||
"""Send a test apprise notification"""
|
||||
os.environ["ARGOS_YAML_FILE"] = config
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from argos.logging import set_log_level
|
||||
from argos.server.alerting import notify_with_apprise
|
||||
from argos.server.main import read_config
|
||||
from argos.server.models import Result, Task
|
||||
|
||||
conf = read_config(config)
|
||||
|
||||
if not conf.general.apprise:
|
||||
click.echo("Apprise notifications are not configured, cannot test", err=True)
|
||||
sysexit(1)
|
||||
else:
|
||||
now = datetime.now()
|
||||
task = Task(
|
||||
url=f"https://{domain}",
|
||||
domain=domain,
|
||||
check="body-contains",
|
||||
expected="foo",
|
||||
frequency=1,
|
||||
selected_by="test",
|
||||
selected_at=now,
|
||||
)
|
||||
|
||||
result = Result(
|
||||
submitted_at=now,
|
||||
status="success",
|
||||
context={"foo": "bar"},
|
||||
task=task,
|
||||
agent_id="test",
|
||||
severity="ok",
|
||||
)
|
||||
|
||||
class _FalseRequest:
|
||||
def url_for(*args, **kwargs):
|
||||
return "/url"
|
||||
|
||||
set_log_level("debug")
|
||||
notify_with_apprise(
|
||||
result,
|
||||
task,
|
||||
severity=severity,
|
||||
old_severity="OLD SEVERITY",
|
||||
group=conf.general.apprise[apprise_group],
|
||||
request=_FalseRequest(),
|
||||
)
|
||||
|
||||
|
||||
@server.command(short_help="Nagios compatible severities report")
|
||||
@click.option(
|
||||
"--config",
|
||||
|
|
|
@ -23,7 +23,10 @@ general:
|
|||
frequency: "1m"
|
||||
# Which way do you want to be warned when a check goes to that severity?
|
||||
# "local" emits a message in the server log
|
||||
# You’ll need to configure mail and gotify below to be able to use them here.
|
||||
# You’ll need to configure mail, gotify or apprise below to be able to use
|
||||
# them here.
|
||||
# Use "apprise:john", "apprise:team" (with the quotes!) to use apprise
|
||||
# notification groups.
|
||||
alerts:
|
||||
ok:
|
||||
- local
|
||||
|
@ -58,6 +61,17 @@ general:
|
|||
# tokens:
|
||||
# - foo
|
||||
# - bar
|
||||
# See https://github.com/caronc/apprise#productivity-based-notifications
|
||||
# for apprise’s URLs syntax.
|
||||
# You need to surround the URLs with quotes like in the examples below.
|
||||
# Use "apprise:john", "apprise:team" (with the quotes!) in "alerts" settings.
|
||||
# apprise:
|
||||
# john:
|
||||
# - "mastodon://access_key@hostname/@user"
|
||||
# - "matrixs://token@hostname:port/?webhook=matrix"
|
||||
# team:
|
||||
# - "mmosts://user@hostname/authkey"
|
||||
# - "nctalks://user:pass@host/RoomId1/RoomId2/RoomIdN"
|
||||
|
||||
service:
|
||||
secrets:
|
||||
|
|
|
@ -168,6 +168,7 @@ class General(BaseModel):
|
|||
alerts: Alert
|
||||
mail: Optional[Mail] = None
|
||||
gotify: Optional[List[GotifyUrl]] = None
|
||||
apprise: Optional[Dict[str, List[str]]] = None
|
||||
|
||||
@field_validator("frequency", mode="before")
|
||||
def parse_frequency(cls, value):
|
||||
|
|
|
@ -4,14 +4,24 @@ import smtplib
|
|||
from typing import List
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import apprise
|
||||
import httpx
|
||||
|
||||
from argos.checks.base import Severity
|
||||
from argos.logging import logger
|
||||
from argos.schemas.config import Config, Mail, GotifyUrl
|
||||
|
||||
# XXX Implement mail alerts https://framagit.org/framasoft/framaspace/argos/-/issues/15
|
||||
# XXX Implement gotify alerts https://framagit.org/framasoft/framaspace/argos/-/issues/16
|
||||
|
||||
def get_icon_from_severity(severity: str) -> str:
|
||||
icon = "❌"
|
||||
if severity == Severity.OK:
|
||||
icon = "✅"
|
||||
elif severity == Severity.WARNING:
|
||||
icon = "⚠️"
|
||||
elif severity == Severity.UNKNOWN:
|
||||
icon = "❔"
|
||||
|
||||
return icon
|
||||
|
||||
|
||||
def handle_alert(config: Config, result, task, severity, old_severity, request):
|
||||
|
@ -39,20 +49,52 @@ def handle_alert(config: Config, result, task, severity, old_severity, request):
|
|||
result, task, severity, old_severity, config.general.gotify, request
|
||||
)
|
||||
|
||||
if config.general.apprise is not None:
|
||||
for notif_way in getattr(config.general.alerts, severity):
|
||||
if notif_way.startswith("apprise:"):
|
||||
group = notif_way[8:]
|
||||
notify_with_apprise(
|
||||
result,
|
||||
task,
|
||||
severity,
|
||||
old_severity,
|
||||
config.general.apprise[group],
|
||||
request,
|
||||
)
|
||||
|
||||
|
||||
def notify_with_apprise(
|
||||
result, task, severity: str, old_severity: str, group: List[str], request
|
||||
) -> None:
|
||||
logger.debug("Will send apprise notification")
|
||||
|
||||
apobj = apprise.Apprise()
|
||||
for channel in group:
|
||||
apobj.add(channel)
|
||||
|
||||
icon = get_icon_from_severity(severity)
|
||||
title = f"[Argos] {icon} {urlparse(task.url).netloc}: status {severity}"
|
||||
msg = f"""\
|
||||
URL: {task.url}
|
||||
Check: {task.check}
|
||||
Status: {severity}
|
||||
Time: {result.submitted_at}
|
||||
Previous status: {old_severity}
|
||||
|
||||
See result on {request.url_for('get_result_view', result_id=result.id)}
|
||||
|
||||
See results of task on {request.url_for('get_task_results_view', task_id=task.id)}#{result.id}
|
||||
"""
|
||||
|
||||
apobj.notify(title=title, body=msg)
|
||||
|
||||
|
||||
def notify_by_mail(
|
||||
result, task, severity: str, old_severity: str, config: Mail, request
|
||||
) -> None:
|
||||
logger.debug("Will send mail notification")
|
||||
|
||||
icon = "❌"
|
||||
if severity == Severity.OK:
|
||||
icon = "✅"
|
||||
elif severity == Severity.WARNING:
|
||||
icon = "⚠️"
|
||||
elif severity == Severity.UNKNOWN:
|
||||
icon = "❔"
|
||||
|
||||
icon = get_icon_from_severity(severity)
|
||||
msg = f"""\
|
||||
URL: {task.url}
|
||||
Check: {task.check}
|
||||
|
@ -100,17 +142,14 @@ def notify_with_gotify(
|
|||
logger.debug("Will send gotify notification")
|
||||
headers = {"accept": "application/json", "content-type": "application/json"}
|
||||
|
||||
icon = get_icon_from_severity(severity)
|
||||
priority = 9
|
||||
icon = "❌"
|
||||
if severity == Severity.OK:
|
||||
priority = 1
|
||||
icon = "✅"
|
||||
elif severity == Severity.WARNING:
|
||||
priority = 5
|
||||
icon = "⚠️"
|
||||
elif severity == Severity.UNKNOWN:
|
||||
priority = 5
|
||||
icon = "❔"
|
||||
|
||||
subject = f"{icon} {urlparse(task.url).netloc}: status {severity}"
|
||||
msg = f"""\
|
||||
|
|
28
docs/cli.md
28
docs/cli.md
|
@ -86,6 +86,7 @@ Commands:
|
|||
nagios Nagios compatible severities report
|
||||
reload-config Load or reload tasks’ configuration
|
||||
start Starts the server (use only for testing or development!)
|
||||
test-apprise Send a test apprise notification
|
||||
test-gotify Send a test gotify notification
|
||||
test-mail Send a test email
|
||||
user User management
|
||||
|
@ -542,3 +543,30 @@ Options:
|
|||
|
||||
<!--[[[end]]]
|
||||
-->
|
||||
|
||||
#### Test the Apprise settings
|
||||
|
||||
You can verify that your Apprise settings are ok by sending a test notification.
|
||||
|
||||
<!--
|
||||
.. [[[cog
|
||||
help(["server", "test-apprise", "--help"])
|
||||
.. ]]] -->
|
||||
|
||||
```man
|
||||
Usage: argos server test-apprise [OPTIONS]
|
||||
|
||||
Send a test apprise notification
|
||||
|
||||
Options:
|
||||
--config TEXT Path of the configuration file. If ARGOS_YAML_FILE
|
||||
environment variable is set, its value will be used
|
||||
instead.
|
||||
--domain TEXT Domain for the notification
|
||||
--severity TEXT Severity
|
||||
--apprise-group TEXT Apprise group for the notification [required]
|
||||
--help Show this message and exit.
|
||||
```
|
||||
|
||||
<!--[[[end]]]
|
||||
-->
|
||||
|
|
|
@ -22,6 +22,7 @@ classifiers = [
|
|||
|
||||
dependencies = [
|
||||
"alembic>=1.13.0,<1.14",
|
||||
"apprise>=1.9.0,<2",
|
||||
"bcrypt>=4.1.3,<5",
|
||||
"click>=8.1,<9",
|
||||
"fastapi>=0.103,<0.104",
|
||||
|
|
Loading…
Reference in a new issue