This commit is contained in:
Sense T 2022-08-08 05:51:01 +00:00
commit 135a9dd01d
16 changed files with 213 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
.venv
__pycache__
config/config.yaml
config/text_template.tpl

1
.python-version Normal file
View File

@ -0,0 +1 @@
system

35
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,35 @@
{
"version": "0.2.0",
"configurations": [
{
"name":"Python: Flask Migration",
"type":"python",
"request":"launch",
"module":"flask",
"env":{
"FLASK_APP":"app.migrate",
"FLASK_ENV":"development",
"FLASK_DEBUG":"0"
},
"args":["db", "migrate"],
"jinja":false
},
{
"name": "Python: Flask",
"type": "python",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "app",
"FLASK_ENV": "development",
"FLASK_DEBUG": "1"
},
"args": [
"run",
"--no-debugger",
"--no-reload"
],
"jinja": true
}
]
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"python.defaultInterpreterPath": "venv/bin/python3"
}

3
app/__init__.py Normal file
View File

@ -0,0 +1,3 @@
from app.app import app
from views import *
from views.apis import *

4
app/api.py Normal file
View File

@ -0,0 +1,4 @@
from .app import app
from flask_restful import Api
api = Api(app)

24
app/app.py Normal file
View File

@ -0,0 +1,24 @@
import yaml
from flask import Flask
from utils.json_encoder import JSONEncoder
from os.path import dirname, abspath, join
class Config():
pass
with open('config/config.yaml', 'r') as f:
config_yaml = yaml.safe_load(f)
config = Config()
for k, v in config_yaml.items():
setattr(config, k, v)
app = Flask(__name__,
root_path=join(dirname(abspath(__file__)), '..'))
app.config.from_object(config)
app.json_encoder = JSONEncoder
app.config['RESTFUL_JSON'] = {
'cls': app.json_encoder
}

View File

@ -0,0 +1,8 @@
bark_api: http://bark-server.default:8080/push
title:
firing: Homeserver 告警发生
resolved: Homeserver 告警解除
default: Homeserver
to:
- 'token'
template_file: text_template.tpl

View File

@ -0,0 +1,22 @@
{%- for alert in alerts -%}
{%- if alert.status == 'firing' -%}
告警发生:
告警时间:{{alert.startsAt}}
{% if alert.labels.instance -%}涉及实例:{{alert.labels.instance}}{%- endif %}
{% if alert.labels.device -%}涉及设备:{{alert.labels.device}}{%- endif %}
告警名称:{{alert.labels.alertname}}
严重性:{{alert.labels.severity}}
详情:{{alert.annotations.summary}}
{% if alert.annotations.value -%}告警数据:{{alert.annotations.value}}{%- endif %}
{%- else -%}
告警恢复:
告警时间:{{alert.startsAt}}
恢复时间:{{alert.endsAt}}
{% if alert.labels.instance -%}涉及实例:{{alert.labels.instance}}{%- endif %}
{% if alert.labels.device -%}涉及设备:{{alert.labels.device}}{%- endif %}
告警名称:{{alert.labels.alertname}}
严重性:{{alert.labels.severity}}
详情:{{alert.annotations.summary}}
{% if alert.annotations.value -%}告警数据:{{alert.annotations.value}}{%- endif %}
{%- endif -%}
{%- endfor -%}

0
utils/__init__.py Normal file
View File

11
utils/error_handler.py Normal file
View File

@ -0,0 +1,11 @@
import traceback
from app import app
def error_handler(e):
app.logger.warning(e, traceback.format_exc())
return {
'success': False,
'message': 'Error: {0}'.format(str(e)),
'data': None
}, 500

18
utils/json_encoder.py Normal file
View File

@ -0,0 +1,18 @@
from flask.json import JSONEncoder
import datetime
import decimal
class JSONEncoder(JSONEncoder):
def default(self, obj):
try:
if isinstance(obj, datetime.datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(obj, decimal.Decimal):
return float(obj)
iterable = iter(obj)
except TypeError:
pass
else:
return list(iterable)
return JSONEncoder.default(self, obj)

1
views/__init__.py Normal file
View File

@ -0,0 +1 @@
__all__ = ['apis']

1
views/apis/__init__.py Normal file
View File

@ -0,0 +1 @@
__all__ = ['bark_service', 'health']

View File

@ -0,0 +1,66 @@
from flask import request
from flask_restful import Resource
from utils.error_handler import error_handler
from app.app import app
from app.api import api
from munch import Munch
import requests
class BarkResource(Resource):
def post(self):
try:
data = Munch.fromDict(request.get_json(silent=True))
app.logger.debug(data)
config = Munch.fromDict(app.config)
content = {
'title': config.title.firing if data.status == 'firing' else config.title.resolved if data.status == 'resolved' else config.title.default,
'category': 'category'
}
# TODO: alertmanager message to bark content.
'''
{
"version": "4",
"groupKey": <string>, // key identifying the group of alerts (e.g. to deduplicate)
"truncatedAlerts": <int>, // how many alerts have been truncated due to "max_alerts"
"status": "<resolved|firing>",
"receiver": <string>,
"groupLabels": <object>,
"commonLabels": <object>,
"commonAnnotations": <object>,
"externalURL": <string>, // backlink to the Alertmanager.
"alerts": [
{
"status": "<resolved|firing>",
"labels": <object>,
"annotations": <object>,
"startsAt": "<rfc3339>",
"endsAt": "<rfc3339>",
"generatorURL": <string>, // identifies the entity that caused the alert
"fingerprint": <string> // fingerprint to identify the alert
},
...
]
}
'''
content.body = app.jinja_environment.get_template(config.template_file).render(data)
app.logger.debug(content.body)
for to in config.to:
content['device_key'] = to
response = requests.post(
url = config.bark_api,
headers = {
"Content-Type": "application/json; charset=utf-8",
},
data=content
)
app.logger.info(response)
return {
'success': True,
'message': '',
'data': {},
}
except Exception as e:
return error_handler(e)
api.add_resource(BarkResource, '/api/send')

12
views/apis/health.py Normal file
View File

@ -0,0 +1,12 @@
from flask_restful import Resource
from app.api import api
class HealthResource(Resource):
def get(self):
return {
'success': True,
'message': '',
'data': {},
}
api.add_resource(HealthResource, '/health')