From b607d21b264ac3a6afc3dd48ede6f60ff4c06018 Mon Sep 17 00:00:00 2001 From: Jeroen Date: Fri, 16 Apr 2021 13:36:29 +0200 Subject: [PATCH] initial commit --- Dockerfile | 19 +++++++++++++++ README.md | 13 ++++++++++ bridge.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ bridge.sh | 4 +++ requirements.txt | 4 +++ 5 files changed, 103 insertions(+) create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 bridge.py create mode 100644 bridge.sh create mode 100644 requirements.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bd9637e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.8-slim-buster + +RUN useradd -m bridge + +RUN mkdir /app +WORKDIR /app + +RUN apt-get update &&\ + apt-get install -y build-essential &&\ + rm -rf /var/lib/apt/* /var/cache/apt/* + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +COPY bridge.py ./ +COPY bridge.sh ./ + +USER bridge +CMD [ "bash", "bridge.sh" ] diff --git a/README.md b/README.md new file mode 100644 index 0000000..8a714b3 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# Grafana-matrix-alert + +This is a small container to send alerts from grafana to a matrix room. + +Preconditions: in matrix, a user must exist for grafana to use. That user must be a member of the "alert room". + +Set the following environment variables when running the container: +MATRIX_HOMESERVER_URL +MATRIX_USER +MATRIX_PASSWORD +MATRIX_ROOM_ID (the internal room ID) + +In Grafana, configure a notification channel of type "webhook" and set the URL to the host/port where the container is running. diff --git a/bridge.py b/bridge.py new file mode 100644 index 0000000..0bfb11a --- /dev/null +++ b/bridge.py @@ -0,0 +1,63 @@ +import asyncio +import datetime +import logging +import os +import time +import json +from ssl import create_default_context +from statistics import mean + +from flask import Flask, request +from flask_restful import Resource, Api + +# import pytz +# import requests +from nio import AsyncClient + +logging.basicConfig(level=logging.INFO) + +app = Flask(__name__) +api = Api(app) + +MATRIX_HOMESERVER_URL = os.environ.get("MATRIX_HOMESERVER_URL") +MATRIX_USER = os.environ.get("MATRIX_USER") +MATRIX_PASSWORD = os.environ.get("MATRIX_PASSWORD") +MATRIX_ROOM_ID = os.environ.get("MATRIX_ROOM_ID") + + +async def send_message(msg, room_id): + client = AsyncClient( + MATRIX_HOMESERVER_URL, + MATRIX_USER + ) + await client.login(MATRIX_PASSWORD) + await client.room_send( + room_id=room_id, + message_type="m.room.message", + content={"msgtype": "m.text", "body": msg}, + ) + await client.close() + + +def publish(msg, room_id): + asyncio.get_event_loop().run_until_complete(send_message(msg, room_id)) + + +# def now(): +# return ( +# pytz.utc.localize(datetime.datetime.utcnow()) +# .astimezone(pytz.timezone("Europe/Brussels")) +# .isoformat() +# ) + + +class PostEndpoint(Resource): + def post(self): + logging.info(request.data) + data = json.loads(request.data) + msg = f"{data.get('title', '')}: {data.get('message', '')}" + publish(msg, MATRIX_ROOM_ID) + return None, 204 + + +api.add_resource(PostEndpoint, '/') diff --git a/bridge.sh b/bridge.sh new file mode 100644 index 0000000..a83dd8f --- /dev/null +++ b/bridge.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cd /app || exit +gunicorn --workers=2 --bind=0.0.0.0:8000 bridge:app diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7158a07 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Flask==1.1.2 +Flask-RESTful==0.3.8 +gunicorn==20.1.0 +matrix-nio==0.17.0