diff --git a/README.md b/README.md index 235fb501..0f5c248a 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ You can leverage this library in your automation framework to process circuit ma - **provider**: identifies the provider of the service that is the subject of the maintenance notification. - **account**: identifies an account associated with the service that is the subject of the maintenance notification. - **maintenance_id**: contains text that uniquely identifies (at least within the context of a specific provider) the maintenance that is the subject of the notification. -- **circuits**: list of circuits affected by the maintenance notification and their specific impact. Note that in a maintenance canceled notification, some providers omit the circuit list, so this may be blank for maintenance notifications with a status of CANCELLED. +- **circuits**: list of circuits affected by the maintenance notification and their specific impact. Note that in a maintenance canceled or completed notification, some providers omit the circuit list, so this may be blank for maintenance notifications with a status of CANCELLED or COMPLETED. - **start**: timestamp that defines the starting date/time of the maintenance in GMT. - **end**: timestamp that defines the ending date/time of the maintenance in GMT. - **stamp**: timestamp that defines the update date/time of the maintenance in GMT. @@ -71,6 +71,7 @@ By default, there is a `GenericProvider` that supports a `SimpleProcessor` using - BSO - Cogent - Colt +- Crown Castle Fiber - Equinix - EXA (formerly GTT) - HGC diff --git a/circuit_maintenance_parser/__init__.py b/circuit_maintenance_parser/__init__.py index e003b085..f22c54d2 100644 --- a/circuit_maintenance_parser/__init__.py +++ b/circuit_maintenance_parser/__init__.py @@ -12,6 +12,7 @@ BSO, Cogent, Colt, + CrownCastle, Equinix, EUNetworks, GTT, @@ -39,6 +40,7 @@ BSO, Cogent, Colt, + CrownCastle, Equinix, EUNetworks, GTT, diff --git a/circuit_maintenance_parser/output.py b/circuit_maintenance_parser/output.py index 98892f2a..43bc383f 100644 --- a/circuit_maintenance_parser/output.py +++ b/circuit_maintenance_parser/output.py @@ -108,7 +108,8 @@ class Maintenance(BaseModel, extra=Extra.forbid): account: identifies an account associated with the service that is the subject of the maintenance notification maintenance_id: contains text that uniquely identifies the maintenance that is the subject of the notification circuits: list of circuits affected by the maintenance notification and their specific impact. Note this can be - an empty list for notifications with a CANCELLED status if the provider does not populate the circuit list. + an empty list for notifications with a CANCELLED or COMPLETED status if the provider does not populate the + circuit list. status: defines the overall status or confirmation for the maintenance start: timestamp that defines the start date of the maintenance in GMT end: timestamp that defines the end date of the maintenance in GMT @@ -184,7 +185,7 @@ def validate_empty_strings(cls, value): @validator("circuits") def validate_empty_circuits(cls, value, values): """Validate non-cancel notifications have a populated circuit list.""" - if len(value) < 1 and values["status"] != "CANCELLED": + if len(value) < 1 and str(values["status"]) in ("CANCELLED", "COMPLETED"): raise ValueError("At least one circuit has to be included in the maintenance") return value diff --git a/circuit_maintenance_parser/parsers/crowncastle.py b/circuit_maintenance_parser/parsers/crowncastle.py new file mode 100644 index 00000000..855814d5 --- /dev/null +++ b/circuit_maintenance_parser/parsers/crowncastle.py @@ -0,0 +1,90 @@ +"""Crown Castle Fiber parser.""" +import logging +import re +from datetime import datetime + +from circuit_maintenance_parser.parser import Html, Impact, CircuitImpact, Status + +# pylint: disable=too-many-nested-blocks, too-many-branches + +logger = logging.getLogger(__name__) + + +class HtmlParserCrownCastle1(Html): + """Notifications Parser for Crown Castle Fiber notifications.""" + + def parse_html(self, soup): + """Execute parsing.""" + data = {} + data["circuits"] = [] + + data["status"] = self.get_status(soup) + + for paragraph in soup.find_all("p"): + for pstring in paragraph.strings: + search = re.match(r"^Dear (.*),", pstring) + if search: + data["account"] = search.group(1) + + self.parse_strong(soup, data) + + table = soup.find("table", "timezonegrid") + for row in table.find_all("tr"): + cols = row.find_all("td") + if len(cols) == 5: + if cols[4].string.strip() == "GMT": + st_dt = cols[0].string.strip() + " " + cols[1].string.strip() + " GMT" + en_dt = cols[2].string.strip() + " " + cols[3].string.strip() + " GMT" + data["start"] = self.dt2ts(datetime.strptime(st_dt, "%m/%d/%Y %I:%M %p %Z")) + data["end"] = self.dt2ts(datetime.strptime(en_dt, "%m/%d/%Y %I:%M %p %Z")) + + table = soup.find("table", id="circuitgrid") + if table is not None: + for row in table.find_all("tr"): + cols = row.find_all("td") + if len(cols) == 6: + if cols[4].string.strip() == "None": + impact = Impact("NO-IMPACT") + else: + impact = Impact("OUTAGE") + data["circuits"].append(CircuitImpact(impact=impact, circuit_id=cols[0].string.strip())) + + return [data] + + def parse_strong(self, soup, data): + """Parse the strong tags, to find summary and maintenance ID info.""" + for strong in soup.find_all("strong"): + if strong.string.strip() == "Ticket Number:": + data["maintenance_id"] = strong.next_sibling.strip() + if strong.string.strip() == "Description:": + summary = strong.parent.next_sibling.next_sibling.contents[0].string.strip() + summary = re.sub(r"[\n\r]", "", summary) + data["summary"] = summary + if strong.string.strip().startswith("Work Description:"): + for sibling in strong.parent.next_siblings: + summary = "".join(sibling.strings) + summary = re.sub(r"[\n\r]", "", summary) + if summary != "": + data["summary"] = summary + break + + def get_status(self, soup): + """Get the status of the maintenance.""" + for paragraph in soup.find_all("p"): + for pstring in paragraph.strings: + if "has been completed." in pstring: + return Status("COMPLETED") + + for underline in soup.find_all("u"): + if underline.string is None: + continue + if underline.string.strip() == "Maintenance Notification": + return Status("CONFIRMED") + if underline.string.strip() == "Emergency Notification": + return Status("CONFIRMED") + if underline.string.strip() == "Maintenance Notification - Rescheduled Event": + return Status("RE-SCHEDULED") + if underline.string.strip() == "Maintenance Cancellation Notification": + return Status("CANCELLED") + + return Status("NO-CHANGE") diff --git a/circuit_maintenance_parser/provider.py b/circuit_maintenance_parser/provider.py index d67cf8e8..cf40789a 100644 --- a/circuit_maintenance_parser/provider.py +++ b/circuit_maintenance_parser/provider.py @@ -23,6 +23,7 @@ from circuit_maintenance_parser.parsers.bso import HtmlParserBSO1 from circuit_maintenance_parser.parsers.cogent import HtmlParserCogent1, TextParserCogent1, SubjectParserCogent1 from circuit_maintenance_parser.parsers.colt import CsvParserColt1, SubjectParserColt1, SubjectParserColt2 +from circuit_maintenance_parser.parsers.crowncastle import HtmlParserCrownCastle1 from circuit_maintenance_parser.parsers.equinix import HtmlParserEquinix, SubjectParserEquinix from circuit_maintenance_parser.parsers.gtt import HtmlParserGTT1 from circuit_maintenance_parser.parsers.hgc import HtmlParserHGC1, HtmlParserHGC2, SubjectParserHGC1 @@ -225,6 +226,15 @@ class Colt(GenericProvider): _default_organizer = "PlannedWorks@colt.net" +class CrownCastle(GenericProvider): + """Crown Castle Fiber provider custom class.""" + + _processors: List[GenericProcessor] = [ + CombinedProcessor(data_parsers=[EmailDateParser, HtmlParserCrownCastle1]), + ] + _default_organizer = "fiberchangemgmt@crowncastle.com" + + class Equinix(GenericProvider): """Equinix provider custom class.""" diff --git a/tests/unit/data/crowncastle/crowncastle1.eml b/tests/unit/data/crowncastle/crowncastle1.eml new file mode 100644 index 00000000..db1cf659 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle1.eml @@ -0,0 +1,116 @@ +Delivered-To: noc@example.com +Message-ID: <1@FIBERCHANGEMGMT.CROWNCASTLE.COM> +MIME-Version: 1.0 +From: Change Management +To: NOC +Date: Tue, 10 Dec 2023 01:44:00 -0500 +Subject: Crown Castle Fiber Scheduled Maintenance Notification: CM20231201000 on 1/3/2024 3:00 AM EST +Content-Type: text/html; charset="utf-8" +Content-Transfer-Encoding: base64 + +PCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJlbiI+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1 +aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4NCjx0 +aXRsZT48L3RpdGxlPg0KPHN0eWxlPgogICAgICAgIC50aW1lem9uZWdyaWQsICNjaXJjdWl0Z3Jp +ZCB7CiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiBBcmlhbDsKICAgICAgICAgICAgYm9yZGVyLWNv +bGxhcHNlOiBjb2xsYXBzZTsKICAgICAgICAgICAgZm9udC1zaXplOiAxMnB4OwogICAgICAgIH0K +CiAgICAgICAgICAgIC50aW1lem9uZWdyaWQgdGQsIC50aW1lem9uZWdyaWQgdGgsICNjaXJjdWl0 +Z3JpZCB0ZCwgI2NpcmN1aXRncmlkIHRoIHsKICAgICAgICAgICAgICAgIGJvcmRlcjogMXB4IHNv +bGlkICNkZGQ7CiAgICAgICAgICAgICAgICBwYWRkaW5nOiA4cHg7CiAgICAgICAgICAgIH0KCiAg +ICAgICAgICAgIC50aW1lem9uZWdyaWQgdGhlYWQsICNjaXJjdWl0Z3JpZCB0aGVhZCB7CiAgICAg +ICAgICAgICAgICBwYWRkaW5nLXRvcDogMnB4OwogICAgICAgICAgICAgICAgcGFkZGluZy1ib3R0 +b206IDJweDsKICAgICAgICAgICAgICAgIGJvcmRlcjogMXB4IHNvbGlkICNkZGQ7CiAgICAgICAg +ICAgICAgICB0ZXh0LWFsaWduOiBsZWZ0OwogICAgICAgICAgICB9CgogICAgICAgIGJvZHkgewog +ICAgICAgICAgICBmb250LWZhbWlseTogQXJpYWw7CiAgICAgICAgICAgIGJvcmRlci1jb2xsYXBz +ZTogY29sbGFwc2U7CiAgICAgICAgICAgIGZvbnQtc2l6ZTogMTJweDsKICAgICAgICB9CiAgICA8 +L3N0eWxlPg0KPC9oZWFkPg0KPGJvZHk+DQo8ZGl2Pg0KPHRhYmxlIHN0eWxlPSJ3aWR0aDogOTAl +OyBib3JkZXI6bm9uZTsgYm9yZGVyLXNwYWNpbmc6MDsgcGFkZGluZzowOyI+DQo8dGJvZHk+DQo8 +dHI+DQo8dGQgdmFsaWduPSJ0b3AiPg0KPHAgYWxpZ249ImNlbnRlciI+PGI+PHU+PHNwYW4+PGlt +ZyBzcmM9Imh0dHBzOi8vdGVtcGdvLmNyb3duY2FzdGxlLmNvbS9ycy8zNDMtTFFSLTY1MC9pbWFn +ZXMvaW1hZ2UwMV9DQ0xvZ28yLnBuZyIgaGVpZ2h0PSI2NSIgd2lkdGg9IjI0NiI+PC9zcGFuPjwv +dT48L2I+PC9wPg0KPC90ZD4NCjwvdHI+DQo8dHI+DQo8dGQgdmFsaWduPSJ0b3AiPg0KPHAgYWxp +Z249ImNlbnRlciI+Jm5ic3A7PC9wPg0KPC90ZD4NCjwvdHI+DQo8dHI+DQo8dGQgdmFsaWduPSJ0 +b3AiPg0KPHAgYWxpZ249ImNlbnRlciI+PGI+PHNwYW4gc3R5bGU9ImNvbG9yOiM1QTY3NzE7Zm9u +dC1zaXplOjI0cHgiPjx1Pk1haW50ZW5hbmNlIE5vdGlmaWNhdGlvbjwvdT48L3NwYW4+PC9iPjwv +cD4NCjwvdGQ+DQo8L3RyPg0KPHRyPg0KPHRkPg0KPHA+PC9wPg0KPC90ZD4NCjwvdHI+DQo8dHI+ +DQo8dGQ+DQo8cD48L3A+DQo8L3RkPg0KPC90cj4NCjx0cj4NCjx0ZCB2YWxpZ249InRvcCI+DQo8 +cD4mbmJzcDs8L3A+DQo8cD4mbmJzcDs8L3A+DQo8cD48L3A+DQo8cD48L3A+DQo8cD5EZWFyIEV4 +YW1wbGUgQ3VzdG9tZXIsIDxicj4NCjxicj4NClRoaXMgbm90aWNlIGlzIGJlaW5nIHNlbnQgdG8g +bm90aWZ5IHlvdSBvZiB0aGUgZm9sbG93aW5nIHBsYW5uZWQgbWFpbnRlbmFuY2UgZXZlbnQgb24g +dGhlIENyb3duIENhc3RsZSBGaWJlciBuZXR3b3JrLg0KPGJyPg0KPGJyPg0KPC9wPg0KPHA+PHN0 +cm9uZz5UaWNrZXQgTnVtYmVyOiA8L3N0cm9uZz5DTTIwMjMxMjAxMDAwPC9wPg0KPHA+PHN0cm9u +Zz5Mb2NhdGlvbiBvZiBXb3JrOiA8L3N0cm9uZz5Bbnl3aGVyZSwgRkw8L3A+DQo8cD48L3A+DQo8 +cD4NCjx0YWJsZSBjbGFzcz0idGltZXpvbmVncmlkIj4NCjx0Ym9keT4NCjx0cj4NCjx0aCBjb2xz +cGFuPSIyIj5TY2hlZHVsZWQgU3RhcnQgRGF0ZSAmYW1wOyBUaW1lIDwvdGg+DQo8dGggY29sc3Bh +bj0iMiI+U2NoZWR1bGVkIEVuZCBEYXRlICZhbXA7IFRpbWUgPC90aD4NCjx0aD5UaW1lIFpvbmUg +PC90aD4NCjwvdHI+DQo8dHI+DQo8dGQ+MS8zLzIwMjQgPC90ZD4NCjx0ZD4zOjAwIEFNIDwvdGQ+ +DQo8dGQ+MS8zLzIwMjQgPC90ZD4NCjx0ZD45OjAwIEFNIDwvdGQ+DQo8dGQ+RWFzdGVybiA8L3Rk +Pg0KPC90cj4NCjx0cj4NCjx0ZD4xLzMvMjAyNCA8L3RkPg0KPHRkPjI6MDAgQU0gPC90ZD4NCjx0 +ZD4xLzMvMjAyNCA8L3RkPg0KPHRkPjg6MDAgQU0gPC90ZD4NCjx0ZD5DZW50cmFsIDwvdGQ+DQo8 +L3RyPg0KPHRyPg0KPHRkPjEvMy8yMDI0IDwvdGQ+DQo8dGQ+MTowMCBBTSA8L3RkPg0KPHRkPjEv +My8yMDI0IDwvdGQ+DQo8dGQ+NzowMCBBTSA8L3RkPg0KPHRkPk1vdW50YWluIDwvdGQ+DQo8L3Ry +Pg0KPHRyPg0KPHRkPjEvMy8yMDI0IDwvdGQ+DQo8dGQ+MTI6MDAgQU0gPC90ZD4NCjx0ZD4xLzMv +MjAyNCA8L3RkPg0KPHRkPjY6MDAgQU0gPC90ZD4NCjx0ZD5QYWNpZmljIDwvdGQ+DQo8L3RyPg0K +PHRyPg0KPHRkPjEvMy8yMDI0IDwvdGQ+DQo8dGQ+ODowMCBBTSA8L3RkPg0KPHRkPjEvMy8yMDI0 +IDwvdGQ+DQo8dGQ+MjowMCBQTSA8L3RkPg0KPHRkPkdNVCA8L3RkPg0KPC90cj4NCjwvdGJvZHk+ +DQo8L3RhYmxlPg0KPC9wPg0KPHA+PHN0cm9uZz5FeHBlY3RlZCBDdXN0b21lciBJbXBhY3Q6PC9z +dHJvbmc+IFBvdGVudGlhbCBTZXJ2aWNlIEFmZmVjdGluZzwvcD4NCjxwPjxzdHJvbmc+RXhwZWN0 +ZWQgSW1wYWN0IER1cmF0aW9uOjwvc3Ryb25nPiBOb25lIEV4cGVjdGVkPC9wPg0KPHA+PC9wPg0K +PHA+PHN0cm9uZz5Xb3JrPC9zdHJvbmc+IDxzdHJvbmc+RGVzY3JpcHRpb246PC9zdHJvbmc+PC9w +Pg0KPHA+Q3Jvd24gQ2FzdGxlIEZpYmVyIHdpbGwgYmUgY29uZHVjdGluZyBhIHJlcXVpcmVkIG1h +aW50ZW5hbmNlIGF0IHRoZSBhYm92ZS1saXN0ZWQgbG9jYXRpb24gZm9yIHJvdXRpbmUgc3BsaWNp +bmcuIEFsdGhvdWdoIG5vIGltcGFjdCB0byB5b3VyIGNpcmN1aXQocykgbGlzdGVkIGJlbG93IGlz +IGV4cGVjdGVkLCB0aGlzIG1haW50ZW5hbmNlIGlzIGRlZW1lZCBwb3RlbnRpYWxseSBzZXJ2aWNl +IGFmZmVjdGluZy4gV2UgYXBvbG9naXplIGZvciBhbnkNCiByZXN1bHRpbmcgaW5jb252ZW5pZW5j +ZSBhbmQgYXNzdXJlIHlvdSBvZiBvdXIgZWZmb3J0cyB0byBtaW5pbWl6ZSBhbnkgc2VydmljZSBk +aXNydXB0aW9uLjwvcD4NCjxwPjxicj4NCkN1c3RvbWVyIENpcmN1aXRzOiA8L3A+DQo8cD4NCjx0 +YWJsZSBpZD0iY2lyY3VpdGdyaWQiPg0KPHRoZWFkPg0KPHRyPg0KPHRoPkNpcmN1aXQgSUQ8L3Ro +Pg0KPHRoPkFjdGl2ZSBQcm9kdWN0PC90aD4NCjx0aD5BIExvY2F0aW9uPC90aD4NCjx0aD5aIExv +Y2F0aW9uPC90aD4NCjx0aD5JbXBhY3Q8L3RoPg0KPHRoPk5vdGVzPC90aD4NCjwvdHI+DQo8L3Ro +ZWFkPg0KPHRib2R5Pg0KPHRyPg0KPHRkPjAwMDAwMC1ERi1BQkNERkwwMS1EQ0JBRkwwMjwvdGQ+ +DQo8dGQ+RGFyayBGaWJlciAvIFBvaW50IHRvIFBvaW50IC8gTi9BPC90ZD4NCjx0ZD4xMjMgTWFp +biwgQmFzZW1lbnQsIEFueXdoZXJlLCBGTCAxMjM0NTwvdGQ+DQo8dGQ+NTY3IE1haW4sIDFzdCBG +bG9vciwgQW55d2hlcmUsIEZMIDU0MzIxPC90ZD4NCjx0ZD5Ob25lPC90ZD4NCjx0ZD48L3RkPg0K +PC90cj4NCjx0cj4NCjx0ZD4xMTExMTEtREZBQS1DQ0Y8L3RkPg0KPHRkPkRhcmsgRmliZXIgLyBQ +b2ludCB0byBQb2ludCAvIE4vQTwvdGQ+DQo8dGQ+MjM0IE1haW4sIEJhc2VtZW50LCBBbnl3aGVy +ZSwgRkwgMTIzNDU8L3RkPg0KPHRkPjY3OCBNYWluLCAxc3QgRmxvb3IsIEFueXdoZXJlLCBGTCA1 +NDMyMTwvdGQ+DQo8dGQ+Tm9uZTwvdGQ+DQo8dGQ+PC90ZD4NCjwvdHI+DQo8L3Rib2R5Pg0KPC90 +YWJsZT4NCjwvcD4NCjxwPjwvcD4NCjxwPjwvcD4NCjxwPjwvcD4NCjxwPjxzdHJvbmc+RGFyay1G +aWJlciBDdXN0b21lcnM6PC9zdHJvbmc+IDxicj4NCjxicj4NCkRhcmsgRmliZXIgc2VydmljZXMg +Y2Fubm90IGJlIG1vbml0b3JlZCBieSBDcm93biBDYXN0bGUsIHdlIGFyZSByZWxpYW50IG9uIGN1 +c3RvbWVyIGZlZWQgYmFjayBmb3IgY29uZmlybWF0aW9uIHRoYXQgc2VydmljZXMgaGF2ZSByZXN0 +b3JlZC4gVG8gZW5zdXJlIHlvdXIgc2VydmljZXMgaGF2ZSByZXN0b3JlZCwgd2UgYXJlIHJlcXVl +c3RpbmcgdGhhdCB5b3UgcHJvdmlkZSBhIGNvbnRhY3Qgd2hpY2ggaXMgYm90aCBmYW1pbGlhciB3 +aXRoIHRoZSBzZXJ2aWNlDQogYW5kIHdvdWxkIGJlIGFibGUgdG8gcHJvbXB0bHkgY29uZmlybSBz +ZXJ2aWNlIHJlc3RvcmF0aW9uIG9uY2UgdGhlIENNIGlzIGNvbXBsZXRlLiBUaGUgcmVxdWVzdCBm +b3IgY29uZmlybWF0aW9uIG1heSBiZSBuZWVkZWQgYWZ0ZXIgaG91cnMsIHBsZWFzZSBwcm92aWRl +IGJvdGggYSBuYW1lIGFuZCBjb250YWN0IHBob25lIG51bWJlciBpbiByZXNwb25zZSB0byB0aGlz +IGVtYWlsLg0KPGJyPg0KPGJyPg0KSWYgeW91IGhhdmUgYW55IHF1ZXN0aW9ucyBvciBjb25jZXJu +cyBwcmlvciB0byB0aGlzIGV2ZW50LCBwbGVhc2UgcmVwbHkgdG8gdGhpcyBub3RpZmljYXRpb24g +YXMgc29vbiBhcyBwb3NzaWJsZS4NCjxicj4NCjxicj4NCkJ5IHJlc3BvbmRpbmcgdG8gdGhpcyBu +b3RpZmljYXRpb24gaW4gYSB0aW1lbHkgbWFubmVyLCBDcm93biBDYXN0bGUgRmliZXIgQ2hhbmdl +IE1hbmFnZW1lbnQgY2FuIGF0dGVtcHQgdG8gcmVzb2x2ZSBhbnkgcG90ZW50aWFsIGNvbmZsaWN0 +cyB0aGF0IG1heSBhcmlzZS4NCjxicj4NCjxicj4NCklmIHlvdSBoYXZlIGFueSBxdWVzdGlvbnMs +IGNvbmNlcm5zIG9yIGlzc3VlcyBiZWZvcmUsIGR1cmluZyBvciBhZnRlciB0aGlzIG1haW50ZW5h +bmNlIHdpbmRvdywgcGxlYXNlIGNvbnRhY3Qgb3VyIENoYW5nZSBNYW5hZ2VtZW50IERlcGFydG1l +bnQgYXQgMS01MDgtNjIxLTE4ODggYW5kIHJlZmVyZW5jZSB0aGlzIHRpY2tldCBudW1iZXIuDQo8 +YnI+DQo8YnI+DQpJZiB5b3UgaGF2ZSBhbnkgc2VydmljZS9wZXJmb3JtYW5jZSByZWxhdGVkIGlz +c3VlcyBhZnRlciB0aGlzIG1haW50ZW5hbmNlIHdpbmRvdywgcGxlYXNlIGNvbnRhY3Qgb3VyIE5l +dHdvcmsgT3BlcmF0aW9ucyBDZW50ZXIgYXQgMS04NTUtOTMtRklCRVIgKDEtODU1LTkzMy00MjM3 +KSBhbmQgcmVmZXJlbmNlIHRoaXMgdGlja2V0IG51bWJlci4NCjwvcD4NCjxwPjwvcD4NCjxicj4N +ClRoYW5rIFlvdSw8YnI+DQo8YnI+DQo8aT5DaGFuZ2UgQ29udHJvbDxicj4NCkVtYWlsOiA8YSBj +bGFzcz0iYXV0by1zdHlsZTEiIGhyZWY9Im1haWx0bzpmaWJlcmNoYW5nZW1nbXRAY3Jvd25jYXN0 +bGUuY29tIj48c3BhbiBzdHlsZT0iY29sb3I6IzAwNjZjYzsiPmZpYmVyY2hhbmdlbWdtdEBjcm93 +bmNhc3RsZS5jb208L3NwYW4+PC9hPjxicj4NCjUwOC02MjEtMTg4ODwvaT4NCjxwPjwvcD4NCjxw +PjxpbWcgd2lkdGg9IjIwOCIgaGVpZ2h0PSI1NSIgc3JjPSJodHRwczovL3RlbXBnby5jcm93bmNh +c3RsZS5jb20vcnMvMzQzLUxRUi02NTAvaW1hZ2VzL2ltYWdlMDFfQ0NMb2dvMi5wbmciPjwvcD4N +CjwvdGQ+DQo8L3RyPg0KPC90Ym9keT4NCjwvdGFibGU+DQo8L2Rpdj4NCjxwPjwvcD4NCjxwIGFs +aWduPSJjZW50ZXIiPjxpPjxzcGFuIHN0eWxlPSJjb2xvcjpibGFjaztmb250LXNpemU6OS41cHgi +PlBsZWFzZSBub3RlOiBldmVyeSBtYWludGVuYW5jZSBlbnRhaWxzIGEgY2VydGFpbiBsZXZlbCBv +ZiByaXNrIGFuZCBhbHRob3VnaCBDcm93biBDYXN0bGUgRmliZXIgbWFrZXMgZXZlcnkgZWZmb3J0 +IHRvIHByb3ZpZGUgYWNjdXJhdGUgZXhwZWN0ZWQgY3VzdG9tZXIgaW1wYWN0LCBjb25kaXRpb25z +IG91dHNpZGUgb2YgQ3Jvd24gQ2FzdGxlDQogRmliZXIncyBjb250cm9sIG1heSBjYXVzZSBpbXBh +Y3QgdG8gYmUgZ3JlYXRlciB0aGFuIGFudGljaXBhdGVkLjwvc3Bhbj48L2k+PC9wPg0KVGhpcyBl +bWFpbCBtYXkgY29udGFpbiBjb25maWRlbnRpYWwgb3IgcHJpdmlsZWdlZCBtYXRlcmlhbC4gVXNl +IG9yIGRpc2Nsb3N1cmUgb2YgaXQgYnkgYW55b25lIG90aGVyIHRoYW4gdGhlIHJlY2lwaWVudCBp +cyB1bmF1dGhvcml6ZWQuIElmIHlvdSBhcmUgbm90IGFuIGludGVuZGVkIHJlY2lwaWVudCwgcGxl +YXNlIGRlbGV0ZSB0aGlzIGVtYWlsLg0KPC9ib2R5Pg0KPC9odG1sPg0K diff --git a/tests/unit/data/crowncastle/crowncastle1_result.json b/tests/unit/data/crowncastle/crowncastle1_result.json new file mode 100644 index 00000000..85678966 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle1_result.json @@ -0,0 +1,25 @@ +[ + { + "account": "Example Customer", + "circuits": [ + { + "circuit_id": "000000-DF-ABCDFL01-DCBAFL02", + "impact": "NO-IMPACT" + }, + { + "circuit_id": "111111-DFAA-CCF", + "impact": "NO-IMPACT" + } + ], + "end": 1704290400, + "maintenance_id": "CM20231201000", + "organizer": "fiberchangemgmt@crowncastle.com", + "provider": "crowncastle", + "sequence": 1, + "stamp": 1702190640, + "start": 1704268800, + "status": "CONFIRMED", + "summary": "Crown Castle Fiber will be conducting a required maintenance at the above-listed location for routine splicing. Although no impact to your circuit(s) listed below is expected, this maintenance is deemed potentially service affecting. We apologize for any resulting inconvenience and assure you of our efforts to minimize any service disruption.", + "uid": "0" + } +] diff --git a/tests/unit/data/crowncastle/crowncastle2.html b/tests/unit/data/crowncastle/crowncastle2.html new file mode 100644 index 00000000..870b69be --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle2.html @@ -0,0 +1,201 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+

+
+

 

+
+

Maintenance Notification

+
+

+
+

+
+

 

+

 

+

+

+

Dear Example Customer,
+
+This notice is being sent to notify you of the following planned maintenance event on the Crown Castle Fiber network. +
+
+

+

Ticket Number: CM20231201000

+

Location of Work: Anywhere, FL

+

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Scheduled Start Date & Time Scheduled End Date & Time Time Zone
1/3/2024 3:00 AM 1/3/2024 9:00 AM Eastern
1/3/2024 2:00 AM 1/3/2024 8:00 AM Central
1/3/2024 1:00 AM 1/3/2024 7:00 AM Mountain
1/3/2024 12:00 AM 1/3/2024 6:00 AM Pacific
1/3/2024 8:00 AM 1/3/2024 2:00 PM GMT
+

+

Expected Customer Impact: Potential Service Affecting

+

Expected Impact Duration: None Expected

+

+

Work Description:

+

Crown Castle Fiber will be conducting a required maintenance at the above-listed location for routine splicing. Although no impact to your circuit(s) listed below is expected, this maintenance is deemed potentially service affecting. We apologize for any + resulting inconvenience and assure you of our efforts to minimize any service disruption.

+


+Customer Circuits:

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Circuit IDActive ProductA LocationZ LocationImpactNotes
000000-DF-ABCDFL01-DCBAFL02Dark Fiber / Point to Point / N/A123 Main, Basement, Anywhere, FL 12345567 Main, 1st Floor, Anywhere, FL 54321None
111111-DFAA-CCFDark Fiber / Point to Point / N/A234 Main, Basement, Anywhere, FL 12345678 Main, 1st Floor, Anywhere, FL 54321None
+

+

+

+

+

Dark-Fiber Customers:
+
+Dark Fiber services cannot be monitored by Crown Castle, we are reliant on customer feed back for confirmation that services have restored. To ensure your services have restored, we are requesting that you provide a contact which is both familiar with the service + and would be able to promptly confirm service restoration once the CM is complete. The request for confirmation may be needed after hours, please provide both a name and contact phone number in response to this email. +
+
+If you have any questions or concerns prior to this event, please reply to this notification as soon as possible. +
+
+By responding to this notification in a timely manner, Crown Castle Fiber Change Management can attempt to resolve any potential conflicts that may arise. +
+
+If you have any questions, concerns or issues before, during or after this maintenance window, please contact our Change Management Department at 1-508-621-1888 and reference this ticket number. +
+
+If you have any service/performance related issues after this maintenance window, please contact our Network Operations Center at 1-855-93-FIBER (1-855-933-4237) and reference this ticket number. +

+

+
+Thank You,
+
+Change Control
+Email: fiberchangemgmt@crowncastle.com
+508-621-1888
+

+

+
+
+

+

Please note: every maintenance entails a certain level of risk and although Crown Castle Fiber makes every effort to provide accurate expected customer impact, conditions outside of Crown Castle + Fiber's control may cause impact to be greater than anticipated.

+This email may contain confidential or privileged material. Use or disclosure of it by anyone other than the recipient is unauthorized. If you are not an intended recipient, please delete this email. + + diff --git a/tests/unit/data/crowncastle/crowncastle2_parser_result.json b/tests/unit/data/crowncastle/crowncastle2_parser_result.json new file mode 100644 index 00000000..a7b562b7 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle2_parser_result.json @@ -0,0 +1,20 @@ +[ + { + "account": "Example Customer", + "circuits": [ + { + "circuit_id": "000000-DF-ABCDFL01-DCBAFL02", + "impact": "NO-IMPACT" + }, + { + "circuit_id": "111111-DFAA-CCF", + "impact": "NO-IMPACT" + } + ], + "end": 1704290400, + "maintenance_id": "CM20231201000", + "start": 1704268800, + "status": "CONFIRMED", + "summary": "Crown Castle Fiber will be conducting a required maintenance at the above-listed location for routine splicing. Although no impact to your circuit(s) listed below is expected, this maintenance is deemed potentially service affecting. We apologize for any resulting inconvenience and assure you of our efforts to minimize any service disruption." + } +] diff --git a/tests/unit/data/crowncastle/crowncastle3.html b/tests/unit/data/crowncastle/crowncastle3.html new file mode 100644 index 00000000..44c4ad54 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle3.html @@ -0,0 +1,173 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+

+

+
+

 

+
+

Maintenance Cancellation Notification +

+
+

 

+

 

+

+

+

+
+

+
+

+

Dear Example Customer,
+
+This notice is being sent to notify you that the aforementioned planned maintenance event on the Crown Castle Fiber network has been cancelled. +
+
+

+

Ticket Number: CM20231201000

+

Location of Work: Anywhere, FL

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Scheduled Start Date & Time Scheduled End Date & Time Time Zone
12/14/2023 10:00 PM 12/15/2023 6:00 AM Eastern
12/14/2023 9:00 PM 12/15/2023 5:00 AM Central
12/14/2023 8:00 PM 12/15/2023 4:00 AM Mountain
12/14/2023 7:00 PM 12/15/2023 3:00 AM Pacific
12/15/2023 3:00 AM 12/15/2023 11:00 AM GMT
+

+

+

Expected Impact Duration: Diverse Impact - Please See Impact per Circuit

+

+

Work Description: **THIS EVENT HAS BEEN CANCELLED**

+

Please note this maintenance has been cancelled. Crown Castle Fiber apologizes for any resulting inconvenience and thank you for your patience.

+


+Customer Circuits:

+

+ + + + + + + + + + + + + + + + + + + + + +
Circuit IDActive ProductA LocationZ LocationImpactNotes
666666-WAVE-CCFWavelength / DC to DC Connectivity - Inter Market / 10GigE123 Main St, Basement, Anywhere, FL 12345321 Main St, 1st Floor, Anywhere, FL 54321Up to 7 hours
+

+


+
+If you have any questions or concerns, please contact Crown Castle Fiber Change Control and reference this ticket number.

+

+

Change Control
+Email: fiberchangemgmt@crowncastle.com
+1-508-621-1888

+

+
+

+

Please note: every maintenance entails a certain level of risk and although Crown Castle Fiber makes every effort to provide accurate expected customer impact, conditions + outside of Crown Castle Fiber's control may cause impact to be greater than anticipated.

+
+This email may contain confidential or privileged material. Use or disclosure of it by anyone other than the recipient is unauthorized. If you are not an intended recipient, please delete this email. + + diff --git a/tests/unit/data/crowncastle/crowncastle3_parser_result.json b/tests/unit/data/crowncastle/crowncastle3_parser_result.json new file mode 100644 index 00000000..770e88c0 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle3_parser_result.json @@ -0,0 +1,16 @@ +[ + { + "account": "Example Customer", + "circuits": [ + { + "circuit_id": "666666-WAVE-CCF", + "impact": "OUTAGE" + } + ], + "end": 1702638000, + "maintenance_id": "CM20231201000", + "start": 1702609200, + "status": "CANCELLED", + "summary": "Please note this maintenance has been cancelled. Crown Castle Fiber apologizes for any resulting inconvenience and thank you for your patience." + } +] diff --git a/tests/unit/data/crowncastle/crowncastle4.html b/tests/unit/data/crowncastle/crowncastle4.html new file mode 100644 index 00000000..09da0193 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle4.html @@ -0,0 +1,188 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+

+
+

 

+
+

Maintenance Notification - Rescheduled Event

+
+

+
+

+
+

 

+

 

+

+

+

Dear Example Customer,
+
+This notice is being sent to notify you of the rescheduled date/time of the previously notified planned maintenance event on the Crown Castle Fiber Network. +

+

+

Ticket Number: CM20231201000

+

Location of Work: Anywhere, FL

+

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Scheduled Start Date & Time Scheduled End Date & Time Time Zone
12/12/2023 12:00 AM 12/12/2023 6:00 AM Eastern
12/11/2023 11:00 PM 12/12/2023 5:00 AM Central
12/11/2023 10:00 PM 12/12/2023 4:00 AM Mountain
12/11/2023 9:00 PM 12/12/2023 3:00 AM Pacific
12/12/2023 5:00 AM 12/12/2023 11:00 AM GMT
+

+

Expected Customer Impact: Potential Service Affecting

+

Expected Impact Duration: None Expected

+

+

Work Description: *** Rescheduled - Please note new date ***

+

Please note this maintenance has been rescheduled to the dates/times listed above. The previous date was 12/12/23 and the new rescheduled date is 13/12/23. Crown Castle Fiber apologizes for any inconvenience this may cause.

+


+Customer Circuits:

+


+ + + + + + + + + + + + + + + + + + + + + +
Circuit IDActive ProductA LocationZ LocationImpactNotes
666666-DBAA-CCFDark Fiber / Point to Point / N/A123 Main St, Basement, Anywhere, FL 12345321 Main St, 1st Floor, Anywhere, FL 54321None Expected
+

+

+

+

+

Dark-Fiber Customers:
+
+Dark Fiber services cannot be monitored by Crown Castle, we are reliant on customer feed back for confirmation that services have restored. To ensure your services have restored, we are requesting that you provide a contact which is both familiar with the service + and would be able to promptly confirm service restoration once the CM is complete. The request for confirmation may be needed after hours, please provide both a name and contact phone number in response to this email. +
+
+If you have any questions or concerns prior to this event, please reply to this notification as soon as possible. +
+
+By responding to this notification in a timely manner, Crown Castle Fiber Change Management can attempt to resolve any potential conflicts that may arise. +
+
+If you have any questions, concerns or issues before, during or after this maintenance window, please contact our Change Management Department at 1-508-621-1888 and reference this ticket number. +
+
+If you have any service/performance related issues after this maintenance window, please contact our Network Operations Center at 1-855-93-FIBER (1-855-933-4237) and reference this ticket number. +

+

+

Thank You,

+

Change Control
+Email: fiberchangemgmt@crowncastle.com
+508-621-1888

+

+
+

+

Please note: every maintenance entails a certain level of risk and although Crown Castle Fiber makes every effort to provide accurate expected customer impact, conditions outside Crown Castle Fiber's + control may cause impact to be greater than anticipated.

+
+This email may contain confidential or privileged material. Use or disclosure of it by anyone other than the recipient is unauthorized. If you are not an intended recipient, please delete this email. + + diff --git a/tests/unit/data/crowncastle/crowncastle4_parser_result.json b/tests/unit/data/crowncastle/crowncastle4_parser_result.json new file mode 100644 index 00000000..37f48099 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle4_parser_result.json @@ -0,0 +1,16 @@ +[ + { + "account": "Example Customer", + "circuits": [ + { + "circuit_id": "666666-DBAA-CCF", + "impact": "OUTAGE" + } + ], + "end": 1702378800, + "maintenance_id": "CM20231201000", + "start": 1702357200, + "status": "RE-SCHEDULED", + "summary": "Please note this maintenance has been rescheduled to the dates/times listed above. The previous date was 12/12/23 and the new rescheduled date is 13/12/23. Crown Castle Fiber apologizes for any inconvenience this may cause." + } +] diff --git a/tests/unit/data/crowncastle/crowncastle5.html b/tests/unit/data/crowncastle/crowncastle5.html new file mode 100644 index 00000000..8cf57d68 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle5.html @@ -0,0 +1,336 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+

+
+

 

+
+

Maintenance Event Status

+
+

+
+

+
+

 

+

 

+

+

+

+

Dear Example Customer,
+
+This notice is being sent to inform you that the work associated with today’s maintenance window has been completed. We thank you for your patience. +

+

*DARK FIBER CUSTOMERS PLEASE NOTE: All dark fiber services must be reviewed and checked for restoration at this time to ensure connectivity after this maintenance work since we have now completed the event in its entirety. If your services have not restored + please contact our Change Control support line at 1-508-621-1888 immediately to troubleshoot and resolve the matter.

+

If this was a one day maintenance event, please consider this event completed. If maintenance was scheduled for several days, please note the event will be officially complete on the last day of the event. If you have received this notice and your services + have not restored please contact our Change Control support line at 1-508-621-1888.

+

Ticket Number: CM20231201000

+

Location of Work: Anywhere, FL

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Scheduled Start Date & Time Scheduled End Date & Time Time Zone
12/5/2023 4:30 AM 12/5/2023 9:00 AM Eastern
12/5/2023 3:30 AM 12/5/2023 8:00 AM Central
12/5/2023 2:30 AM 12/5/2023 7:00 AM Mountain
12/5/2023 1:30 AM 12/5/2023 6:00 AM Pacific
12/5/2023 9:30 AM 12/5/2023 2:00 PM GMT
+

+

Expected Customer Impact: Please Reference Your Original Notice Below For Impact

+

Expected Impact Duration: None

+

+

+


+

+

Change Control
+Email: fiberchangemgmt@crowncastle.com
+1-508-621-1888

+

+
+

+

Please note: every maintenance entails a certain level of risk and although Crown Castle Fiber makes every effort to provide accurate expected customer impact, conditions outside Crown Castle Fiber's + control may cause impact to be greater than anticipated.

+
+
+Forwarded: Original Event Notice
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + +
+

+
+

 

+
+

Maintenance Notification - Rescheduled Event

+
+

+
+

+
+

 

+

 

+

+

+

Dear Example Customer,
+
+This notice is being sent to notify you of the rescheduled date/time of the previously notified planned maintenance event on the Crown Castle Fiber Network. +

+

+

Ticket Number: CM20231201000

+

Location of Work: Anywhere, FL

+

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Scheduled Start Date & Time Scheduled End Date & Time Time Zone
12/5/2023 4:30 AM 12/5/2023 9:00 AM Eastern
12/5/2023 3:30 AM 12/5/2023 8:00 AM Central
12/5/2023 2:30 AM 12/5/2023 7:00 AM Mountain
12/5/2023 1:30 AM 12/5/2023 6:00 AM Pacific
12/5/2023 9:30 AM 12/5/2023 2:00 PM GMT
+

+

Expected Customer Impact: Potential Service Affecting

+

Expected Impact Duration: None

+

+

Work Description: *** Rescheduled - Please note new date ***

+

Please note this maintenance has been rescheduled to the dates/times listed above. The previous date was 12/1/23 and the new rescheduled date is 12/5/23. Crown Castle Fiber apologizes for any inconvenience this may cause.

+


+Customer Circuits:

+


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Circuit IDActive ProductA LocationZ LocationImpactNotes
666666-DF-ANYWFL00-ANYWFL01Dark Fiber / Point to Point / N/A123 Main St, Basement, Anywhere, FL 12345321 Main St, 1st Floor, Anywhere, FL 54321None
666666-DBAA-CCFDark Fiber / Point to Point / N/A234 Main St, Basement, Anywhere, FL 12345432 Main St, 1st Floor, Anywhere, FL 54321None
+

+

+

+

+

Dark-Fiber Customers:
+
+Dark Fiber services cannot be monitored by Crown Castle, we are reliant on customer feed back for confirmation that services have restored. To ensure your services have restored, we are requesting that you provide a contact which is both familiar with the service + and would be able to promptly confirm service restoration once the CM is complete. The request for confirmation may be needed after hours, please provide both a name and contact phone number in response to this email. +
+
+If you have any questions or concerns prior to this event, please reply to this notification as soon as possible. +
+
+By responding to this notification in a timely manner, Crown Castle Fiber Change Management can attempt to resolve any potential conflicts that may arise. +
+
+If you have any questions, concerns or issues before, during or after this maintenance window, please contact our Change Management Department at 1-508-621-1888 and reference this ticket number. +
+
+If you have any service/performance related issues after this maintenance window, please contact our Network Operations Center at 1-855-93-FIBER (1-855-933-4237) and reference this ticket number. +

+

+

Thank You,

+

Change Control
+Email: fiberchangemgmt@crowncastle.com
+508-621-1888

+

+
+

+

Please note: every maintenance entails a certain level of risk and although Crown Castle Fiber makes every effort to provide accurate expected customer impact, conditions outside Crown Castle Fiber's + control may cause impact to be greater than anticipated.

+
+This email may contain confidential or privileged material. Use or disclosure of it by anyone other than the recipient is unauthorized. If you are not an intended recipient, please delete this email. + + diff --git a/tests/unit/data/crowncastle/crowncastle5_parser_result.json b/tests/unit/data/crowncastle/crowncastle5_parser_result.json new file mode 100644 index 00000000..76a72e61 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle5_parser_result.json @@ -0,0 +1,20 @@ +[ + { + "account": "Example Customer", + "circuits": [ + { + "circuit_id": "666666-DF-ANYWFL00-ANYWFL01", + "impact": "NO-IMPACT" + }, + { + "circuit_id": "666666-DBAA-CCF", + "impact": "NO-IMPACT" + } + ], + "end": 1701784800, + "maintenance_id": "CM20231201000", + "start": 1701768600, + "status": "COMPLETED", + "summary": "Please note this maintenance has been rescheduled to the dates/times listed above. The previous date was 12/1/23 and the new rescheduled date is 12/5/23. Crown Castle Fiber apologizes for any inconvenience this may cause." + } +] diff --git a/tests/unit/data/crowncastle/crowncastle6.html b/tests/unit/data/crowncastle/crowncastle6.html new file mode 100644 index 00000000..4a57e414 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle6.html @@ -0,0 +1,144 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+

+
+

 

+
+

Maintenance Event Status

+
+

+
+

+
+

 

+

 

+

+

+

+

Dear Example Customer,
+
+This notice is being sent to inform you that the work associated with today’s maintenance window has been completed. We thank you for your patience. +

+

*DARK FIBER CUSTOMERS PLEASE NOTE: All dark fiber services must be reviewed and checked for restoration at this time to ensure connectivity after this maintenance work since we have now completed the event in its entirety. If your services have not restored + please contact our Change Control support line at 1-508-621-1888 immediately to troubleshoot and resolve the matter.

+

If this was a one day maintenance event, please consider this event completed. If maintenance was scheduled for several days, please note the event will be officially complete on the last day of the event. If you have received this notice and your services + have not restored please contact our Change Control support line at 1-508-621-1888.

+

Ticket Number: CM20231201000

+

Location of Work: Anywhere, FL

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Scheduled Start Date & Time Scheduled End Date & Time Time Zone
12/2/2023 10:00 PM 12/3/2023 6:00 AM Eastern
12/2/2023 9:00 PM 12/3/2023 5:00 AM Central
12/2/2023 8:00 PM 12/3/2023 4:00 AM Mountain
12/2/2023 7:00 PM 12/3/2023 3:00 AM Pacific
12/3/2023 3:00 AM 12/3/2023 11:00 AM GMT
+

+

Expected Customer Impact: Please Reference Your Original Notice Below For Impact

+

Expected Impact Duration: Diverse Impact - Please See Impact per Circuit

+

+

+


+

+

Change Control
+Email: fiberchangemgmt@crowncastle.com
+1-508-621-1888

+

+
+

+

Please note: every maintenance entails a certain level of risk and although Crown Castle Fiber makes every effort to provide accurate expected customer impact, conditions outside Crown Castle Fiber's + control may cause impact to be greater than anticipated.

+
+This email may contain confidential or privileged material. Use or disclosure of it by anyone other than the recipient is unauthorized. If you are not an intended recipient, please delete this email. + + diff --git a/tests/unit/data/crowncastle/crowncastle6_parser_result.json b/tests/unit/data/crowncastle/crowncastle6_parser_result.json new file mode 100644 index 00000000..03f5a0da --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle6_parser_result.json @@ -0,0 +1,10 @@ +[ + { + "account": "Example Customer", + "circuits": [], + "end": 1701601200, + "maintenance_id": "CM20231201000", + "start": 1701572400, + "status": "COMPLETED" + } +] diff --git a/tests/unit/data/crowncastle/crowncastle7.eml b/tests/unit/data/crowncastle/crowncastle7.eml new file mode 100644 index 00000000..7006dc84 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle7.eml @@ -0,0 +1,88 @@ +Delivered-To: noc@example.com +Message-ID: <1@FIBERCHANGEMGMT.CROWNCASTLE.COM> +MIME-Version: 1.0 +From: Change Management +To: NOC +Date: Tue, 10 Dec 2023 01:44:00 -0500 +Subject: Crown Castle Fiber Scheduled Maintenance Notification: CM20231201000 on 12/2/2023 3:00 AM EST Event Completed +Content-Type: text/html; charset="utf-8" +Content-Transfer-Encoding: base64 + +PCFET0NUWVBFIGh0bWw+DQo8aHRtbD4NCjxoZWFkPg0KPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVu +dC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgiPg0KPHRpdGxlPjwvdGl0 +bGU+DQo8c3R5bGU+CiAgICAgICAgLnRpbWV6b25lZ3JpZCwgI2NpcmN1aXRncmlkIHsKICAgICAg +ICAgICAgZm9udC1mYW1pbHk6IEFyaWFsOwogICAgICAgICAgICBib3JkZXItY29sbGFwc2U6IGNv +bGxhcHNlOwogICAgICAgICAgICBmb250LXNpemU6IDEycHg7CiAgICAgICAgfQoKICAgICAgICAg +ICAgLnRpbWV6b25lZ3JpZCB0ZCwgLnRpbWV6b25lZ3JpZCB0aCwgI2NpcmN1aXRncmlkIHRkLCAj +Y2lyY3VpdGdyaWQgdGggewogICAgICAgICAgICAgICAgYm9yZGVyOiAxcHggc29saWQgI2RkZDsK +ICAgICAgICAgICAgICAgIHBhZGRpbmc6IDhweDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAg +LnRpbWV6b25lZ3JpZCB0aGVhZCwgI2NpcmN1aXRncmlkIHRoZWFkIHsKICAgICAgICAgICAgICAg +IHBhZGRpbmctdG9wOiAycHg7CiAgICAgICAgICAgICAgICBwYWRkaW5nLWJvdHRvbTogMnB4Owog +ICAgICAgICAgICAgICAgYm9yZGVyOiAxcHggc29saWQgI2RkZDsKICAgICAgICAgICAgICAgIHRl +eHQtYWxpZ246IGxlZnQ7CiAgICAgICAgICAgIH0KCiAgICAgICAgYm9keSB7CiAgICAgICAgICAg +IGZvbnQtZmFtaWx5OiBBcmlhbDsKICAgICAgICAgICAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBz +ZTsKICAgICAgICAgICAgZm9udC1zaXplOiAxMnB4OwogICAgICAgIH0KICAgIDwvc3R5bGU+DQo8 +L2hlYWQ+DQo8Ym9keT4NCjxkaXY+DQo8dGFibGUgc3R5bGU9IndpZHRoOiA5MCU7IGJvcmRlcjpu +b25lOyBib3JkZXItc3BhY2luZzowOyBwYWRkaW5nOjA7Ij4NCjx0Ym9keT4NCjx0cj4NCjx0ZCB2 +YWxpZ249InRvcCI+DQo8cCBzdHlsZT0ibWFyZ2luOjBpbiAwaW4gMHB0O3RleHQtYWxpZ246Y2Vu +dGVyIj48aW1nIHNyYz0iaHR0cHM6Ly90ZW1wZ28uY3Jvd25jYXN0bGUuY29tL3JzLzM0My1MUVIt +NjUwL2ltYWdlcy9pbWFnZTAxX0NDTG9nbzIucG5nIiBoZWlnaHQ9IjY1IiB3aWR0aD0iMjQ2Ij48 +L3A+DQo8L3RkPg0KPC90cj4NCjx0cj4NCjx0ZCB2YWxpZ249InRvcCI+DQo8cD4mbmJzcDs8L3A+ +DQo8L3RkPg0KPC90cj4NCjx0cj4NCjx0ZCB2YWxpZ249InRvcCI+DQo8cCBzdHlsZT0idGV4dC1h +bGlnbjpjZW50ZXIiPjxiPjxzcGFuIHN0eWxlPSJjb2xvcjojNUE2NzcxO2ZvbnQtc2l6ZToyNHB4 +Ij48dT5NYWludGVuYW5jZSBFdmVudCBTdGF0dXM8L3U+PC9zcGFuPjwvYj48L3A+DQo8L3RkPg0K +PC90cj4NCjx0cj4NCjx0ZD4NCjxwPjwvcD4NCjwvdGQ+DQo8L3RyPg0KPHRyPg0KPHRkPg0KPHA+ +PC9wPg0KPC90ZD4NCjwvdHI+DQo8dHI+DQo8dGQgdmFsaWduPSJ0b3AiPg0KPHA+Jm5ic3A7PC9w +Pg0KPHA+Jm5ic3A7PC9wPg0KPHA+PC9wPg0KPHA+PC9wPg0KPHA+PC9wPg0KPHA+RGVhciBFeGFt +cGxlIEN1c3RvbWVyLCA8YnI+DQo8YnI+DQpUaGlzIG5vdGljZSBpcyBiZWluZyBzZW50IHRvIGlu +Zm9ybSB5b3UgdGhhdCB0aGUgd29yayBhc3NvY2lhdGVkIHdpdGggdG9kYXnigJlzIG1haW50ZW5h +bmNlIHdpbmRvdyBoYXMgYmVlbiBjb21wbGV0ZWQuIFdlIHRoYW5rIHlvdSBmb3IgeW91ciBwYXRp +ZW5jZS4NCjwvcD4NCjxwPipEQVJLIEZJQkVSIENVU1RPTUVSUyBQTEVBU0UgTk9URTogQWxsIGRh +cmsgZmliZXIgc2VydmljZXMgbXVzdCBiZSByZXZpZXdlZCBhbmQgY2hlY2tlZCBmb3IgcmVzdG9y +YXRpb24gYXQgdGhpcyB0aW1lIHRvIGVuc3VyZSBjb25uZWN0aXZpdHkgYWZ0ZXIgdGhpcyBtYWlu +dGVuYW5jZSB3b3JrIHNpbmNlIHdlIGhhdmUgbm93IGNvbXBsZXRlZCB0aGUgZXZlbnQgaW4gaXRz +IGVudGlyZXR5LiBJZiB5b3VyIHNlcnZpY2VzIGhhdmUgbm90IHJlc3RvcmVkDQogcGxlYXNlIGNv +bnRhY3Qgb3VyIENoYW5nZSBDb250cm9sIHN1cHBvcnQgbGluZSBhdCAxLTUwOC02MjEtMTg4OCBp +bW1lZGlhdGVseSB0byB0cm91Ymxlc2hvb3QgYW5kIHJlc29sdmUgdGhlIG1hdHRlci48L3A+DQo8 +cD5JZiB0aGlzIHdhcyBhIG9uZSBkYXkgbWFpbnRlbmFuY2UgZXZlbnQsIHBsZWFzZSBjb25zaWRl +ciB0aGlzIGV2ZW50IGNvbXBsZXRlZC4gSWYgbWFpbnRlbmFuY2Ugd2FzIHNjaGVkdWxlZCBmb3Ig +c2V2ZXJhbCBkYXlzLCBwbGVhc2Ugbm90ZSB0aGUgZXZlbnQgd2lsbCBiZSBvZmZpY2lhbGx5IGNv +bXBsZXRlIG9uIHRoZSBsYXN0IGRheSBvZiB0aGUgZXZlbnQuIElmIHlvdSBoYXZlIHJlY2VpdmVk +IHRoaXMgbm90aWNlIGFuZCB5b3VyIHNlcnZpY2VzDQogaGF2ZSBub3QgcmVzdG9yZWQgcGxlYXNl +IGNvbnRhY3Qgb3VyIENoYW5nZSBDb250cm9sIHN1cHBvcnQgbGluZSBhdCAxLTUwOC02MjEtMTg4 +OC48L3A+DQo8cD48c3Ryb25nPlRpY2tldCBOdW1iZXI6IDwvc3Ryb25nPkNNMjAyMzEyMDEwMDA8 +L3A+DQo8cD48c3Ryb25nPkxvY2F0aW9uIG9mIFdvcms6IDwvc3Ryb25nPkFueXdoZXJlLCBGTDwv +cD4NCjxwPg0KPHRhYmxlIGNsYXNzPSJ0aW1lem9uZWdyaWQiPg0KPHRib2R5Pg0KPHRyPg0KPHRo +IGNvbHNwYW49IjIiPlNjaGVkdWxlZCBTdGFydCBEYXRlICZhbXA7IFRpbWUgPC90aD4NCjx0aCBj +b2xzcGFuPSIyIj5TY2hlZHVsZWQgRW5kIERhdGUgJmFtcDsgVGltZSA8L3RoPg0KPHRoPlRpbWUg +Wm9uZSA8L3RoPg0KPC90cj4NCjx0cj4NCjx0ZD4xMi8yLzIwMjMgPC90ZD4NCjx0ZD4xMDowMCBQ +TSA8L3RkPg0KPHRkPjEyLzMvMjAyMyA8L3RkPg0KPHRkPjY6MDAgQU0gPC90ZD4NCjx0ZD5FYXN0 +ZXJuIDwvdGQ+DQo8L3RyPg0KPHRyPg0KPHRkPjEyLzIvMjAyMyA8L3RkPg0KPHRkPjk6MDAgUE0g +PC90ZD4NCjx0ZD4xMi8zLzIwMjMgPC90ZD4NCjx0ZD41OjAwIEFNIDwvdGQ+DQo8dGQ+Q2VudHJh +bCA8L3RkPg0KPC90cj4NCjx0cj4NCjx0ZD4xMi8yLzIwMjMgPC90ZD4NCjx0ZD44OjAwIFBNIDwv +dGQ+DQo8dGQ+MTIvMy8yMDIzIDwvdGQ+DQo8dGQ+NDowMCBBTSA8L3RkPg0KPHRkPk1vdW50YWlu +IDwvdGQ+DQo8L3RyPg0KPHRyPg0KPHRkPjEyLzIvMjAyMyA8L3RkPg0KPHRkPjc6MDAgUE0gPC90 +ZD4NCjx0ZD4xMi8zLzIwMjMgPC90ZD4NCjx0ZD4zOjAwIEFNIDwvdGQ+DQo8dGQ+UGFjaWZpYyA8 +L3RkPg0KPC90cj4NCjx0cj4NCjx0ZD4xMi8zLzIwMjMgPC90ZD4NCjx0ZD4zOjAwIEFNIDwvdGQ+ +DQo8dGQ+MTIvMy8yMDIzIDwvdGQ+DQo8dGQ+MTE6MDAgQU0gPC90ZD4NCjx0ZD5HTVQgPC90ZD4N +CjwvdHI+DQo8L3Rib2R5Pg0KPC90YWJsZT4NCjwvcD4NCjxwPjxzdHJvbmc+RXhwZWN0ZWQgQ3Vz +dG9tZXIgSW1wYWN0Ojwvc3Ryb25nPiBQbGVhc2UgUmVmZXJlbmNlIFlvdXIgT3JpZ2luYWwgTm90 +aWNlIEJlbG93IEZvciBJbXBhY3Q8L3A+DQo8cD48c3Ryb25nPkV4cGVjdGVkIEltcGFjdCBEdXJh +dGlvbjo8L3N0cm9uZz4gRGl2ZXJzZSBJbXBhY3QgLSBQbGVhc2UgU2VlIEltcGFjdCBwZXIgQ2ly +Y3VpdDwvcD4NCjxwPjwvcD4NCjxwPjwvcD4NCjxwPjxicj4NCjwvcD4NCjxwPjxpPkNoYW5nZSBD +b250cm9sPGJyPg0KRW1haWw6IDxhIGhyZWY9Im1haWx0bzpmaWJlcmNoYW5nZW1nbXRAY3Jvd25j +YXN0bGUuY29tIj48c3BhbiBzdHlsZT0iY29sb3I6IzAwNjZjYzsiPmZpYmVyY2hhbmdlbWdtdEBj +cm93bmNhc3RsZS5jb208L3NwYW4+PC9hPjxicj4NCjEtNTA4LTYyMS0xODg4PC9pPjwvcD4NCjxw +PjxpbWcgd2lkdGg9IjIwOCIgaGVpZ2h0PSI1NSIgc3JjPSJodHRwczovL3RlbXBnby5jcm93bmNh +c3RsZS5jb20vcnMvMzQzLUxRUi02NTAvaW1hZ2VzL2ltYWdlMDFfQ0NMb2dvMi5wbmciPjwvcD4N +CjwvdGQ+DQo8L3RyPg0KPC90Ym9keT4NCjwvdGFibGU+DQo8cD48L3A+DQo8cCBhbGlnbj0iY2Vu +dGVyIj48aT48c3BhbiBzdHlsZT0iY29sb3I6YmxhY2s7Zm9udC1zaXplOjkuNXB4Ij5QbGVhc2Ug +bm90ZTogZXZlcnkgbWFpbnRlbmFuY2UgZW50YWlscyBhIGNlcnRhaW4gbGV2ZWwgb2YgcmlzayBh +bmQgYWx0aG91Z2ggQ3Jvd24gQ2FzdGxlIEZpYmVyIG1ha2VzIGV2ZXJ5IGVmZm9ydCB0byBwcm92 +aWRlIGFjY3VyYXRlIGV4cGVjdGVkIGN1c3RvbWVyIGltcGFjdCwgY29uZGl0aW9ucyBvdXRzaWRl +IENyb3duIENhc3RsZSBGaWJlcidzDQogY29udHJvbCBtYXkgY2F1c2UgaW1wYWN0IHRvIGJlIGdy +ZWF0ZXIgdGhhbiBhbnRpY2lwYXRlZC48L3NwYW4+PC9pPjwvcD4NCjwvZGl2Pg0KVGhpcyBlbWFp +bCBtYXkgY29udGFpbiBjb25maWRlbnRpYWwgb3IgcHJpdmlsZWdlZCBtYXRlcmlhbC4gVXNlIG9y +IGRpc2Nsb3N1cmUgb2YgaXQgYnkgYW55b25lIG90aGVyIHRoYW4gdGhlIHJlY2lwaWVudCBpcyB1 +bmF1dGhvcml6ZWQuIElmIHlvdSBhcmUgbm90IGFuIGludGVuZGVkIHJlY2lwaWVudCwgcGxlYXNl +IGRlbGV0ZSB0aGlzIGVtYWlsLg0KPC9ib2R5Pg0KPC9odG1sPg0K diff --git a/tests/unit/data/crowncastle/crowncastle7_result.json b/tests/unit/data/crowncastle/crowncastle7_result.json new file mode 100644 index 00000000..d9762bb2 --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle7_result.json @@ -0,0 +1,15 @@ +[ + { + "account": "Example Customer", + "circuits": [], + "end": 1701601200, + "maintenance_id": "CM20231201000", + "organizer": "fiberchangemgmt@crowncastle.com", + "provider": "crowncastle", + "sequence": 1, + "stamp": 1702190640, + "start": 1701572400, + "status": "COMPLETED", + "uid": "0" + } +] diff --git a/tests/unit/data/crowncastle/crowncastle8.html b/tests/unit/data/crowncastle/crowncastle8.html new file mode 100644 index 00000000..eb0301bf --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle8.html @@ -0,0 +1,202 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+

+
+

 

+
+

Emergency Notification

+
+

+
+

+
+

 

+

 

+

+

+

+

Dear Example Customer,

+


+This notice is being sent to notify you of the following +Emergency Demand Maintenance Event on the Crown Castle Fiber network. +
+
+

+

+

Ticket Number: CM20231201000

+

Location of Work: Anywhere, FL

+

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Scheduled Start Date & Time Scheduled End Date & Time Time Zone
12/13/2023 10:00 PM 12/14/2023 6:00 AM Eastern
12/13/2023 9:00 PM 12/14/2023 5:00 AM Central
12/13/2023 8:00 PM 12/14/2023 4:00 AM Mountain
12/13/2023 7:00 PM 12/14/2023 3:00 AM Pacific
12/14/2023 3:00 AM 12/14/2023 11:00 AM GMT
+

+

Expected Customer Impact: Potential Service Affecting

+

Expected Impact Duration: Please See Below

+

+

Work Description:

+


+

+

A Crown Castle Fiber partner + carrier will be conducting an emergency enclosure repair on their network at the above-listed location. Although no impact is expected, your services listed below might experience short-duration impact due to the need to drain the enclosure, and move the cables + within the enclosure. We apologize for any resulting inconvenience and assure you of our efforts to minimize any service disruption. +

+

+


+Customer Circuits:

+

+ + + + + + + + + + + + + + + + + + + + + +
Circuit IDActive ProductA LocationZ LocationImpactNotes
666666-WAVE-CCFWavelength / DC to DC Connectivity - Inter Market123 Main St, Basement, Anywhere, FL 12345321 Main St, 1st Floor, Anywhere, FL 54321Please See Below
+

+

+

+

+

Dark-Fiber Customers:
+
+Dark Fiber services cannot be monitored by Crown Castle, we are reliant on customer feed back for confirmation that services have restored. To ensure your services have restored, we are requesting that you provide a contact which is both familiar with the service + and would be able to promptly confirm service restoration once the CM is complete. The request for confirmation may be needed after hours, please provide both a name and contact phone number in response to this email. +
+
+If you have any questions or concerns prior to this event, please reply to this notification as soon as possible. +
+
+By responding to this notification in a timely manner, Crown Castle Fiber Change Management can attempt to resolve any potential conflicts that may arise. +
+
+If you have any questions, concerns or issues before, during or after this maintenance window, please contact our Change Management Department at 1-508-621-1888 and reference this ticket number. +
+
+If you have any service/performance related issues after this maintenance window, please contact our Network Operations Center at 1-855-93-FIBER (1-855-933-4237) and reference this ticket number. +

+

+

Thank You,

+

Change Control
+Email: fiberchangemgmt@crowncastle.com
+508-621-1888

+

+

+
+

+

Please note: every maintenance entails a certain level of risk and although Crown Castle Fiber makes every effort to provide accurate expected customer impact, conditions outside Crown + Castle Fiber's control may cause impact to be greater than anticipated.

+
+` This email may contain confidential or privileged material. Use or disclosure of it by anyone other than the recipient is unauthorized. If you are not an intended recipient, please delete this email. + + diff --git a/tests/unit/data/crowncastle/crowncastle8_parser_result.json b/tests/unit/data/crowncastle/crowncastle8_parser_result.json new file mode 100644 index 00000000..50b49a4b --- /dev/null +++ b/tests/unit/data/crowncastle/crowncastle8_parser_result.json @@ -0,0 +1,16 @@ +[ + { + "account": "Example Customer", + "circuits": [ + { + "circuit_id": "666666-WAVE-CCF", + "impact": "OUTAGE" + } + ], + "end": 1702551600, + "maintenance_id": "CM20231201000", + "start": 1702522800, + "status": "CONFIRMED", + "summary": "A Crown Castle Fiber partner carrier will be conducting an emergency enclosure repair on their network at the above-listed location. Although no impact is expected, your services listed below might experience short-duration impact due to the need to drain the enclosure, and move the cables within the enclosure. We apologize for any resulting inconvenience and assure you of our efforts to minimize any service disruption." + } +] diff --git a/tests/unit/test_e2e.py b/tests/unit/test_e2e.py index adbd62fb..489ad9a0 100644 --- a/tests/unit/test_e2e.py +++ b/tests/unit/test_e2e.py @@ -19,6 +19,7 @@ BSO, Cogent, Colt, + CrownCastle, EUNetworks, GTT, HGC, @@ -259,6 +260,21 @@ Path(dir_path, "data", "colt", "colt7_result.json"), ], ), + # Crown Castle + ( + CrownCastle, + [ + ("email", Path(dir_path, "data", "crowncastle", "crowncastle1.eml")), + ], + [Path(dir_path, "data", "crowncastle", "crowncastle1_result.json")], + ), + ( + CrownCastle, + [ + ("email", Path(dir_path, "data", "crowncastle", "crowncastle7.eml")), + ], + [Path(dir_path, "data", "crowncastle", "crowncastle7_result.json")], + ), # Equinix ( Equinix, diff --git a/tests/unit/test_parsers.py b/tests/unit/test_parsers.py index b6dad6bb..c2baa672 100644 --- a/tests/unit/test_parsers.py +++ b/tests/unit/test_parsers.py @@ -12,6 +12,7 @@ from circuit_maintenance_parser.parsers.bso import HtmlParserBSO1 from circuit_maintenance_parser.parsers.cogent import HtmlParserCogent1 from circuit_maintenance_parser.parsers.colt import CsvParserColt1, SubjectParserColt1, SubjectParserColt2 +from circuit_maintenance_parser.parsers.crowncastle import HtmlParserCrownCastle1 from circuit_maintenance_parser.parsers.equinix import HtmlParserEquinix, SubjectParserEquinix from circuit_maintenance_parser.parsers.gtt import HtmlParserGTT1 from circuit_maintenance_parser.parsers.hgc import HtmlParserHGC1, HtmlParserHGC2 @@ -219,6 +220,37 @@ Path(dir_path, "data", "colt", "colt7.eml"), Path(dir_path, "data", "colt", "colt7_subject_parser_1_result.json"), ), + # Crown Castle Fiber + ( + HtmlParserCrownCastle1, + Path(dir_path, "data", "crowncastle", "crowncastle2.html"), + Path(dir_path, "data", "crowncastle", "crowncastle2_parser_result.json"), + ), + ( + HtmlParserCrownCastle1, + Path(dir_path, "data", "crowncastle", "crowncastle3.html"), + Path(dir_path, "data", "crowncastle", "crowncastle3_parser_result.json"), + ), + ( + HtmlParserCrownCastle1, + Path(dir_path, "data", "crowncastle", "crowncastle4.html"), + Path(dir_path, "data", "crowncastle", "crowncastle4_parser_result.json"), + ), + ( + HtmlParserCrownCastle1, + Path(dir_path, "data", "crowncastle", "crowncastle5.html"), + Path(dir_path, "data", "crowncastle", "crowncastle5_parser_result.json"), + ), + ( + HtmlParserCrownCastle1, + Path(dir_path, "data", "crowncastle", "crowncastle6.html"), + Path(dir_path, "data", "crowncastle", "crowncastle6_parser_result.json"), + ), + ( + HtmlParserCrownCastle1, + Path(dir_path, "data", "crowncastle", "crowncastle8.html"), + Path(dir_path, "data", "crowncastle", "crowncastle8_parser_result.json"), + ), # Equinix ( HtmlParserEquinix,