Merge branch 'templating'

This commit is contained in:
Colin Goutte 2021-10-13 13:53:51 +02:00
commit 037643b74e
13 changed files with 400 additions and 25 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
__pycache__
.coverage
credentials.py

View File

@ -23,7 +23,7 @@ dev_serve:
poetry run uvicorn papi.main:app --reload
cleandb:
rm sql_app.db || echo ls
rm test_sql_app.db || echo ls
.ONESHELL:
test: cleandb

8
conf_notifications.ini Normal file
View File

@ -0,0 +1,8 @@
[masonde_001]
email = email@fqdn
email@fqdn.co.uk
masonde_001@fqdn
[test]
email = notif_sondetest@monitoring.com

24
papi/mail_sendermodel.py Normal file
View File

@ -0,0 +1,24 @@
from mailjet_rest import Client
import os
from papi.credentials import api_key, api_secret
def sendmail(htmlpart):
mailjet = Client(auth=(api_key, api_secret), version="v3.1")
data = {
"Messages": [
{
"From": {"Email": "colin.goutte@free.fr", "Name": "Colin"},
"To": [{"Email": "colin.goutte@free.fr", "Name": "Colin"}],
"Subject": "Monitoring API",
"TextPart": "My first Mailjet email",
"HTMLPart": "" + htmlpart,
"CustomID": "AppGettingStartedTest",
}
]
}
result = mailjet.send.create(data=data)
print(result.status_code)
print(result.json())

View File

@ -1,7 +1,10 @@
from typing import Optional, List
from configparser import ConfigParser
from pydantic import BaseModel
from fastapi import FastAPI, Request, Body, Depends
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
from collections import defaultdict
@ -14,14 +17,31 @@ from papi.sqlapp import schemas
app = FastAPI()
templates = Jinja2Templates(directory="templates/")
mesures = defaultdict(list)
notifications = defaultdict(list)
Base.metadata.create_all(bind=engine)
conf = ConfigParser()
conf.read("conf_notifications.ini")
def get_db():
def sondeid2notifsemails(idsonde, mapping=conf):
try:
section = mapping[idsonde]
except KeyError: # pragma: no cover
raise KeyError(f"{idsonde} non trouvé dans {list(mapping.keys())}")
mails = section["email"]
if isinstance(mails, str):
mails = [x.strip() for x in mails.split("\n")]
return mails
def get_db(): # pragma: no cover
db = SessionLocal()
try:
yield db
@ -37,6 +57,15 @@ class Notifier:
{"changes": changes, "status": [x for x in status]}
)
@staticmethod
def error_sonde(idsonde, kind="perte_contact_api"):
notifications[idsonde].append(
{
"changes": ["perte contact api"],
"status": ["Le monitoring est inacessible"],
}
)
Notifier = Notifier()
@ -71,14 +100,76 @@ def list_sonde():
return [x for x in sondes.values()]
@app.get("/notifications/{idsonde}/")
@app.get("/notifications/{idsonde}")
def list_notification(idsonde: str):
return notifications[idsonde][::-1]
@app.get("/notifications/{idsonde}/text")
def last_notif_text(request: Request, idsonde: str):
notifs = notifications[idsonde]
try:
content = notifs[-1]
except IndexError: # pragma: no cover
return
try:
recipients = sondeid2notifsemails(idsonde)
except KeyError: # pragma: no cover
recipients = ["mail1@xxx", "mail2@xxx"]
changements = content["changes"]
status = content["status"]
def coloriser(message):
d = {"error": "red", "warning": "orange", "pending": "yellow", "ok": "green"}
for k, v in d.items():
if message.endswith(k):
return "color: %s;" % v
data = {"recipients": recipients, "changements": changements, "status": status}
return templates.TemplateResponse(
"notification_email.html",
context={
"request": request,
"data": data,
"coloriser": coloriser,
},
)
@app.post("/sonde/{idsonde}/error")
def post_sonde_error(
request: Request,
idsonde: str,
body: dict = Body(...),
db: Session = Depends(get_db),
):
if not (sonde := crud.get_sonde(db, idsonde)):
return # pragma: no cover
Notifier.error_sonde(idsonde)
# create fake sample
last = list(crud.get_mesure(db, sonde.sonde_id, only_last=1))[0]
from copy import copy
api_error = copy(last.content)
from datetime import datetime
date = str(datetime.now())
for channel in api_error["channels"]:
channel["status"] = "perte contact api"
api_error["date"] = date
post_sonde_data(request, idsonde, body=api_error, db=db)
return
@app.post("/sonde/{idsonde}/")
def post_sonde_data(
idsonde: str, body: dict = Body(...), db: Session = Depends(get_db)
request: Request,
idsonde: str,
body: dict = Body(...),
db: Session = Depends(get_db),
):
if not (sonde := crud.get_sonde(db, idsonde)):
return
@ -104,6 +195,13 @@ def post_sonde_data(
)
if content:
Notifier(idsonde, content)
res = last_notif_text(request, idsonde)
html = res.body.decode("utf-8")
from papi.mail_sendermodel import sendmail
cond = False
if cond:
sendmail(html)
return {
"count": len(mesures_)
if "date" in mesures_[0].content.keys()
@ -121,17 +219,18 @@ def get_rapport(idsonde):
else:
last = last.content
last = utils.prepare(last)
for name, data in sorted(
last["channels"].items(), key=lambda text: float(text[0].split("#")[0])
):
yield f'{name} {data["status"]}'
yield f'{name.split("#", 1)[1]} {data["status"]}'
@app.get("/sonde/{idsonde}/historique")
def historique(idsonde, db: Session = Depends(get_db)):
if not (sonde := crud.get_sonde(db, idsonde)):
return
mesures = sonde.mesures
return # pragma: no cover
mesures = crud.get_mesure(db, sonde.sonde_id)
for previous, present in zip(mesures, mesures[1:]):
date = present.content["date"]
@ -145,3 +244,38 @@ def historique(idsonde, db: Session = Depends(get_db)):
for d in diff["changements"]:
line = date, *utils.clean_state(d)
yield " ".join(line)
@app.get("/sonde/{idsonde}/historique/text")
def list_notification_as_text(
request: Request, idsonde: str, db: Session = Depends(get_db)
):
if not (sonde := crud.get_sonde(db, idsonde)):
return # pragma: no cover
def coloriser(message):
d = {"error": "red", "warning": "orange", "pending": "yellow", "ok": "green"}
for k, v in d.items():
if message.endswith(k):
return "color: %s;" % v
mesures = [x for x in crud.get_mesure(db, sonde.sonde_id, only_last=100)]
res = []
for previous, present in zip(mesures, mesures[1:]):
date = present.content["date"]
previous = utils.prepare(previous.content)
present = utils.prepare(present.content)
all_channels = sorted(set((*previous["channels"], *present["channels"])))
diff = utils.compare(all_channels, previous, present)
if diff:
for d in diff["changements"]:
line = date, *utils.clean_state(d)
res.append(" ".join(line))
return templates.TemplateResponse(
"historique.html",
context={"request": request, "lines": reversed(res), "coloriser": coloriser},
)

View File

@ -54,6 +54,7 @@ def forward(data):
for post_url in forward_urls:
res = session.post(post_url, json=data)
print(res.ok)
print(res.json())
def status2list(status: dict):

View File

@ -25,9 +25,11 @@ def create_mesure(db: Session, sonde_id: int, content: dict):
return db_mesure
def get_mesure(db: Session, sonde_id: int, only_last=False):
def get_mesure(db: Session, sonde_id: int, only_last: int = 0):
q = db.query(models.Mesure).filter(models.Mesure.sonde_id == sonde_id)
if not only_last:
return q.all()
else:
return [q.all()[-1]] # order by id desc limit 1
q = q.order_by(models.Mesure.mesure_id.desc()).limit(only_last)
return list(reversed(q.all())) # order by id desc limit 1

View File

@ -56,7 +56,8 @@ def compare(channels, previous, current):
def clean_state(state):
# Ote l'identifiant en début de chaine
return state[0].split("#", 1)[1], *state[1:]
return state[0].split("#", 1)[1], state[1], "->", state[2]
def list_channels(p, c):
@ -115,6 +116,7 @@ def make_id_key(channel, keys=None, sep="#", tuple_=False):
return {kvalue: channel}
"""
def raw_filename():
return "raw_" + str(datetime.date.today()).replace("-", "_") + ".json"
@ -146,4 +148,6 @@ def savediff(date, diff, *, filename=diff_filename):
for d in diff:
data = {"date": date}
data.update(zip(("name", "before", "after"), d))
writer.writerow(data)
"""

109
poetry.lock generated
View File

@ -74,7 +74,7 @@ uvloop = ["uvloop (>=0.15.2)"]
name = "certifi"
version = "2021.5.30"
description = "Python package for providing Mozilla's CA Bundle."
category = "dev"
category = "main"
optional = false
python-versions = "*"
@ -82,7 +82,7 @@ python-versions = "*"
name = "charset-normalizer"
version = "2.0.6"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "dev"
category = "main"
optional = false
python-versions = ">=3.5.0"
@ -195,10 +195,43 @@ test = ["Cython (==0.29.22)"]
name = "idna"
version = "3.2"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "dev"
category = "main"
optional = false
python-versions = ">=3.5"
[[package]]
name = "jinja2"
version = "3.0.1"
description = "A very fast and expressive template engine."
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
MarkupSafe = ">=2.0"
[package.extras]
i18n = ["Babel (>=2.7)"]
[[package]]
name = "mailjet-rest"
version = "1.3.4"
description = "Mailjet V3 API wrapper"
category = "main"
optional = false
python-versions = "*"
[package.dependencies]
requests = ">=2.4.3"
[[package]]
name = "markupsafe"
version = "2.0.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "main"
optional = false
python-versions = ">=3.6"
[[package]]
name = "mccabe"
version = "0.6.1"
@ -411,7 +444,7 @@ python-versions = "*"
name = "requests"
version = "2.26.0"
description = "Python HTTP for Humans."
category = "dev"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
@ -496,7 +529,7 @@ python-versions = "*"
name = "urllib3"
version = "1.26.6"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "dev"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
@ -568,7 +601,7 @@ python-versions = ">=3.7"
[metadata]
lock-version = "1.1"
python-versions = "^3.9"
content-hash = "76743b3324f5a77d33919708ffcf63515ea12024f618338503683ca1a1d8405b"
content-hash = "3ec44b61bba180c6ddba65f7112199812d58584ed5a7b9524d7ef37202e371b6"
[metadata.files]
asgiref = [
@ -750,6 +783,70 @@ idna = [
{file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
{file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
]
jinja2 = [
{file = "Jinja2-3.0.1-py3-none-any.whl", hash = "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4"},
{file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"},
]
mailjet-rest = [
{file = "mailjet_rest-1.3.4-py3-none-any.whl", hash = "sha256:635d53ac3fd61020f309c24ee977ae3458654ab39f9c36fc4b50c74e5d8ad410"},
{file = "mailjet_rest-1.3.4.tar.gz", hash = "sha256:e02663fa0369543bcd48c37a146e8143bb12b9f3512af2d5ba6dfbcc99e64a2d"},
]
markupsafe = [
{file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"},
{file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"},
{file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"},
{file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"},
{file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"},
{file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"},
{file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
{file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"},
{file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"},
{file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
{file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
]
mccabe = [
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},

View File

@ -9,6 +9,8 @@ python = "^3.9"
fastapi = "^0.68.1"
uvicorn = {extras = ["standard"], version = "^0.15.0"}
SQLAlchemy = "^1.4.25"
Jinja2 = "^3.0.1"
mailjet-rest = "^1.3.4"
[tool.poetry.dev-dependencies]
pytest = "^5.2"

18
templates/historique.html Normal file
View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Historique </title>
</head>
<body style="background: lightgray;">
<p> Changements </p>
{% for changement in lines %}
<p style="{{ coloriser(changement) }}"> {{changement}} </p>
{% endfor %}
</body>
</html>

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Email de notification</title>
</head>
<body style="background: lightgray;">
<p> Destinataires {{ ''.join(data['recipients']) }} </p>
{% if data['changements'] %}
<p> Changements </p>
{% for changement in data['changements'] %}
<p style="{{ coloriser(changement) }}"> {{changement}} </p>
{% endfor %}
{% endif %}
{% if data['status'] %}
<p> État courant </p>
{% for status in data['status'] %}
<p style="{{ coloriser(status) }}"> {{status}} </p>
{% endfor %}
{% endif %}
</body>
</html>

View File

@ -5,13 +5,39 @@ import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from papi.main import app
from papi.main import app, get_db
from papi.main import sondes
from papi import __version__
from . import utils as testutils
from papi.sqlapp.database import Base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./test_sql_app.db"
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base.metadata.create_all(bind=engine)
def override_get_db():
try:
db = TestingSessionLocal()
yield db
finally:
db.close()
app.dependency_overrides[get_db] = override_get_db
client = TestClient(app)
@ -62,7 +88,7 @@ def test_sample_report():
report = client.get(f"/sonde/{id_}/rapport")
rjson = report.json()
assert len(rjson) == 1
assert rjson[0] == "-1#Test channel ok"
assert rjson[0] == "Test channel ok"
data["channels"][0]["status"] = "error"
response = client.post(f"/sonde/{id_}/", json=data)
@ -70,7 +96,7 @@ def test_sample_report():
report = client.get(f"/sonde/{id_}/rapport")
rjson = report.json()
assert len(rjson) == 1
assert rjson[0] == "-1#Test channel error"
assert rjson[0] == "Test channel error"
def test_historique():
@ -79,16 +105,16 @@ def test_historique():
assert client.post("/sonde/", json=histo).ok
data = testutils.probe_sample_body(
data_ok = testutils.probe_sample_body(
channel_name="test_historique", channel_id=0, status="ok"
)
response = client.post(f"/sonde/{id_sonde}/", json=data)
response = client.post(f"/sonde/{id_sonde}/", json=data_ok)
assert response.ok
debut_supervision = client.get(f"/sonde/{id_sonde}/historique")
debut_supervision = debut_supervision.json()
assert len(debut_supervision) == 1
assert debut_supervision[0] == f"{data['date']} test_historique absent ok"
assert debut_supervision[0] == f"{data_ok['date']} test_historique absent -> ok"
data = testutils.probe_sample_body(
channel_name="test_historique", channel_id=0, status="error"
@ -98,7 +124,7 @@ def test_historique():
ok_erreur_supervision = client.get(f"/sonde/{id_sonde}/historique")
ok_erreur_supervision = ok_erreur_supervision.json()
assert ok_erreur_supervision[-1] == f"{data['date']} test_historique ok error"
assert ok_erreur_supervision[-1] == f"{data['date']} test_historique ok -> error"
data = testutils.probe_sample_body(
channel_name="test_historique", channel_id=0, status="error"
@ -109,7 +135,29 @@ def test_historique():
perte_supervision = client.get(f"/sonde/{id_sonde}/historique")
perte_supervision = perte_supervision.json()
assert perte_supervision[-1] == f"{data['date']} test_historique error absent"
assert perte_supervision[-1] == f"{data['date']} test_historique error -> absent"
# perte api et repise
from papi.main import notifications
notifs = notifications[id_sonde]
response = client.post(f"/sonde/{id_sonde}/", json=data_ok)
perte_api = client.post(f"/sonde/{id_sonde}/error", json={})
perte_api_rapport = client.get(f"/sonde/{id_sonde}/rapport")
assert "perte contact api" in perte_api_rapport.text
assert perte_api.ok
response = client.post(f"/sonde/{id_sonde}/", json=data_ok)
def test_historique_rendering():
idsonde = "masonde_001"
notifs_text = client.get(f"/sonde/{idsonde}/historique/text")
assert notifs_text.ok
content = notifs_text
assert f"absent" in content.text.lower()
def test_onchange_notification():
@ -131,7 +179,7 @@ def test_onchange_notification():
jresp = response.json()
assert jresp["notify"]
assert jresp["notify"][0].split(" ", 1)[1] == "test_historique absent ok"
assert jresp["notify"][0].split(" ", 1)[1] == "test_historique absent -> ok"
data = testutils.probe_sample_body(
channel_name="test_historique", channel_id=0, status="ok"
@ -148,6 +196,14 @@ def test_onchange_notification():
assert len(notifs.json()) == 1
def test_notif_rendering():
idsonde = "masonde_001"
notifs_text = client.get(f"/notifications/{idsonde}/text")
assert notifs_text.ok
content = notifs_text
assert f"{idsonde}@fqdn" in content.text.lower()
class CodeCoverageTestCase(TestCase):
""" Get covergage to 100% """