Move package to src/ to properly separate what goes into docker image

This commit is contained in:
Einar Forselv
2019-12-05 10:26:46 +01:00
parent 0af9f2e8ee
commit 130be30268
19 changed files with 2 additions and 2 deletions

View File

@@ -0,0 +1,44 @@
import logging
from restic_compose_backup.alerts.smtp import SMTPAlert
from restic_compose_backup.alerts.discord import DiscordWebhookAlert
from restic_compose_backup.config import Config
logger = logging.getLogger(__name__)
ALERT_INFO = 'INFO',
ALERT_ERROR = 'ERROR'
ALERT_TYPES = [ALERT_INFO, ALERT_ERROR]
BACKENDS = [SMTPAlert, DiscordWebhookAlert]
def send(subject: str = None, body: str = None, alert_type: str = 'INFO'):
"""Send alert to all configured backends"""
alert_classes = configured_alert_types()
for instance in alert_classes:
logger.info('Configured: %s', instance.name)
try:
instance.send(
subject=f'[{alert_type}] {subject}',
body=body,
)
except Exception as ex:
logger.error("Exception raised when sending alert [%s]: %s", instance.name, ex)
logger.exception(ex)
if len(alert_classes) == 0:
logger.info("No alerts configured")
def configured_alert_types():
"""Returns a list of configured alert class instances"""
logger.debug('Getting alert backends')
entires = []
for cls in BACKENDS:
instance = cls.create_from_env()
logger.debug("Alert backend '%s' configured: %s", cls.name, instance != None)
if instance:
entires.append(instance)
return entires

View File

@@ -0,0 +1,14 @@
class BaseAlert:
name = None
def create_from_env(self):
return None
@property
def properly_configured(self) -> bool:
return False
def send(self, subject: str = None, body: str = None, alert_type: str = None):
pass

View File

@@ -0,0 +1,46 @@
import os
import logging
from urllib.parse import urlparse
import requests
from restic_compose_backup.alerts.base import BaseAlert
logger = logging.getLogger(__name__)
class DiscordWebhookAlert(BaseAlert):
name = 'discord_webhook'
success_codes = [200]
def __init__(self, webhook_url):
self.url = webhook_url
@classmethod
def create_from_env(cls):
instance = cls(os.environ.get('DISCORD_WEBHOOK'))
if instance.properly_configured:
return instance
return None
@property
def properly_configured(self) -> bool:
return isinstance(self.url, str) and self.url.startswith("https://")
def send(self, subject: str = None, body: str = None, alert_type: str = None):
"""Send basic webhook request. Max embed size is 6000"""
logger.info("Triggering discord webhook")
data = {
'embeds': [
{
'title': subject,
'description': body[:5000],
},
]
}
response = requests.post(self.url, params={'wait': True}, json=data)
if response.status_code not in self.success_codes:
log.error("Discord webhook failed: %s: %s", response.status_code, response.content)
else:
logger.info('Discord webhook successful')

View File

@@ -0,0 +1,56 @@
import os
import smtplib
import logging
from email.mime.text import MIMEText
from restic_compose_backup.alerts.base import BaseAlert
logger = logging.getLogger(__name__)
class SMTPAlert(BaseAlert):
name = 'smtp'
def __init__(self, host, port, user, password, to):
self.host = host
self.port = port
self.user = user
self.password = password
self.to = to
@classmethod
def create_from_env(cls):
instance = cls(
os.environ.get('EMAIL_HOST'),
os.environ.get('EMAIL_PORT'),
os.environ.get('EMAIL_HOST_USER'),
os.environ.get('EMAIL_HOST_PASSWORD'),
(os.environ.get('EMAIL_SEND_TO') or "").split(','),
)
if instance.properly_configured:
return instance
return None
@property
def properly_configured(self) -> bool:
return self.host and self.port and self.user and self.password and len(self.to) > 0
def send(self, subject: str = None, body: str = None, alert_type: str = 'INFO'):
# send_mail("Hello world!")
msg = MIMEText(body)
msg['Subject'] = f"[{alert_type}] {subject}"
msg['From'] = self.user
msg['To'] = ', '.join(self.to)
try:
logger.info("Connecting to %s port %s", self.host, self.port)
server = smtplib.SMTP_SSL(self.host, self.port)
server.ehlo()
server.login(self.user, self.password)
server.sendmail(self.user, self.to, msg.as_string())
logger.info('Email sent')
except Exception as ex:
logger.exception(ex)
finally:
server.close()