Skip to content

Commit

Permalink
Merge branch 'main' into bug-2025-workflow-execution
Browse files Browse the repository at this point in the history
  • Loading branch information
rajesh-jonnalagadda authored Oct 30, 2024
2 parents d78d02a + 7e2df16 commit cee6f96
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Fix broken links between alerts and incidents
Revision ID: 991b30bcf0b9
Revises: 89b4d3905d26
Create Date: 2024-10-29 18:37:28.668473
"""

import sqlalchemy as sa
from alembic import op
import logging

# revision identifiers, used by Alembic.
revision = "991b30bcf0b9"
down_revision = "89b4d3905d26"
branch_labels = None
depends_on = None

logger = logging.getLogger(__name__)

def upgrade() -> None:
connection = op.get_bind()
if connection.dialect.name == 'sqlite':
logger.info("""Migration 83c1020be97d corrupted alert_to_incident.deleted_at at SQLite databases
because server_default was set to \"1000-01-01 00:00:00\", not \"1000-01-01 00:00:00.000000\".
Fixing the value in this migration.""")

# Filtering only by deleted_at = '1000-01-01 00:00:00'. If deleted_at is different, it should be already formated well.
result = connection.execute(sa.text("SELECT incident_id, alert_id, deleted_at FROM alerttoincident WHERE deleted_at = '1000-01-01 00:00:00'"))
db_datetime_format = "%Y-%m-%d %H:%M:%S.%f"
print(f"Database datetime format: {db_datetime_format}")
for row in result:
try:
connection.execute(
sa.text(
"UPDATE alerttoincident SET deleted_at = '1000-01-01 00:00:00.000000' WHERE incident_id = :incident_id AND alert_id = :alert_id AND deleted_at = '1000-01-01 00:00:00'"
),
{"incident_id": row["incident_id"], "alert_id": row["alert_id"]}
)
print(f"Updated deleted_at for incident_id: {row['incident_id']}, alert_id: {row['alert_id']}")
except sa.exc.IntegrityError as e:
if "UNIQUE constraint failed: alerttoincident.alert_id, alerttoincident.incident_id, alerttoincident.deleted_at" in str(e):
connection.execute(
sa.text(
"DELETE FROM alerttoincident WHERE incident_id = :incident_id AND alert_id = :alert_id AND deleted_at = '1000-01-01 00:00:00'"
),
{"incident_id": row["incident_id"], "alert_id": row["alert_id"]}
)
logger.warning(f"IntegrityError encountered for incident_id: {row['incident_id']}, alert_id: {row['alert_id']}. It's a duplicate. Deleted.")
else:
raise e
else:
logger.info("Skipping the fix since it's not SQLite.")

# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###
91 changes: 47 additions & 44 deletions keep/providers/smtp_provider/smtp_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

import dataclasses
import typing

import pydantic
from smtplib import SMTP, SMTP_SSL
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from smtplib import SMTP, SMTP_SSL

import pydantic

from keep.contextmanager.contextmanager import ContextManager
from keep.providers.base.base_provider import BaseProvider
Expand All @@ -17,23 +17,6 @@

@pydantic.dataclasses.dataclass
class SmtpProviderAuthConfig:
smtp_username: str = dataclasses.field(
metadata={
"required": True,
"description": "SMTP username",
"config_main_group": "authentication",
}
)

smtp_password: str = dataclasses.field(
metadata={
"required": True,
"sensitive": True,
"description": "SMTP password",
"config_main_group": "authentication",
}
)

smtp_server: str = dataclasses.field(
metadata={
"required": True,
Expand All @@ -47,7 +30,8 @@ class SmtpProviderAuthConfig:
"required": True,
"description": "SMTP port",
"config_main_group": "authentication",
}
},
default=587,
)

encryption: typing.Literal["SSL", "TLS"] = dataclasses.field(
Expand All @@ -61,6 +45,25 @@ class SmtpProviderAuthConfig:
},
)

smtp_username: str = dataclasses.field(
metadata={
"required": False,
"description": "SMTP username",
"config_main_group": "authentication",
},
default="",
)

smtp_password: str = dataclasses.field(
metadata={
"required": False,
"sensitive": True,
"description": "SMTP password",
"config_main_group": "authentication",
},
default="",
)


class SmtpProvider(BaseProvider):
PROVIDER_SCOPES = [
Expand All @@ -75,18 +78,18 @@ class SmtpProvider(BaseProvider):
PROVIDER_DISPLAY_NAME = "SMTP"

def __init__(
self, context_manager: ContextManager, provider_id: str, config: ProviderConfig
self, context_manager: ContextManager, provider_id: str, config: ProviderConfig
):
super().__init__(context_manager, provider_id, config)

def dispose(self):
pass

def validate_config(self):
self.authentication_config = SmtpProviderAuthConfig(
**self.config.authentication
)

def validate_scopes(self):
"""
Validate that the scopes provided are correct.
Expand All @@ -97,7 +100,7 @@ def validate_scopes(self):
return {"send_email": True}
except Exception as e:
return {"send_email": str(e)}

def generate_smtp_client(self):
"""
Generate an SMTP client.
Expand All @@ -108,28 +111,30 @@ def generate_smtp_client(self):
smtp_port = self.authentication_config.smtp_port
encryption = self.authentication_config.encryption

if (encryption == "SSL"):
if encryption == "SSL":
smtp = SMTP_SSL(smtp_server, smtp_port)
smtp.login(smtp_username, smtp_password)
return smtp

elif (encryption == "TLS"):
elif encryption == "TLS":
smtp = SMTP(smtp_server, smtp_port)
smtp.starttls()

if smtp_username and smtp_password:
smtp.login(smtp_username, smtp_password)
return smtp

def send_email(self, from_email: str, from_name: str, to_email: str, subject: str, body: str):

return smtp

def send_email(
self, from_email: str, from_name: str, to_email: str, subject: str, body: str
):
"""
Send an email using SMTP protocol.
"""
msg = MIMEMultipart()
if from_name == "":
msg["From"] = from_email
msg["From"] = f"{from_name} <{from_email}>"
msg['To'] = to_email
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
msg["To"] = to_email
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain"))

try:
smtp = self.generate_smtp_client()
Expand All @@ -138,18 +143,16 @@ def send_email(self, from_email: str, from_name: str, to_email: str, subject: st

except Exception as e:
raise Exception(f"Failed to send email: {str(e)}")

def _notify(self, from_email: str, from_name: str, to_email: str, subject: str, body: str):

def _notify(
self, from_email: str, from_name: str, to_email: str, subject: str, body: str
):
"""
Send an email using SMTP protocol.
"""
self.send_email(from_email, from_name, to_email, subject, body)
return {
"from": from_email,
"to": to_email,
"subject": subject,
"body": body
}
return {"from": from_email, "to": to_email, "subject": subject, "body": body}


if __name__ == "__main__":
import logging
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "keep"
version = "0.27.7"
version = "0.27.8"
description = "Alerting. for developers, by developers."
authors = ["Keep Alerting LTD"]
readme = "README.md"
Expand Down

0 comments on commit cee6f96

Please sign in to comment.