From 0b9495ae584b627b20d15d9186b84489153612b7 Mon Sep 17 00:00:00 2001 From: pke11y Date: Wed, 24 Nov 2021 23:36:44 +0000 Subject: [PATCH 1/4] Colt parsing updates to align with encoding fix in nautobot --- circuit_maintenance_parser/parsers/colt.py | 31 +- circuit_maintenance_parser/provider.py | 3 +- tests/unit/data/colt/colt5.eml | 327 +++++++++++++++++++++ tests/unit/data/colt/colt5_result.json | 18 ++ tests/unit/test_e2e.py | 5 + 5 files changed, 381 insertions(+), 3 deletions(-) create mode 100644 tests/unit/data/colt/colt5.eml create mode 100644 tests/unit/data/colt/colt5_result.json diff --git a/circuit_maintenance_parser/parsers/colt.py b/circuit_maintenance_parser/parsers/colt.py index 126dfb57..f9243301 100644 --- a/circuit_maintenance_parser/parsers/colt.py +++ b/circuit_maintenance_parser/parsers/colt.py @@ -33,7 +33,7 @@ def parse_csv(raw): class SubjectParserColt1(EmailSubjectParser): - """Subject parser for Colt notifications.""" + """Subject parser for Colt notifications - type 1.""" def parse_subject(self, subject): """Parse subject. @@ -44,7 +44,7 @@ def parse_subject(self, subject): """ data = {} search = re.search( - r"\[.+\](.+).+?(CRQ\w+-\w+).+?(\d+/\d+/\d+\s\d+:\d+:\d+\s[A-Z]+).+?(\d+/\d+/\d+\s\d+:\d+:\d+\s[A-Z]+).+?([A-Z]+)", + r"\[.+\](.+).+?(CRQ\w+-\w+)\s(\d+/\d+/\d+\s\d+:\d+:\d+\s+[A-Z]+).+?(\d+/\d+/\d+\s\d+:\d+:\d+\s+[A-Z]+).+?([A-Z]+)", subject, ) if search: @@ -59,3 +59,30 @@ def parse_subject(self, subject): data["status"] = Status("CONFIRMED") data["summary"] = subject return [data] + + +class SubjectParserColt2(EmailSubjectParser): + """Subject parser for Colt notifications - type 2.""" + + def parse_subject(self, subject): + r"""Parse subject. + + Example: + - [ EXTERNAL ] Cancellation Colt Third Party Maintenance Notification -\n CRQ1-12345678 [07/12/2021 23:00:00 GMT - 08/12/2021 05:00:00 GMT] for\n ACME, 123456 + - [ EXTERNAL ] Colt Third Party Maintenance Notification -\n CRQ1-48926339503 [07/12/2021 23:00:00 GMT - 08/12/2021 05:00:00 GMT] for\n ACME, 123456 + """ + data = {} + search = re.search( + r"\[.+\]\s+([A-Za-z]+)\s+([\w\s]+)[\s-]+?(CRQ\w+-\w+).+?(\d+/\d+/\d+\s\d+:\d+:\d+\s+[A-Z]+).+?(\d+/\d+/\d+\s\d+:\d+:\d+\s[A-Z]+).+", + subject, + ) + if search: + if search.group(1).upper() == "CANCELLATION": + data["status"] = Status("CANCELLED") + else: + data["status"] = Status("CONFIRMED") + data["maintenance_id"] = search.group(3) + data["start"] = self.dt2ts(parser.parse(search.group(4))) + data["end"] = self.dt2ts(parser.parse(search.group(5))) + data["summary"] = subject + return [data] diff --git a/circuit_maintenance_parser/provider.py b/circuit_maintenance_parser/provider.py index 7538dda1..12295a9f 100644 --- a/circuit_maintenance_parser/provider.py +++ b/circuit_maintenance_parser/provider.py @@ -19,7 +19,7 @@ from circuit_maintenance_parser.parsers.aquacomms import HtmlParserAquaComms1, SubjectParserAquaComms1 from circuit_maintenance_parser.parsers.aws import SubjectParserAWS1, TextParserAWS1 from circuit_maintenance_parser.parsers.cogent import HtmlParserCogent1 -from circuit_maintenance_parser.parsers.colt import CsvParserColt1, SubjectParserColt1 +from circuit_maintenance_parser.parsers.colt import CsvParserColt1, SubjectParserColt1, SubjectParserColt2 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 @@ -194,6 +194,7 @@ class Colt(GenericProvider): _processors: List[GenericProcessor] = [ CombinedProcessor(data_parsers=[EmailDateParser, CsvParserColt1, SubjectParserColt1]), + CombinedProcessor(data_parsers=[EmailDateParser, CsvParserColt1, SubjectParserColt2]), ] _default_organizer = "PlannedWorks@colt.net" diff --git a/tests/unit/data/colt/colt5.eml b/tests/unit/data/colt/colt5.eml new file mode 100644 index 00000000..3b67d150 --- /dev/null +++ b/tests/unit/data/colt/colt5.eml @@ -0,0 +1,327 @@ +Return-Path: +Received: from [192.168.1.25] ([78.18.3.75]) + by smtp.gmail.com with ESMTPSA id m3sm902024wrv.95.2021.11.24.13.43.50 + for + (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); + Wed, 24 Nov 2021 13:43:50 -0800 (PST) +Content-Type: multipart/mixed; boundary="------------0TFLSHrH0cciiTuijamM72EE" +Message-ID: <88226301-ff4c-6811-0ca8-9599d131eca5@networktocode.com> +Date: Wed, 24 Nov 2021 21:43:49 +0000 +MIME-Version: 1.0 +User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) + Gecko/20100101 Thunderbird/91.3.0 +Content-Language: en-US +From: Paddy Kelly +To: patrick.kelly@networktocode.com +Subject: [ EXTERNAL ] Cancellation Colt Third Party Maintenance Notification - + CRQ1-12345678 [07/12/2021 23:00:00 GMT - 08/12/2021 05:00:00 GMT] for + ACME, 123456 + +This is a multi-part message in MIME format. +--------------0TFLSHrH0cciiTuijamM72EE +Content-Type: text/plain; charset=UTF-8; format=flowed +Content-Transfer-Encoding: 7bit + +[ EXTERNAL ] + +Planned Outage Notification + +Dear Sir or Madam, + +In order to maintain the highest levels of availability and service to +our customers, it is sometimes necessary for Colt and our partners to +perform network maintenance. We apologize for any resulting +inconvenience and assure you of our efforts to minimise any service +disruption. To view this, and all other planned maintenance on your +services, or if you require any assistance, please contact us via the +Colt Online Portal http://online.colt.net. Alternatively, email us to +PlannedWorks@colt.net, quoting the following reference number +CRQ1-12345678. Please retain this unique reference for the maintenance. + +Planned Works Details: + +Planned Work (PW)Ref.: CRQ1-12345678 +Start Date & Time: 07/12/2021 23:00:00(GMT)* +End Date & Time: 08/12/2021 05:00:00 (GMT)* +Outage Duration: 360 Minutes + +*Time Zone: +Central European Time (CET) = GMT + 1 hour +Central European Summer Time (CEST) = GMT + 2 hours + +Justification of the work: We would like to make you aware of a +maintenance our carrier will conduct on their network affecting your +service to perform Cable Maintenance Work. As this maintenance is not +being conducted by Colt, rescheduling this work may not be possible. +Should the date and time for the maintenance have passed, without an +updated notification communicated for it, please consider the work as +completed. + +Service: ***Please refer to the attached CSV file for your service(s) +affected by this maintenance**** + +PLEASE NOTE: To enable you to plan appropriately the list of impacted +services includes those that have been completed, as well as those +pending completion. If the pending installation is completed prior to +the scheduled date for the planned maintenance these services will be +impacted. + +Please assist Colt by informing us about any changes to your contact +details via the Colt Online Portal http://online.colt.net or by replying +to PlannedWorks@colt.net so that we can ensure that future notifications +reach the correct parties. + +Should you experience any issue with your service post the maintenance +end time, please contact Colt Technical support via the Colt Online +Portal http://online.colt.net. Alternatively, visit +http://www.colt.net/support to contact us by phone, quoting your service ID. + +For more information about a service, please consult the Colt Online +Portal http://online.colt.net + + +Colt Change management +Colt Technology Services - Operations + +For support log into Colt Online: https://online.colt.net +For other contact options: https://www.colt.net/support +[Colt Disclaimer] This email is from an entity of the Colt group of +companies. Colt Group Holdings Limited, Colt House, 20 Great Eastern +Street, London, EC2A 3EH, United Kingdom, registered in England and +Wales, under company number 11530966. Corporate and contact information +for our entities can be found at +https://www.colt.net/legal/colt-group-of-companies/. Internet +communications are not secure and Colt does not accept responsibility +for the accurate transmission of this message. Content of this email or +its attachments is not legally or contractually binding unless expressly +previously agreed in writing by Colt +--------------0TFLSHrH0cciiTuijamM72EE +Content-Type: text/plain; charset=UTF-8; name="colt1" +Content-Disposition: attachment; filename="colt1" +Content-Transfer-Encoding: base64 + +QkVHSU46VkNBTEVOREFSClBST0RJRDotLy9NaWNyb3NvZnQgQ29ycG9yYXRpb24vL091dGxv +b2sgMTYuMCBNSU1FRElSLy9FTgpWRVJTSU9OOjIuMApNRVRIT0Q6UkVRVUVTVApCRUdJTjpW +VElNRVpPTkUKVFpJRDpVVEMKQkVHSU46U1RBTkRBUkQKRFRTVEFSVDoxNjAxMTAyOFQwMjAw +MDAKVFpPRkZTRVRGUk9NOi0wMDAwClRaT0ZGU0VUVE86LTAwMDAKRU5EOlNUQU5EQVJECkVO +RDpWVElNRVpPTkUKQkVHSU46VkVWRU5UCkNMQVNTOlBVQkxJQwpDUkVBVEVEOjIwMjEwNzMw +VDE0MDMwOFoKRFRFTkQ7VFpJRD1VVEM6MjAyMTA4MDdUMDUwMDAwCkRUU1RBTVA6MjAyMTA3 +MzBUMTQwMzA4WgpEVFNUQVJUO1RaSUQ9VVRDOjIwMjEwODA2VDIxMDAwMApMQVNULU1PRElG +SUVEOjIwMjEwNzMwVDE0MDMwOFoKT1JHQU5JWkVSOkRvTm90UmVwbHlfQ2hhbmdlQGNvbHQu +bmV0CkxPQ0FUSU9OOkNvbHQgSW50ZXJuYWwgTWFpbnRlbmFuY2UKUFJJT1JJVFk6NQpTRVFV +RU5DRTowClNVTU1BUlk7TEFOR1VBR0U9ZW4tdXM6WyBFWFRFUk5BTCBdIENvbHQgU2Vydmlj +ZSBBZmZlY3RpbmcgTWFpbnRlbmFuY2UgTm90aWZpY2F0aW9uIC0gQ1JRMS0xMjM0NTY3OCBb +MDYvOC8yMDIxIDIyOjAwOjAwIEdNVCAtIDA3LzgvMjAyMSAwNjowMDowMCBHTVRdIGZvciBB +Q01FLCAgMTIzNDUwMDAKVFJBTlNQOk9QQVFVRQpVSUQ6TVMwME5ERTFNamM1TkRjM05UTTRP +REU0TVRGSmJYQmhZM1JsWkE9PQpYLUFMVC1ERVNDO0ZNVFRZUEU9dGV4dC9odG1sOjxodG1s +IHhtbG5zOnY9J3VybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206dm1sJyAgeG1sbnM6bz0ndXJu +OnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6b2ZmaWNlJyB4bWxuczp3PSd1cm46c2No +ZW1hcy1taWMgcm9zb2Z0LWNvbTpvZmZpY2U6d29yZCcgeG1sbnM6bT0naHR0cDovL3NjaGVt +YXMubWljcm9zb2Z0LmNvbS9vZmZpY2UvMjAwNC8xMi9vbW1sJyB4bWxucz0naHR0cDovL3d3 +dy53My5vcmcvVFIvUkVDLWh0bWw0MCc+PGhlYWQ+PG1ldGEgbmFtZT1Qcm9nSWQgY29udGVu +dD1Xb3JkLkRvY3VtZW50PjxtZXRhIG5hbWU9R2VuZXJhdG9yIGNvbnRlbnQ9J01pY3Jvc29m +dCBXb3JkIDE1Jz48bWV0YSBuYW1lPU9yaWdpbmF0b3IgY29udGVudD0nTWljcm9zb2Z0IFdv +cmQgMTUnPjxsaW5rIHJlbD1GaWxlLUxpc3QgaHJlZj0nY2lkOmZpbGVsaXN0LnhtbEAwMUQ2 +NDBFQS45QzI4MjU5MCc+IDwvaGVhZD4gPGJvZHkgbGFuZz1FTi1VUyBsaW5rPScjMDU2M0Mx +JyB2bGluaz0nIzk1NEY3Micgc3R5bGU9J3RhYi1pbnRlcnZhbDouNWluJz48dGFibGUgd2lk +dGg9IjEwMCUiIGJvcmRlcj0iMCIgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRkaW5nPSIwIj48 +dHI+PHRkIGFsaWduPSJjZW50ZXIiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTJwdDtmb250 +LWZhbWlseTonQ2FsaWJyaScsc2Fucy1zZXJpZjtjb2xvcjojQzAwMDAwO3RleHQtYWxpZ246 +Y2VudGVyIj48c3Ryb25nPlRoaXMgaXMgYSBzeXN0ZW0gZ2VuZXJhdGVkIGNhbGVuZGFyIGlu +dml0ZS4gQWNjZXB0aW5nIG9yIERlY2xpbmluZyBpcyBtZWFudCBvbmx5IGZvciB0aGUgcHVy +cG9zZSBvZiBhIENhbGVuZGFyIGRpc3BsYXkuICBUaGUgdGltaW5nIG9mIHRoZSBpbnZpdGUg +aXMgc2V0IHRvIHRoZSB1c2Vy4oCZcyBsb2NhbCBzeXN0ZW0gdGltZSBhbmQgc2hvdWxkIG5v +dCB0byBiZSBjb25mdXNlZCB3aXRoIHRoZSB0ZXh0IGRpc3BsYXllZCB3aXRoaQogbiB0aGUg +aW52aXRlLCB3aGljaCBpcyBpbiBHTVQuICBTaG91bGQgeW91IHJlcXVpcmUgYW55IGFzc2lz +dGFuY2UsIHBsZWFzZSBjb250YWN0IHVzIHZpYSB0aGUgQ29sdCBPbmxpbmUgUG9ydGFsIDxz +cGFuIHN0eWxlPSJjb2xvcjojQzAwMDAwIj48YSBocmVmPSJodHRwOi8vb25saW5lLmNvbHQu +bmV0LyIgc3R5bGU9ImJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjMDAwOyI+PHNwYW4gbGFu +Zz0iREUiIHN0eWxlPSJjb2xvcjojQzAwMDAwO2JvcmRlci1ib3R0b206IDFweCBzb2xpZCAj +MDAwOyI+aHR0cDovL29ubGluZS5jb2x0Lm5ldDwvc3Bhbj48L2E+PC9zcGFuPiBvciBhbHRl +cm5hdGl2ZWx5IG1haWwgdXMgYnkgcmVwbHlpbmcgdG8gdGhlIG5vdGlmaWNhdGlvbjwvc3Bh +bj48L3RkPjwvdHI+PC90YWJsZT48cD48L3A+PHA+PHN0cm9uZz48c3BhbiBzdHlsZT0iZm9u +dC1zaXplOiAxMHB0OyI+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1z +ZXJpZjsiPjxpbWcgYm9yZGVyPSIwIiBpZD0iX3gwMDAwX2kxMDI1IiBzcmM9Imh0dHBzOi8v +ZmlsZXN0b3JlLnhtcjMuY29tLzc2MzI1Mi8xMTEzNTk3OTAvMTQ2MjI5LzE4NTAwNC9qb2Jz +ZXR0aW5ncy9kb2NzL2xvZ29sXzE0MjkxNDU1MDI0NDIucG5nIiAvPjwvc3Bhbj48L3NwYW4+ +PC9zdHJvbmc+PC9wPjxwPjwvcD48cD48c3BhbiBzdHlsZT0iZm9udC1zaXplOiAxMHB0OyI+ +PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsiPjxzcGFuIHN0 +eWxlPSJmb250LXNpemU6IDEwcHQ7Ij48c3Ryb25nPlBsYW5uZWQgT3V0YWdlIE5vdGlmaWNh +dGlvbjwvc3Ryb25nPjwvc3Bhbj48L3NwYW4+PC9zcGFuPjwvcD48cD48L3A+PHA+PHNwYW4g +c3R5bGU9ImZvbnQtc2l6ZTogMTBwdDsiPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTogYXJp +YWwsIHNhbnMtc2VyaWY7Ij5EZWFyIFNpciBvciBNYWRhbSw8L3NwYW4+PC9zcGFuPjwvcD48 +cD48L3A+PHA+PHNwYW4gc3R5bAogZT0iZm9udC1zaXplOiAxMHB0OyI+PHNwYW4gc3R5bGU9 +ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsiPkluIG9yZGVyJm5ic3A7dG8gbWFp +bnRhaW4gdGhlIGhpZ2hlc3QgbGV2ZWxzIG9mIGF2YWlsYWJpbGl0eSBhbmQgc2VydmljZSB0 +byBvdXIgY3VzdG9tZXJzLCBpdCBpcyBzb21ldGltZXMgbmVjZXNzYXJ5IGZvciBDb2x0Jm5i +c3A7YW5kIG91ciBwYXJ0bmVycyB0byBwZXJmb3JtIG5ldHdvcmsgbWFpbnRlbmFuY2UuJm5i +c3A7Jm5ic3A7V2UgYXBvbG9naXplIGZvciBhbnkgcmVzdWx0aW5nIGluY29udmVuaWVuY2Ug +YW5kIGFzc3VyZSB5b3Ugb2Ygb3VyIGVmZm9ydHMgdG8gbWluaW1pc2UgYW55IHNlcnZpY2Ug +ZGlzcnVwdGlvbi4gVG8gdmlldyB0aGlzLCBhbmQgYWxsIG90aGVyIHBsYW5uZWQgbWFpbnRl +bmFuY2Ugb24geW91ciBzZXJ2aWNlcywgb3IgaWYgeW91IHJlcXVpcmUgYW55IGFzc2lzdGFu +Y2UsIHBsZWFzZSBjb250YWN0IHVzIHZpYSB0aGUgQ29sdCBPbmxpbmUgUG9ydGFsJm5ic3A7 +PC9zcGFuPjwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFsLCBzYW5zLXNl +cmlmOyI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogMTFwdDsiPjxzcGFuIHN0eWxlPSJmb250 +LXNpemU6IDEwcHQ7Ij48YSBocmVmPSJodHRwOi8vb25saW5lLmNvbHQubmV0Ij5odHRwOi8v +b25saW5lLmNvbHQubmV0PC9hPi4gQWx0ZXJuYXRpdmVseSwgZW1haWwgdXMgdG8mbmJzcDs8 +L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogMTBwdDsiPjxhIGhyZWY9Im1haWx0bzpQ +bGFubmVkV29ya3NAY29sdC5uZXQiPlBsYW5uZWRXb3Jrc0Bjb2x0Lm5ldDwvYT4sJm5ic3A7 +PC9zcGFuPjwvc3Bhbj48L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogMTBwdDsiPjxz +cGFuIHN0eWxlPSJmb250LWZhbWlseTogYXJpYWwsIHNhbnMtc2VyaWY7Ij5xdW90aW5nIHRo +ZSBmb2xsb3dpbmcgcmVmZXJlbmNlIG51bWJlciZuYnNwOzxzdHJvbmc+Q1JRMQogLTEyMzQ1 +Njc4PC9zdHJvbmc+LiBQbGVhc2UgcmV0YWluIHRoaXMgdW5pcXVlIHJlZmVyZW5jZSBmb3Ig +dGhlIG1haW50ZW5hbmNlLjwvc3Bhbj48L3NwYW4+PC9wPjxwPjwvcD48cD48c3BhbiBzdHls +ZT0iZm9udC1zaXplOiAxMHB0OyI+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwg +c2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDEwcHQ7Ij48c3Ryb25nPjx1 +PlBsYW5uZWQgV29ya3MgRGV0YWlsczo8L3U+PC9zdHJvbmc+PC9zcGFuPjwvc3Bhbj48L3Nw +YW4+PC9wPjxwPjwvcD48cD48c3BhbiBzdHlsZT0iZm9udC1zaXplOiAxMHB0OyI+PHNwYW4g +c3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsiPjxzdHJvbmc+UGxhbm5l +ZCBXb3JrIChQVylSZWYuOjwvc3Ryb25nPiZuYnNwOyZuYnNwOyBDUlExLTEyMzQ1Njc4PC9z +cGFuPjwvc3Bhbj48YnIgLz48c3BhbiBzdHlsZT0iZm9udC1zaXplOiAxMHB0OyI+PHNwYW4g +c3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsiPjxzdHJvbmc+U3RhcnQg +RGF0ZSAmYW1wOyBUaW1lOjwvc3Ryb25nPiZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAm +bmJzcDsgJm5ic3A7ICZuYnNwOzwvc3Bhbj48L3NwYW4+MDYvOC8yMDIxIDIxOjAwOjAwPHNw +YW4gc3R5bGU9ImZvbnQtc2l6ZTogMTBwdDsiPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTog +YXJpYWwsIHNhbnMtc2VyaWY7Ij4oR01UKSo8L3NwYW4+PC9zcGFuPjxiciAvPjxzcGFuIHN0 +eWxlPSJmb250LXNpemU6IDEwcHQ7Ij48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFs +LCBzYW5zLXNlcmlmOyI+PHN0cm9uZz5FbmQgRGF0ZSAmYW1wOyBUaW1lOjwvc3Ryb25nPiZu +YnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyZuYnNwOzwv +c3Bhbj48L3NwYW4+MDcvOC8yMDIxIDA1OjAwOjAwPHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTog +MTBwdDsiPjxzcGFuIAogc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsi +PiZuYnNwOyhHTVQpKjwvc3Bhbj48L3NwYW4+PGJyIC8+PHNwYW4gc3R5bGU9ImZvbnQtc2l6 +ZTogMTBwdDsiPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTogYXJpYWwsIHNhbnMtc2VyaWY7 +Ij48c3Ryb25nPk91dGFnZSBEdXJhdGlvbjo8L3N0cm9uZz4mbmJzcDsgJm5ic3A7ICZuYnNw +OyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgTm8gSW1wYWN0PC9zcGFuPjwvc3Bhbj48 +L3A+PHA+PC9wPjxwPjxzdHJvbmc+PGVtPjxzcGFuIHN0eWxlPSJiYWNrZ3JvdW5kLWltYWdl +OiBpbml0aWFsOyBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBpbml0aWFsOyBiYWNrZ3JvdW5kLXNp +emU6IGluaXRpYWw7IGJhY2tncm91bmQtcmVwZWF0OiBpbml0aWFsOyBiYWNrZ3JvdW5kLWF0 +dGFjaG1lbnQ6IGluaXRpYWw7IGJhY2tncm91bmQtb3JpZ2luOiBpbml0aWFsOyBiYWNrZ3Jv +dW5kLWNsaXA6IGluaXRpYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFsLCBz +YW5zLXNlcmlmOyI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogOXB0OyI+KlRpbWUgWm9uZTo8 +L3NwYW4+PC9zcGFuPjwvc3Bhbj48L2VtPjwvc3Ryb25nPjxiciAvPjxlbT48c3BhbiBzdHls +ZT0iYmFja2dyb3VuZC1pbWFnZTogaW5pdGlhbDsgYmFja2dyb3VuZC1wb3NpdGlvbjogaW5p +dGlhbDsgYmFja2dyb3VuZC1zaXplOiBpbml0aWFsOyBiYWNrZ3JvdW5kLXJlcGVhdDogaW5p +dGlhbDsgYmFja2dyb3VuZC1hdHRhY2htZW50OiBpbml0aWFsOyBiYWNrZ3JvdW5kLW9yaWdp +bjogaW5pdGlhbDsgYmFja2dyb3VuZC1jbGlwOiBpbml0aWFsOyI+PHNwYW4gc3R5bGU9ImZv +bnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6 +IDlwdDsiPkNlbnRyYWwgRXVyb3BlYW4gVGltZSAoQ0VUKSZuYnNwOyZuYnNwOz0gR01UICsg +MSBob3VyPC9zcGFuPjwvc3Bhbj48L3NwYW4+PC9lbT48YnIgLz48ZQogbT48c3BhbiBzdHls +ZT0iYmFja2dyb3VuZC1pbWFnZTogaW5pdGlhbDsgYmFja2dyb3VuZC1wb3NpdGlvbjogaW5p +dGlhbDsgYmFja2dyb3VuZC1zaXplOiBpbml0aWFsOyBiYWNrZ3JvdW5kLXJlcGVhdDogaW5p +dGlhbDsgYmFja2dyb3VuZC1hdHRhY2htZW50OiBpbml0aWFsOyBiYWNrZ3JvdW5kLW9yaWdp +bjogaW5pdGlhbDsgYmFja2dyb3VuZC1jbGlwOiBpbml0aWFsOyI+PHNwYW4gc3R5bGU9ImZv +bnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6 +IDlwdDsiPjxlbT5DZW50cmFsIEV1cm9wZWFuIFN1bW1lciBUaW1lIChDRVNUKSA9IEdNVCAr +IDImbmJzcDtob3VyczwvZW0+PC9zcGFuPjwvc3Bhbj48L3NwYW4+PC9lbT48L3A+PHA+PHNw +YW4gc3R5bGU9ImZvbnQtc2l6ZTogMTBwdDsiPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTog +YXJpYWwsIHNhbnMtc2VyaWY7Ij48c3Ryb25nPkp1c3RpZmljYXRpb24gb2YgdGhlIHdvcms6 +PC9zdHJvbmc+Jm5ic3A7S2luZGx5IG5vdGUgdGhlIGRldmljZSBvbiB3aGljaCB5b3VyIHNl +cnZpY2UgaXMgY29tbWlzc2lvbmVkLCB3aWxsIGJlIHVwZ3JhZGVkIGF0IGEgbGF0ZXIgc3Rh +Z2UuIFRodXMgcGxlYXNlIHRha2Ugbm90ZSB0aGF0IHRoaXMgbWFpbnRlbmFuY2UgZm9yIHlv +dXIgc2VydmljZSwgaW4gdGhlIGF0dGFjaGVkIENTViBmaWxlLCBzdGFuZHMgYXMgY2FuY2Vs +bGVkLiBUaGVyZSBhcmUgY3VycmVudGx5IG5vIG5ldyBkYXRlcyBhdmFpbGFibGUuIE9uY2Ug +dGhlIG5ldyB0aW1pbmdzIGhhdmUgYmVlbiBmaW5hbGlzZWQsIENvbHQgd2lsbCByYWlzZSBh +IG5ldyBjaGFuZ2UgdGlja2V0LCBhbmQgaW5mb3JtIHlvdSBhYm91dCB0aGUgd29yay4gV2Ug +d291bGQgbGlrZSB0byBhcG9sb2dpc2UgZm9yIGFueSBpbmNvbnZlbmllbmNlIHRoaXMgbWF5 +IGhhdmUgcmVzdWx0ZWQgaW48L3NwYW4+PC9zcGFuPjwvcD48cD48L3A+PHA+PHNwYW4gc3R5 +bGU9ImZvbnQtc2l6ZQogOiAxMHB0OyI+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlh +bCwgc2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDEwcHQ7Ij48c3Ryb25n +PlNlcnZpY2U6Jm5ic3A7Jm5ic3A7PHNwYW4gc3R5bGU9ImNvbG9yOiByZ2IoMCwgNTEsIDE1 +Myk7Ij4qKipQbGVhc2UgcmVmZXIgdG8gdGhlIGF0dGFjaGVkIENTViBmaWxlIGZvciB5b3Vy +IHNlcnZpY2UocykgYWZmZWN0ZWQgYnkgdGhpcyBtYWludGVuYW5jZSoqKio8L3NwYW4+PC9z +dHJvbmc+PC9zcGFuPjwvc3Bhbj48L3NwYW4+PC9wPjxwPjwvcD48cD48L3A+PHA+PC9wPjxw +PjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDEwcHQ7Ij48c3BhbiBzdHlsZT0iZm9udC1mYW1p +bHk6IGFyaWFsLCBzYW5zLXNlcmlmOyI+PHN0cm9uZz5QTEVBU0UgTk9URTo8L3N0cm9uZz4m +bmJzcDsmbmJzcDtUbyBlbmFibGUgeW91IHRvIHBsYW4gYXBwcm9wcmlhdGVseSB0aGUgbGlz +dCBvZiBpbXBhY3RlZCBzZXJ2aWNlcyBpbmNsdWRlcyB0aG9zZSB0aGF0IGhhdmUgYmVlbiBj +b21wbGV0ZWQsIGFzIHdlbGwgYXMgdGhvc2UgcGVuZGluZyBjb21wbGV0aW9uLiZuYnNwOyZu +YnNwO0lmIHRoZSBwZW5kaW5nIGluc3RhbGxhdGlvbiBpcyBjb21wbGV0ZWQgcHJpb3IgdG8g +dGhlIHNjaGVkdWxlZCBkYXRlIGZvciB0aGUgcGxhbm5lZCBtYWludGVuYW5jZSB0aGVzZSBz +ZXJ2aWNlcyB3aWxsIGJlIGltcGFjdGVkLjwvc3Bhbj48L3NwYW4+PC9wPjxwPjwvcD48cD48 +c3BhbiBzdHlsZT0iZm9udC1zaXplOiAxMHB0OyI+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5 +OiBhcmlhbCwgc2Fucy1zZXJpZjsiPlBsZWFzZSBhc3Npc3QgQ29sdCBieSBpbmZvcm1pbmcg +dXMgYWJvdXQgYW55IGNoYW5nZXMgdG8geW91ciBjb250YWN0IGRldGFpbHMmbmJzcDs8L3Nw +YW4+PC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTogYXJpYWwsIHNhbnMtc2VyaWY7 +Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiAxMHB0OyI+dmlhIHRoZQogIENvbHQgT25saW5l +IFBvcnRhbCZuYnNwOzwvc3Bhbj48L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBh +cmlhbCwgc2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDExcHQ7Ij48YSBo +cmVmPSJodHRwOi8vb25saW5lLmNvbHQubmV0Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiAx +MHB0OyI+aHR0cDovL29ubGluZS5jb2x0Lm5ldDwvc3Bhbj48L2E+PC9zcGFuPjwvc3Bhbj48 +c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFsLCBzYW5zLXNlcmlmOyI+PHNwYW4gc3R5 +bGU9ImZvbnQtc2l6ZTogMTBwdDsiPiZuYnNwO29yIGJ5IHJlcGx5aW5nIHRvJm5ic3A7PC9z +cGFuPjwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFsLCBzYW5zLXNlcmlm +OyI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogMTFwdDsiPjxzcGFuIHN0eWxlPSJmb250LXNp +emU6IDEwcHQ7Ij48YSBocmVmPSJtYWlsdG86UGxhbm5lZFdvcmtzQGNvbHQubmV0Ij5QbGFu +bmVkV29ya3NAY29sdC5uZXQ8L2E+Jm5ic3A7PC9zcGFuPjwvc3Bhbj48L3NwYW4+PHNwYW4g +c3R5bGU9ImZvbnQtc2l6ZTogMTBwdDsiPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTogYXJp +YWwsIHNhbnMtc2VyaWY7Ij5zbyB0aGF0IHdlIGNhbiBlbnN1cmUgdGhhdCBmdXR1cmUgbm90 +aWZpY2F0aW9ucyByZWFjaCB0aGUgY29ycmVjdCBwYXJ0aWVzLjwvc3Bhbj48L3NwYW4+PGJy +IC8+PGJyIC8+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsi +PjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDEwcHQ7Ij5TaG91bGQgeW91IGV4cGVyaWVuY2Ug +YW55IGlzc3VlIHdpdGggeW91ciBzZXJ2aWNlIHBvc3QgdGhlIG1haW50ZW5hbmNlIGVuZCB0 +aW1lLCBwbGVhc2UgY29udGFjdCBDb2x0IFRlY2huaWNhbCBzdXBwb3J0IHZpYSB0aGUgQ29s +dCBPbmxpbmUgUG9ydGFsJm5ic3A7PC9zcGFuPjwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1m +YW1pbHk6IGFyaWFsLAogIHNhbnMtc2VyaWY7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiAx +MXB0OyI+PGEgaHJlZj0iaHR0cDovL29ubGluZS5jb2x0Lm5ldCI+PHNwYW4gc3R5bGU9ImZv +bnQtc2l6ZTogMTBwdDsiPmh0dHA6Ly9vbmxpbmUuY29sdC5uZXQ8L3NwYW4+PC9hPjwvc3Bh +bj48L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsi +PjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDEwcHQ7Ij4uIEFsdGVybmF0aXZlbHksIHZpc2l0 +Jm5ic3A7PGEgaHJlZj0iaHR0cDovL3d3dy5jb2x0Lm5ldC9zdXBwb3J0Ij5odHRwOi8vd3d3 +LmNvbHQubmV0L3N1cHBvcnQ8L2E+Jm5ic3A7dG8gY29udGFjdCB1cyBieSBwaG9uZSwgcXVv +dGluZyB5b3VyIHNlcnZpY2UgSUQ8L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogMTFw +dDsiPi48L3NwYW4+PGJyIC8+PGJyIC8+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogMTBwdDsi +PkZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IGEgc2VydmljZSwgcGxlYXNlIGNvbnN1bHQm +bmJzcDs8L3NwYW4+PC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTogYXJpYWwsIHNh +bnMtc2VyaWY7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiAxMHB0OyI+dGhlIENvbHQgT25s +aW5lIFBvcnRhbCZuYnNwOzwvc3Bhbj48L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5 +OiBhcmlhbCwgc2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDExcHQ7Ij48 +YSBocmVmPSJodHRwOi8vb25saW5lLmNvbHQubmV0Ij48c3BhbiBzdHlsZT0iZm9udC1zaXpl +OiAxMHB0OyI+aHR0cDovL29ubGluZS5jb2x0Lm5ldDwvc3Bhbj48L2E+PC9zcGFuPjwvc3Bh +bj48L3A+PHA+PC9wPjxwPjxiciAvPjxzdHJvbmc+PHNwYW4gc3R5bGU9ImNvbG9yOiByZ2Io +MTA2LCAxMDYsIDEwNik7Ij48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFsLCBzYW5z +LXNlcmlmOyI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogMTFwdDsiPgogQ29sdCBDaGFuZ2Ug +bWFuYWdlbWVudDwvc3Bhbj48L3NwYW4+PC9zcGFuPjwvc3Ryb25nPjxiciAvPjxzdHJvbmc+ +PHNwYW4gc3R5bGU9ImNvbG9yOiByZ2IoMTA2LCAxMDYsIDEwNik7Ij48c3BhbiBzdHlsZT0i +Zm9udC1mYW1pbHk6IGFyaWFsLCBzYW5zLXNlcmlmOyI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6 +ZTogMTFwdDsiPjxzdHJvbmc+Q29sdCBUZWNobm9sb2d5IFNlcnZpY2VzIC0gT3BlcmF0aW9u +czwvc3Ryb25nPjwvc3Bhbj48L3NwYW4+PC9zcGFuPjwvc3Ryb25nPjxiciAvPjxzcGFuIHN0 +eWxlPSJmb250LXNpemU6IDEwcHQ7Ij48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFs +LCBzYW5zLXNlcmlmOyI+PGltZyBib3JkZXI9IjAiIGlkPSJfeDAwMDBfaTEwMjUiIHNyYz0i +aHR0cHM6Ly9maWxlc3RvcmUueG1yMy5jb20vNzYzMjUyLzExMTM1OTc5MC8xNDYyMjkvMTg1 +MDA0L2pvYnNldHRpbmdzL2RvY3MvbG9nb2xfMTQyOTE0NTUwMjQ0Mi5wbmciIC8+Jm5ic3A7 +PC9zcGFuPjwvc3Bhbj48YnIgLz48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFsLCBz +YW5zLXNlcmlmOyI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogOXB0OyI+Rm9yIHN1cHBvcnQg +bG9nIGludG8gQ29sdCBPbmxpbmU6Jm5ic3A7PHNwYW4gc3R5bGU9ImNvbG9yOiByZ2IoMzEs +IDczLCAxMjUpOyI+PGEgaHJlZj0iaHR0cHM6Ly9vbmxpbmUuY29sdC5uZXQiPmh0dHBzOi8v +b25saW5lLmNvbHQubmV0PC9hPjwvc3Bhbj48L3NwYW4+PC9zcGFuPjxiciAvPjxzcGFuIHN0 +eWxlPSJmb250LWZhbWlseTogYXJpYWwsIHNhbnMtc2VyaWY7Ij48c3BhbiBzdHlsZT0iZm9u +dC1zaXplOiA5cHQ7Ij5Gb3Igb3RoZXIgY29udGFjdCBvcHRpb25zOiZuYnNwOzxzcGFuIHN0 +eWxlPSJjb2xvcjogcmdiKDMxLCA3MywgMTI1KTsiPjxhIGhyZWY9Imh0dHBzOi8vd3d3LmNv +bHQubmV0L3N1cHBvcnQiPmh0dHBzOi8vd3d3LmNvbHQubmV0L3N1cHBvcnQ8L2E+PC9zcGFu +Pjwvc3Bhbj48L3NwYQogbj48L3A+PC9ib2R5PjwvaHRtbD4KQkVHSU46VkFMQVJNClRSSUdH +RVI6LVBUMTVNCkFDVElPTjpESVNQTEFZCkRFU0NSSVBUSU9OOlJlbWluZGVyCkVORDpWQUxB +Uk0KRU5EOlZFVkVOVApFTkQ6VkNBTEVOREFS +--------------0TFLSHrH0cciiTuijamM72EE +Content-Type: text/csv; charset=UTF-16LE; name="colt2.csv" +Content-Disposition: attachment; filename="colt2.csv" +Content-Transfer-Encoding: base64 + +//5PAEMATgAJAEwAZQBnAGEAbAAgAEMAdQBzAHQAbwBtAGUAcgAJAE8AcgBkAGUAcgAgAE4A +dQBtAGIAZQByAAkAQwBpAHIAYwB1AGkAdAAgAEkARAAJAEMAdQBzAHQAbwBtAGUAcgAgAFIA +ZQBmACAAMQAJAEMAdQBzAHQAbwBtAGUAcgAgAFIAZQBmACAAMgAJAFMAZQByAHYAaQBjAGUA +CQBBACAAQwB1AHMAdABvAG0AZQByAAkAQQAgAEEAZABkAHIAZQBzAHMACQBBACAAUABvAHMA +dABjAG8AZABlAAkAQQAgAFQAbwB3AG4AIABDAGkAdAB5AAkAQgAgAEMAdQBzAHQAbwBtAGUA +cgAJAEIAIABBAGQAZAByAGUAcwBzAAkAQgAgAFAAbwBzAHQAYwBvAGQAZQAJAEIAIABUAG8A +dwBuACAAQwBpAHQAeQAJAA0ACgBPAEMATgA6ACAAMQAyADMANAA1ADYACQBBAEMATQBFACAA +RQBVAFIATwBQAEUAIABTAEEACQA5ADgANwA2ADUANAAzADIAMQAvADEAMgAzADQANQAtADYA +NwA4ADkACQBDAC0AMQAyADMANAA1ADYANwAJAAkAQgBlAGwAZwBpAHUAbQAgAC0AIABCAHIA +dQBzAHMAZQBsAHMACQBJAFAAIABBAEMAQwBFAFMAUwA6ACAAMQAgAEcAQgBQAFMAOwAgAFUA +TgBQAFIATwBUAEUAQwBUAEUARAA7ACAATgBPACAAUgBFAFMASQBMAEkARQBOAEMARQA7ACAA +TgBPACAAQwBPAEwAVAAgAFIATwBVAFQARQBSADsAIABGAEwAQQBUACAAUgBBAFQARQAgAEIA +SQBMAEwASQBOAEcAOwAgADMAUgBEACAAUABBAFIAVABZACAATABFAEEAUwBFAEQAIABMAEkA +TgBFADsAIABFAFQASABFAFIATgBFAFQAOwAgADEAMAAwADAAQgBBAFMARQAtAFQAOwAgAFIA +SgA0ADUACQBBAEMATQBFACAARQBVAFIATwBQAEUAIABTAEEACQBNAEEASQBOACAAUwBUAFIA +RQBFAFQACQAxADIAMwA0AAkAQgBSAFUAUwBTAEUATABTAAkAQwBvAGwAdAAJAAkACQAJAA== + +--------------0TFLSHrH0cciiTuijamM72EE-- + diff --git a/tests/unit/data/colt/colt5_result.json b/tests/unit/data/colt/colt5_result.json new file mode 100644 index 00000000..289d6ce2 --- /dev/null +++ b/tests/unit/data/colt/colt5_result.json @@ -0,0 +1,18 @@ +[ + { + "account": "123456", + "end": 1628744400, + "maintenance_id": "CRQ1-12345678", + "circuits": [ + { + "impact": "OUTAGE", + "circuit_id": "C-1234567" + } + ], + "sequence": 1, + "stamp": 1637790229, + "start": 1626130800, + "status": "CANCELLED", + "summary": "[ EXTERNAL ] Cancellation Colt Third Party Maintenance Notification - CRQ1-12345678 [07/12/2021 23:00:00 GMT - 08/12/2021 05:00:00 GMT] for ACME, 123456" + } +] \ No newline at end of file diff --git a/tests/unit/test_e2e.py b/tests/unit/test_e2e.py index dcaabab0..f4fef6f5 100644 --- a/tests/unit/test_e2e.py +++ b/tests/unit/test_e2e.py @@ -96,6 +96,11 @@ [("email", Path(dir_path, "data", "colt", "colt4.eml")),], [Path(dir_path, "data", "colt", "colt4_result.json"),], ), + ( + Colt, + [("email", Path(dir_path, "data", "colt", "colt5.eml")),], + [Path(dir_path, "data", "colt", "colt5_result.json"),], + ), # Equinix ( Equinix, From 893cf37d4a0c5a57e5a344f5dd11fdd44d3d987b Mon Sep 17 00:00:00 2001 From: pke11y Date: Thu, 25 Nov 2021 15:20:54 +0000 Subject: [PATCH 2/4] Add parser tests and rework parser for Colt --- circuit_maintenance_parser/parsers/colt.py | 11 ++++++----- tests/unit/data/colt/colt1_result.json | 2 +- tests/unit/data/colt/colt3_result.json | 2 +- tests/unit/data/colt/colt4.eml | 2 +- tests/unit/data/colt/colt4_result.json | 2 +- .../data/colt/colt4_subject_parser_1_result.json | 9 +++++++++ tests/unit/data/colt/colt5_result.json | 2 +- .../data/colt/colt5_subject_parser_2_result.json | 9 +++++++++ tests/unit/test_parsers.py | 12 +++++++++++- 9 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 tests/unit/data/colt/colt4_subject_parser_1_result.json create mode 100644 tests/unit/data/colt/colt5_subject_parser_2_result.json diff --git a/circuit_maintenance_parser/parsers/colt.py b/circuit_maintenance_parser/parsers/colt.py index f9243301..59e3ebca 100644 --- a/circuit_maintenance_parser/parsers/colt.py +++ b/circuit_maintenance_parser/parsers/colt.py @@ -44,20 +44,21 @@ def parse_subject(self, subject): """ data = {} search = re.search( - r"\[.+\](.+).+?(CRQ\w+-\w+)\s(\d+/\d+/\d+\s\d+:\d+:\d+\s+[A-Z]+).+?(\d+/\d+/\d+\s\d+:\d+:\d+\s+[A-Z]+).+?([A-Z]+)", + r"\[.+\]\s([A-Za-z\s]+).+?(CRQ\w+-\w+)\s(\d+/\d+/\d+\s\d+:\d+:\d+\s+[A-Z]+).+?(\d+/\d+/\d+\s\d+:\d+:\d+\s+[A-Z]+).+?([A-Z]+)", subject, ) if search: data["maintenance_id"] = search.group(2) data["start"] = self.dt2ts(parser.parse(search.group(3))) data["end"] = self.dt2ts(parser.parse(search.group(4))) - if search.group(5) == "START": + status = search.group(5).strip() + if status == "START": data["status"] = Status("IN-PROCESS") - elif search.group(5) == "COMPLETED": + elif status == "COMPLETED": data["status"] = Status("COMPLETED") else: data["status"] = Status("CONFIRMED") - data["summary"] = subject + data["summary"] = search.group(1).strip() return [data] @@ -84,5 +85,5 @@ def parse_subject(self, subject): data["maintenance_id"] = search.group(3) data["start"] = self.dt2ts(parser.parse(search.group(4))) data["end"] = self.dt2ts(parser.parse(search.group(5))) - data["summary"] = subject + data["summary"] = search.group(2).strip() return [data] diff --git a/tests/unit/data/colt/colt1_result.json b/tests/unit/data/colt/colt1_result.json index c17182fb..aed776c9 100644 --- a/tests/unit/data/colt/colt1_result.json +++ b/tests/unit/data/colt/colt1_result.json @@ -7,6 +7,6 @@ "stamp": 1627653788, "start": 1628283600, "status": "CONFIRMED", - "summary": "[ EXTERNAL ] Colt Service Affecting Maintenance Notification - CRQ1-12345678 [06/8/2021 22:00:00 GMT - 07/8/2021 06:00:00 GMT] for ACME, 12345000" + "summary": "Service Affecting Maintenance Notification" } ] \ No newline at end of file diff --git a/tests/unit/data/colt/colt3_result.json b/tests/unit/data/colt/colt3_result.json index d18f103b..29aadbdd 100644 --- a/tests/unit/data/colt/colt3_result.json +++ b/tests/unit/data/colt/colt3_result.json @@ -13,6 +13,6 @@ "stamp": 1630760572, "start": 1623189600, "status": "CONFIRMED", - "summary": "[ EXTERNAL ] Colt Service Affecting Maintenance Notification - CRQ1-12345678 [06/8/2021 22:00:00 GMT - 07/8/2021 06:00:00 GMT] for ACME, 12345000" + "summary": "Service Affecting Maintenance Notification" } ] \ No newline at end of file diff --git a/tests/unit/data/colt/colt4.eml b/tests/unit/data/colt/colt4.eml index 42704f38..108f777f 100644 --- a/tests/unit/data/colt/colt4.eml +++ b/tests/unit/data/colt/colt4.eml @@ -1,9 +1,9 @@ MIME-Version: 1.0 Date: Mon, 1 Nov 2021 11:51:41 +0000 -Subject: [ EXTERNAL ] MAINTENANCE ALERT: CRQ1-12345678 31/10/2021 00:00:00 GMT - 31/10/2021 07:30:00 GMT - COMPLETED From: Maintenance Request To: Maintenance Request Content-Type: multipart/mixed; boundary="000000000000e8c2b105cfb8cc38" +Subject: [ EXTERNAL ] MAINTENANCE ALERT: CRQ1-12345678 31/10/2021 00:00:00 GMT - 31/10/2021 07:30:00 GMT - COMPLETED --000000000000e8c2b105cfb8cc38 Content-Type: multipart/alternative; boundary="000000000000e8c2ae05cfb8cc36" diff --git a/tests/unit/data/colt/colt4_result.json b/tests/unit/data/colt/colt4_result.json index a57343e2..55fd6de4 100644 --- a/tests/unit/data/colt/colt4_result.json +++ b/tests/unit/data/colt/colt4_result.json @@ -13,6 +13,6 @@ "stamp": 1635767501, "start": 1635638400, "status": "COMPLETED", - "summary": "[ EXTERNAL ] MAINTENANCE ALERT: CRQ1-12345678 31/10/2021 00:00:00 GMT - 31/10/2021 07:30:00 GMT - COMPLETED" + "summary": "MAINTENANCE ALERT" } ] \ No newline at end of file diff --git a/tests/unit/data/colt/colt4_subject_parser_1_result.json b/tests/unit/data/colt/colt4_subject_parser_1_result.json new file mode 100644 index 00000000..219ad228 --- /dev/null +++ b/tests/unit/data/colt/colt4_subject_parser_1_result.json @@ -0,0 +1,9 @@ +[ + { + "end": 1635665400, + "maintenance_id": "CRQ1-12345678", + "start": 1635638400, + "status": "COMPLETED", + "summary": "MAINTENANCE ALERT" + } +] \ No newline at end of file diff --git a/tests/unit/data/colt/colt5_result.json b/tests/unit/data/colt/colt5_result.json index 289d6ce2..f5c2307c 100644 --- a/tests/unit/data/colt/colt5_result.json +++ b/tests/unit/data/colt/colt5_result.json @@ -13,6 +13,6 @@ "stamp": 1637790229, "start": 1626130800, "status": "CANCELLED", - "summary": "[ EXTERNAL ] Cancellation Colt Third Party Maintenance Notification - CRQ1-12345678 [07/12/2021 23:00:00 GMT - 08/12/2021 05:00:00 GMT] for ACME, 123456" + "summary": "Colt Third Party Maintenance Notification" } ] \ No newline at end of file diff --git a/tests/unit/data/colt/colt5_subject_parser_2_result.json b/tests/unit/data/colt/colt5_subject_parser_2_result.json new file mode 100644 index 00000000..b420bffa --- /dev/null +++ b/tests/unit/data/colt/colt5_subject_parser_2_result.json @@ -0,0 +1,9 @@ +[ + { + "end": 1628744400, + "maintenance_id": "CRQ1-12345678", + "start": 1626130800, + "status": "CANCELLED", + "summary": "Colt Third Party Maintenance Notification" + } +] \ No newline at end of file diff --git a/tests/unit/test_parsers.py b/tests/unit/test_parsers.py index d5d99724..c84c29d7 100644 --- a/tests/unit/test_parsers.py +++ b/tests/unit/test_parsers.py @@ -11,7 +11,7 @@ from circuit_maintenance_parser.parsers.aws import SubjectParserAWS1, TextParserAWS1 from circuit_maintenance_parser.parsers.cogent import HtmlParserCogent1 -from circuit_maintenance_parser.parsers.colt import CsvParserColt1 +from circuit_maintenance_parser.parsers.colt import CsvParserColt1, SubjectParserColt1, SubjectParserColt2 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 @@ -92,6 +92,16 @@ Path(dir_path, "data", "colt", "colt2.csv"), Path(dir_path, "data", "colt", "colt2_result.json"), ), + ( + SubjectParserColt1, + Path(dir_path, "data", "colt", "colt4.eml"), + Path(dir_path, "data", "colt", "colt4_subject_parser_1_result.json"), + ), + ( + SubjectParserColt2, + Path(dir_path, "data", "colt", "colt5.eml"), + Path(dir_path, "data", "colt", "colt5_subject_parser_2_result.json"), + ), # Equinix ( HtmlParserEquinix, From 007c2f5f731c9a619a78dca6548334cbcd5086da Mon Sep 17 00:00:00 2001 From: pke11y Date: Mon, 29 Nov 2021 10:37:19 +0000 Subject: [PATCH 3/4] Add additional status for Lumen (#117) * Add additional status for Lumen --- CHANGELOG.md | 7 ++ circuit_maintenance_parser/parsers/lumen.py | 2 + tests/unit/data/lumen/lumen6.html | 123 ++++++++++++++++++++ tests/unit/data/lumen/lumen6_result.json | 17 +++ tests/unit/test_parsers.py | 5 + 5 files changed, 154 insertions(+) create mode 100644 tests/unit/data/lumen/lumen6.html create mode 100644 tests/unit/data/lumen/lumen6_result.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 28351b51..d7cc505e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## v2.0.6 + +### Added + +- #116 - New `EmailSubjectParser` for Colt notifications and tests. +- #117 - Add new notification status of `Alternate Night` for Lumen. + ## v2.0.5 - 2021-11-18 ### Fixed diff --git a/circuit_maintenance_parser/parsers/lumen.py b/circuit_maintenance_parser/parsers/lumen.py index b7ba5876..bf87f973 100644 --- a/circuit_maintenance_parser/parsers/lumen.py +++ b/circuit_maintenance_parser/parsers/lumen.py @@ -95,6 +95,8 @@ def parse_tables(self, tables: ResultSet, data: Dict): data["status"] = Status("RE-SCHEDULED") elif status_string == "Not Completed": data["status"] = Status("CANCELLED") + elif status_string == "Alternate Night": + data["status"] = Status("RE-SCHEDULED") elif "status" not in data: # Update to an existing ticket may not include an update to the status - make a guess data["status"] = "CONFIRMED" diff --git a/tests/unit/data/lumen/lumen6.html b/tests/unit/data/lumen/lumen6.html new file mode 100644 index 00000000..986fa86b --- /dev/null +++ b/tests/unit/data/lumen/lumen6.html @@ -0,0 +1,123 @@ +
+[ EXTERNAL ] +
+

+
+
+Scheduled Maintenance Window #: 123456789-1 +
+
+Summary:

+
+Lumen intends to carry out internal maintenance within its network. This has been designated as ESSENTIAL. The nature of this work is to repair/replace fiber and is required in order to avoid unplanned outages from damages related to natural causes. +
+The estimated GPS location of work is:
+US-11 & Main Street, TN LAT: 35.1111 LONG: -89.1111
+An alternate/backup maintenance window has been scheduled in the event work is unable to be completed on the primary night. Currently no services are scheduled to be impacted on the alternate night. Should the alternate night be deemed necessary, you will receive + an updated notification advising which services will be impacted on that night. Please see the date and times of the alternate night below. +
+Lumen sincerely apologizes for any inconvenience caused by this maintenance. +
+
+Updates: +
+
+2021-11-18 03:57:47 GMT - The scheduled maintenance window 123456789-1 has ended.
+
+Customer Impact: + +

+
+Work on the services below will be performed during the alternate night maintenance window. +

123456789-2 +
+

+ + + + + + + + + + + + + + +
StartEnd
2021-11-19 06:00 GMT (Greenwich Mean Time)2021-11-19 12:00 GMT (Greenwich Mean Time)
2021-11-19 00:00 CST (Central Standard Time)2021-11-19 06:00 CST (Central Standard Time)
+
+
+Maintenance Location(s): KENTUCKY, TN UNITED STATES
+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Customer NameCircuit IDAlt Circuit IDBandwidthA LocationZ LocationImpact TypeMaximum DurationOrder NumberStatus
ACME INCETH1000-111111N/AGIGEMAIN STREET USA Outage2 hours  Alternate Night
+
+
+
+
+Click here for immediate information on scheduled maintenances via the Lumen Customer Portal. +
+
+Click here to manage your notification subscriptions via the Lumen Customer Portal. +
+
+Click here to open a case for assistance on this scheduled maintenance via the Lumen Customer Portal. +
+
+Click here to give us feedback on this scheduled maintenance. +
+
+For updates anytime via telephone:
+
+   North America: 877-453-8353
+
+   Europe, Middle East, and Africa: +44 1270 727 126
+
+   Latin America:
+
+        Argentina: 0800-800-5383
+
+        Brazil: 0800-887-3333
+
+        Chile: 800-360-303
+
+        Colombia: 01 8000 117997
+
+        Ecuador: 1800-400-408
+
+        Peru: 0800-7-0662
+
+        Venezuela: 0800-538-3538
+
+The information in this communication is confidential and may not be disclosed to third parties or shared further without the express permission of Lumen.
+
+
\ No newline at end of file diff --git a/tests/unit/data/lumen/lumen6_result.json b/tests/unit/data/lumen/lumen6_result.json new file mode 100644 index 00000000..f410ce78 --- /dev/null +++ b/tests/unit/data/lumen/lumen6_result.json @@ -0,0 +1,17 @@ +[ + { + "account": "ACME INC", + "circuits": [ + { + "circuit_id": "ETH1000-111111", + "impact": "OUTAGE" + } + ], + "end": 1637323200, + "maintenance_id": "123456789-1", + "stamp": 1637207867, + "start": 1637301600, + "status": "RE-SCHEDULED", + "summary": "Lumen intends to carry out internal maintenance within its network. This has been designated as ESSENTIAL. The nature of this work is to repair/replace fiber and is required in order to avoid unplanned outages from damages related to natural causes." + } +] diff --git a/tests/unit/test_parsers.py b/tests/unit/test_parsers.py index c84c29d7..acfd9800 100644 --- a/tests/unit/test_parsers.py +++ b/tests/unit/test_parsers.py @@ -186,6 +186,11 @@ Path(dir_path, "data", "lumen", "lumen5.html"), Path(dir_path, "data", "lumen", "lumen5_result.json"), ), + ( + HtmlParserLumen1, + Path(dir_path, "data", "lumen", "lumen6.html"), + Path(dir_path, "data", "lumen", "lumen6_result.json"), + ), # Megaport ( HtmlParserMegaport1, From 825a4980b87dc6567b5ff4b8d21db00562a7912f Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Mon, 29 Nov 2021 11:40:54 +0100 Subject: [PATCH 4/4] Release v2.0.6 --- CHANGELOG.md | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7cc505e..2bdee14b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v2.0.6 +## v2.0.6 - 2021-11-30 ### Added diff --git a/pyproject.toml b/pyproject.toml index b7c920fb..b7b21615 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "circuit-maintenance-parser" -version = "2.0.5" +version = "2.0.6" description = "Python library to parse Circuit Maintenance notifications and return a structured data back" authors = ["Network to Code "] license = "Apache-2.0"