From 255fa77ac3a323522085a957dc60ec2caa5aedf1 Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Wed, 4 Sep 2024 14:06:52 +0200 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=92=84=20=E2=80=94=20Improve=20email?= =?UTF-8?q?=20and=20gotify=20notifications?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ argos/server/alerting.py | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fe84eb..7db3b83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +- 💄 — Improve email and gotify notifications + ## 0.3.1 Date: 2024-09-02 diff --git a/argos/server/alerting.py b/argos/server/alerting.py index bb833a2..94ec13e 100644 --- a/argos/server/alerting.py +++ b/argos/server/alerting.py @@ -45,6 +45,14 @@ def notify_by_mail( ) -> None: logger.debug("Will send mail notification") + icon = "❌" + if severity == Severity.OK: + icon = "✅" + elif severity == Severity.WARNING: + icon = "⚠️" + elif severity == Severity.UNKNOWN: + icon = "❔" + msg = f"""\ URL: {task.url} Check: {task.check} @@ -58,7 +66,7 @@ See results of task on {request.url_for('get_task_results_view', task_id=task.id """ mail = f"""\ -Subject: [Argos] {urlparse(task.url).netloc}: status {severity} +Subject: [Argos] {icon} {urlparse(task.url).netloc}: status {severity} {msg}""" @@ -100,21 +108,30 @@ def notify_with_gotify( 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"""\ -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} +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}> """ + extras = { + "client::display": {"contentType": "text/markdown"}, + "client::notification": { + "click": {"url": request.url_for("get_result_view", result_id=result.id)} + }, + } - payload = {"title": subject, "message": msg, "priority": priority} + payload = {"title": subject, "message": msg, "priority": priority, "extras": extras} for url in config: logger.debug("Sending gotify message(s) to %s", url) From 8072a485a1531566cac194ddd4bb85de8867c3f6 Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Wed, 4 Sep 2024 14:19:51 +0200 Subject: [PATCH 2/5] =?UTF-8?q?=E2=9C=A8=20=E2=80=94=20Add=20command=20to?= =?UTF-8?q?=20test=20gotify=20configuration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + argos/commands.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++- docs/cli.md | 26 +++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7db3b83..fad6f94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] - 💄 — Improve email and gotify notifications +- ✨ — Add command to test gotify configuration ## 0.3.1 diff --git a/argos/commands.py b/argos/commands.py index 5b13764..ffd69f7 100644 --- a/argos/commands.py +++ b/argos/commands.py @@ -607,12 +607,76 @@ async def test_mail(config, domain, severity): notify_by_mail( result, task, - severity="SEVERITY", + severity=severity, old_severity="OLD SEVERITY", config=conf.general.mail, request=_FalseRequest(), ) +@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") +@coroutine +async def test_gotify(config, domain, severity): + """Send a test gotify 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_gotify + from argos.server.main import read_config + from argos.server.models import Result, Task + + conf = read_config(config) + + if not conf.general.gotify: + click.echo("Gotify 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_gotify( + result, + task, + severity=severity, + old_severity="OLD SEVERITY", + config=conf.general.gotify, + request=_FalseRequest(), + ) + + if __name__ == "__main__": cli() diff --git a/docs/cli.md b/docs/cli.md index 67a660d..30cb428 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -85,6 +85,7 @@ Commands: migrate Run database migrations reload-config Load or reload tasks’ configuration start Starts the server (use only for testing or development!) + test-gotify Send a test gotify notification test-mail Send a test email user User management watch-agents Watch agents (to run routinely) @@ -491,3 +492,28 @@ Options: + +#### Test the Gotify settings + +You can verify that your Gotify settings are ok by sending a test notification + + + +```man +Usage: argos server test-gotify [OPTIONS] + + Send a test gotify 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 + --help Show this message and exit. +``` + + From 3917eb24980b69498825d4ad71c12327b7b41c6e Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Wed, 4 Sep 2024 14:55:30 +0200 Subject: [PATCH 3/5] =?UTF-8?q?=E2=9C=A8=20=E2=80=94=20Add=20nagios=20comm?= =?UTF-8?q?and=20to=20use=20as=20a=20Nagios=20probe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + argos/commands.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++ docs/cli.md | 29 ++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fad6f94..d046883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - 💄 — Improve email and gotify notifications - ✨ — Add command to test gotify configuration +- ✨ — Add nagios command to use as a Nagios probe ## 0.3.1 diff --git a/argos/commands.py b/argos/commands.py index ffd69f7..31af2b9 100644 --- a/argos/commands.py +++ b/argos/commands.py @@ -678,5 +678,58 @@ async def test_gotify(config, domain, severity): ) +@server.command(short_help="Nagios compatible severities report") +@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, +) +@coroutine +async def nagios(config): + """Output a report of current severities suitable for Nagios + with a Nagios compatible exit code""" + os.environ["ARGOS_YAML_FILE"] = config + + # The imports are made here otherwise the agent will need server configuration files. + from argos.server import queries + + exit_nb = 0 + db = await get_db() + severities = await queries.get_severity_counts(db) + + if severities["warning"] != 0: + exit_nb = 1 + if severities["critical"] != 0: + exit_nb = 2 + if severities["unknown"] != 0: + exit_nb = 2 + + stats = ( + f"ok={severities['ok']}; warning={severities['warning']}; " + f"critical={severities['critical']}; unknown={severities['unknown']};" + ) + + if exit_nb == 0: + print("OK — All sites are ok|{stats}") + elif exit_nb == 1: + print(f"WARNING — {severities['warning']} sites are in warning state|{stats}") + elif severities["critical"] == 0: + print(f"UNKNOWN — {severities['unknown']} sites are in unknown state|{stats}") + elif severities["unknown"] == 0: + print( + f"CRITICAL — {severities['critical']} sites are in critical state|{stats}" + ) + else: + print( + f"CRITICAL/UNKNOWN — {severities['critical']} sites are in critical state " + f"and {severities['unknown']} sites are in unknown state|{stats}" + ) + + sysexit(exit_nb) + + if __name__ == "__main__": cli() diff --git a/docs/cli.md b/docs/cli.md index 30cb428..58b4610 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -83,6 +83,7 @@ Commands: generate-config Output a self-documented example config file. generate-token Generate a token for agents migrate Run database migrations + nagios Nagios compatible severities report reload-config Load or reload tasks’ configuration start Starts the server (use only for testing or development!) test-gotify Send a test gotify notification @@ -468,9 +469,33 @@ Options: +#### Use as a nagios probe + +You can directly use Argos to get an output and an exit code usable with Nagios. + + + +```man +Usage: argos server nagios [OPTIONS] + + Output a report of current severities suitable for Nagios with a Nagios + compatible exit code + +Options: + --config TEXT Path of the configuration file. If ARGOS_YAML_FILE environment + variable is set, its value will be used instead. + --help Show this message and exit. +``` + + + #### Test the email settings -You can verify that your mail settings are ok by sending a test email +You can verify that your mail settings are ok by sending a test email. + +#### Test the Apprise settings + +You can verify that your Apprise settings are ok by sending a test notification. + + + +```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. +``` + + diff --git a/pyproject.toml b/pyproject.toml index 5c94171..dbb231e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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",