Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AquaComms #75

Merged
merged 11 commits into from
Sep 14, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions circuit_maintenance_parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from .errors import NonexistentProviderError, ProviderError
from .provider import (
GenericProvider,
AquaComms,
Cogent,
Colt,
EUNetworks,
Expand All @@ -26,6 +27,7 @@

SUPPORTED_PROVIDERS = (
GenericProvider,
AquaComms,
Cogent,
Colt,
EUNetworks,
Expand Down
78 changes: 78 additions & 0 deletions circuit_maintenance_parser/parsers/aquacomms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""Turkcell parser."""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Turkcell parser."""
"""AquaComms parser."""

import logging
import re
from datetime import datetime

from circuit_maintenance_parser.parser import EmailSubjectParser, Html, Impact, CircuitImpact, Status

# pylint: disable=too-many-nested-blocks, too-many-branches

logger = logging.getLogger(__name__)


class SubjectParserAquaComms1(EmailSubjectParser):
"""Parser for Seaborn subject string, email type 1."""

def parse_subject(self, subject):
"""Parse subject of email file.

Subject: Aqua Comms Planned Outage Work ISSUE=111111 PROJ=999
"""
data = {}
search = re.search(r"ISSUE=([0-9]+).PROJ=([0-9]+)", subject)
if search:
data["maintenance_id"] = search.group(1)
data["account"] = search.group(2)
return [data]


class HtmlParserAquaComms1(Html):
"""Notifications Parser for AquaComms notifications."""

def parse_html(self, soup):
"""Execute parsing."""
data = {}
self.parse_tables(soup.find_all("table"), data)
return [data]

@staticmethod
def get_tr_value(element):
"""Remove new lines and split key to value."""
return element.text.replace("\n", "").split(": ")[1].strip()

def parse_tables(self, tables, data):
"""Parse HTML tables.

<table>
<tbody>
<tr>
<td><font>Ticket Number:</font></td>
<td><font>11111</font></td>
</tr>
<tr>
<td><font>Scheduled Start Date & Time:</font></td>
<td><font>22:00 12/10/2020 GMT</font></td>
</tr>
<tr>
<td><font>Scheduled End Date & Time:</font></td>
<td><font>22:00 12/10/2020 GMT</font></td>
</tr>
...
</tbody>
</table>
"""
for table in tables:
for tr_element in table.find_all("tr"):
if "ticket number" in tr_element.text.lower():
data["maintenance_id"] = self.get_tr_value(tr_element)
elif "update" in tr_element.text.lower():
data["summary"] = tr_element.text.replace("\n", "").split(" - ")[1]
elif "scheduled start date" in tr_element.text.lower():
data["start"] = self.dt2ts(datetime.strptime(self.get_tr_value(tr_element), "%H:%M %d/%m/%Y %Z"))
elif "scheduled end date" in tr_element.text.lower():
data["end"] = self.dt2ts(datetime.strptime(self.get_tr_value(tr_element), "%H:%M %d/%m/%Y %Z"))
elif "service id" in tr_element.text.lower():
data["circuits"] = [
CircuitImpact(circuit_id=self.get_tr_value(tr_element), impact=Impact("OUTAGE"))
]
data["status"] = Status.CONFIRMED
10 changes: 10 additions & 0 deletions circuit_maintenance_parser/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from circuit_maintenance_parser.errors import ProcessorError, ProviderError
from circuit_maintenance_parser.processor import CombinedProcessor, SimpleProcessor, GenericProcessor

from circuit_maintenance_parser.parsers.aquacomms import HtmlParserAquaComms1, SubjectParserAquaComms1
from circuit_maintenance_parser.parsers.cogent import HtmlParserCogent1
from circuit_maintenance_parser.parsers.colt import ICalParserColt1, CsvParserColt1
from circuit_maintenance_parser.parsers.gtt import HtmlParserGTT1
Expand Down Expand Up @@ -105,6 +106,15 @@ def get_provider_type(cls) -> str:
####################


class AquaComms(GenericProvider):
"""AquaComms provider custom class."""

_processors: List[GenericProcessor] = [
CombinedProcessor(data_parsers=[EmailDateParser, HtmlParserAquaComms1, SubjectParserAquaComms1]),
]
_default_organizer = "[email protected]"


class Cogent(GenericProvider):
"""Cogent provider custom class."""

Expand Down
91 changes: 91 additions & 0 deletions tests/unit/data/aquacomms/aquacomms1.eml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
MIME-Version: 1.0
Date: Thu, 26 Aug 2021 18:22:09 +0100
Subject: Aqua Comms Planned Outage Work ISSUE=11111 PROJ=999
Content-Type: multipart/alternative; boundary="000000000000015b7605ca799cf2"

--000000000000015b7605ca799cf2
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<font face=3D"Arial, Verdana, Helvetica, sans-serif" size=3D"2">
When replying, type your text above this line.
<hr>
<br>
<table border=3D"0" cellpadding=3D"0" cellspacing=3D"0">
<tbody><tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, Hel=
vetica, sans-serif" size=3D"2">Dear Network to Code,<br><br></font></td>
</tr>
<tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, Hel=
vetica, sans-serif" size=3D"2">This notice is being sent to notify you of t=
he following Maintenance Event.<br><br></font></td>
</tr>

</tbody></table>
<table border=3D"0" cellpadding=3D"0" cellspacing=3D"0">
<tbody><tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, Hel=
vetica, sans-serif" size=3D"2"><b> Ticket Number: </b></font></td>
<td valign=3D"TOP" align=3D"LEFT" style=3D"padding-left:10px"><font=
face=3D"Arial, Verdana, Helvetica, sans-serif" size=3D"2"> 11111</font></t=
d>
</tr>
<tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, Hel=
vetica, sans-serif" size=3D"2"><b> Scheduled Start Date &amp; Time: </b></f=
ont></td>
<td valign=3D"TOP" align=3D"LEFT" style=3D"padding-left:10px"><font=
face=3D"Arial, Verdana, Helvetica, sans-serif" size=3D"2"> 22:00 12/10/202=
0 GMT</font></td>
</tr>
<tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, Hel=
vetica, sans-serif" size=3D"2"><b> Scheduled End Date &amp; Time: </b></fon=
t></td>
<td valign=3D"TOP" align=3D"LEFT" style=3D"padding-left:10px"><font=
face=3D"Arial, Verdana, Helvetica, sans-serif" size=3D"2"> 08:00 13/10/202=
0 GMT</font></td>
</tr>
=20
<tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, Hel=
vetica, sans-serif" size=3D"2"><b> Service ID: </b></font></td>
<td valign=3D"TOP" align=3D"LEFT" style=3D"padding-left:10px"><font=
face=3D"Arial, Verdana, Helvetica, sans-serif" size=3D"2">111-AAA-11-11BB-=
33333</font></td>
</tr>
=20
</tbody></table>
<br>
<table border=3D"0" cellpadding=3D"0" cellspacing=3D"0">
<tbody><tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, Hel=
vetica, sans-serif" size=3D"2">Please note that all time stamps below will =
appear in US Central time.<br><br></font></td>
</tr>
=20
=20
<tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, H=
elvetica, sans-serif" size=3D"2">- Update - There are no new updates.<br></=
font></td>
</tr>
glennmatthews marked this conversation as resolved.
Show resolved Hide resolved
=20
=20
<tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, H=
elvetica, sans-serif" size=3D"2"><br></font></td>
</tr>
<tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, Hel=
vetica, sans-serif" size=3D"2">Sincerely,</font></td>
</tr>
<tr>
<td valign=3D"TOP" align=3D"LEFT"><font face=3D"Arial, Verdana, Hel=
vetica, sans-serif" size=3D"2">Aqua Comms NOC</font></td>
</tr>
</tbody></table>
</font>

--000000000000015b7605ca799cf2--
15 changes: 15 additions & 0 deletions tests/unit/data/aquacomms/aquacomms1_html_parser_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[
{
"circuits": [
{
"circuit_id": "111-AAA-11-11BB-33333",
"impact": "OUTAGE"
}
],
"end": 1602576000,
"maintenance_id": "11111",
"start": 1602540000,
"status": "CONFIRMED",
"summary": "There are no new updates."
}
]
21 changes: 21 additions & 0 deletions tests/unit/data/aquacomms/aquacomms1_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[
{
"account": "999",
"circuits": [
{
"circuit_id": "111-AAA-11-11BB-33333",
"impact": "OUTAGE"
}
],
"end": 1602576000,
"maintenance_id": "11111",
"organizer": "[email protected]",
"provider": "aquacomms",
"sequence": 1,
"stamp": 1629998529,
"start": 1602540000,
"status": "CONFIRMED",
"summary": "There are no new updates.",
"uid": "0"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"account": "999",
"maintenance_id": "11111"
}
]
7 changes: 7 additions & 0 deletions tests/unit/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# pylint: disable=duplicate-code
from circuit_maintenance_parser.provider import (
GenericProvider,
AquaComms,
Cogent,
Colt,
EUNetworks,
Expand Down Expand Up @@ -40,6 +41,12 @@
[
# GenericProvider
(GenericProvider, [("ical", GENERIC_ICAL_DATA_PATH),], [GENERIC_ICAL_RESULT_PATH,],),
# AquaComms
(
AquaComms,
[("email", Path(dir_path, "data", "aquacomms", "aquacomms1.eml")),],
[Path(dir_path, "data", "aquacomms", "aquacomms1_result.json"),],
),
# Cogent
(
Cogent,
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/test_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from circuit_maintenance_parser.errors import ParserError
from circuit_maintenance_parser.parser import ICal, EmailDateParser
from circuit_maintenance_parser.parsers.aquacomms import HtmlParserAquaComms1, SubjectParserAquaComms1
from circuit_maintenance_parser.parsers.cogent import HtmlParserCogent1
from circuit_maintenance_parser.parsers.colt import ICalParserColt1, CsvParserColt1
from circuit_maintenance_parser.parsers.gtt import HtmlParserGTT1
Expand Down Expand Up @@ -38,6 +39,17 @@
(ICal, Path(dir_path, "data", "ical", "ical3"), Path(dir_path, "data", "ical", "ical3_result.json"),),
(ICal, Path(dir_path, "data", "ical", "ical4"), Path(dir_path, "data", "ical", "ical4_result.json"),),
(ICal, Path(dir_path, "data", "ical", "ical5"), Path(dir_path, "data", "ical", "ical5_result.json"),),
# AquaComms
(
HtmlParserAquaComms1,
Path(dir_path, "data", "aquacomms", "aquacomms1.eml"),
Path(dir_path, "data", "aquacomms", "aquacomms1_html_parser_result.json"),
),
(
SubjectParserAquaComms1,
Path(dir_path, "data", "aquacomms", "aquacomms1.eml"),
Path(dir_path, "data", "aquacomms", "aquacomms1_subject_parser_result.json"),
),
# Cogent
(
HtmlParserCogent1,
Expand Down