init
This commit is contained in:
commit
135a9dd01d
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.venv
|
||||||
|
__pycache__
|
||||||
|
config/config.yaml
|
||||||
|
config/text_template.tpl
|
1
.python-version
Normal file
1
.python-version
Normal file
@ -0,0 +1 @@
|
|||||||
|
system
|
35
.vscode/launch.json
vendored
Normal file
35
.vscode/launch.json
vendored
Normal 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
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"python.defaultInterpreterPath": "venv/bin/python3"
|
||||||
|
}
|
3
app/__init__.py
Normal file
3
app/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from app.app import app
|
||||||
|
from views import *
|
||||||
|
from views.apis import *
|
4
app/api.py
Normal file
4
app/api.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from .app import app
|
||||||
|
from flask_restful import Api
|
||||||
|
|
||||||
|
api = Api(app)
|
24
app/app.py
Normal file
24
app/app.py
Normal 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
|
||||||
|
}
|
8
config/config_example.yaml
Normal file
8
config/config_example.yaml
Normal 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
|
22
config/text_template_example.tpl
Normal file
22
config/text_template_example.tpl
Normal 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
0
utils/__init__.py
Normal file
11
utils/error_handler.py
Normal file
11
utils/error_handler.py
Normal 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
18
utils/json_encoder.py
Normal 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
1
views/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
__all__ = ['apis']
|
1
views/apis/__init__.py
Normal file
1
views/apis/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
__all__ = ['bark_service', 'health']
|
66
views/apis/bark_service.py
Normal file
66
views/apis/bark_service.py
Normal 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
12
views/apis/health.py
Normal 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')
|
Loading…
Reference in New Issue
Block a user