diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bdee14b..88748a5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## v2.0.7 - 2021-12-01 + +### Fixed + +- #120 - Improve handling of Zayo notifications. +- #121 - Defer loading of `tzwhere` data until it's needed, to reduce memory overhead. + ## v2.0.6 - 2021-11-30 ### Added diff --git a/circuit_maintenance_parser/parsers/zayo.py b/circuit_maintenance_parser/parsers/zayo.py index 553bb1ff..37a75ce0 100644 --- a/circuit_maintenance_parser/parsers/zayo.py +++ b/circuit_maintenance_parser/parsers/zayo.py @@ -1,5 +1,6 @@ """Zayo parser.""" import logging +import re from typing import Dict import bs4 # type: ignore @@ -22,15 +23,19 @@ class SubjectParserZayo1(EmailSubjectParser): END OF WINDOW NOTIFICATION***Customer Inc.***ZAYO TTN-0000123456 Planned*** ***Customer Inc***ZAYO TTN-0001234567 Emergency MAINTENANCE NOTIFICATION*** RESCHEDULE NOTIFICATION***Customer Inc***ZAYO TTN-0005423873 Planned*** + + Some degenerate examples have been seen as well: + [notices] CANCELLED NOTIFICATION***Customer,inc***ZAYO TTN-0005432100 Planned** + [notices] Rescheduled Maintenance***ZAYO TTN-0005471719 MAINTENANCE NOTIFICATION*** """ def parse_subject(self, subject): """Parse subject of email message.""" data = {} - tokens = subject.split("***") + tokens = re.split(r"\*+", subject) if len(tokens) == 4: data["account"] = tokens[1] - data["maintenance_id"] = tokens[2].split(" ")[1] + data["maintenance_id"] = tokens[-2].split(" ")[1] return [data] @@ -48,7 +53,7 @@ def parse_html(self, soup): text = soup.get_text() if "will be commencing momentarily" in text: data["status"] = Status("IN-PROCESS") - elif "has been completed" in text: + elif "has been completed" in text or "has closed" in text: data["status"] = Status("COMPLETED") return [data] diff --git a/circuit_maintenance_parser/provider.py b/circuit_maintenance_parser/provider.py index 12295a9f..1189dd69 100644 --- a/circuit_maintenance_parser/provider.py +++ b/circuit_maintenance_parser/provider.py @@ -335,6 +335,11 @@ class Verizon(GenericProvider): class Zayo(GenericProvider): """Zayo provider custom class.""" + _include_filter = { + "text/html": ["Maintenance Ticket #"], + "html": ["Maintenance Ticket #"], + } + _processors: List[GenericProcessor] = [ CombinedProcessor(data_parsers=[EmailDateParser, SubjectParserZayo1, HtmlParserZayo1]), ] diff --git a/circuit_maintenance_parser/utils.py b/circuit_maintenance_parser/utils.py index eb3b0a79..c2d2ca99 100644 --- a/circuit_maintenance_parser/utils.py +++ b/circuit_maintenance_parser/utils.py @@ -16,36 +16,46 @@ dirname = os.path.dirname(__file__) +class classproperty: # pylint: disable=invalid-name,too-few-public-methods + """Simple class-level equivalent of an @property.""" + + def __init__(self, method): + """Wrap a method.""" + self.getter = method + + def __get__(self, _, cls): + """Call the wrapped method.""" + return self.getter(cls) + + class Geolocator: """Class to obtain Geo Location coordinates.""" # Keeping caching of local DB and timezone in the class - db_location: Dict[Union[Tuple[str, str], str], Tuple[float, float]] = {} - timezone = None + _db_location: Dict[Union[Tuple[str, str], str], Tuple[float, float]] = {} + _timezone = None - def __init__(self): - """Initialize instance.""" - self.load_db_location() - self.load_timezone() - - @classmethod - def load_timezone(cls): + @classproperty + def timezone(cls): # pylint: disable=no-self-argument """Load the timezone resolver.""" - if cls.timezone is None: - cls.timezone = tzwhere.tzwhere() + if cls._timezone is None: + cls._timezone = tzwhere.tzwhere() logger.info("Loaded local timezone resolver.") - - @classmethod - def load_db_location(cls): - """Load the localtions DB from CSV into a Dict.""" - with open(os.path.join(dirname, "data", "worldcities.csv")) as csvfile: - reader = csv.DictReader(csvfile) - for row in reader: - # Index by city and country - cls.db_location[(row["city_ascii"], row["country"])] = (float(row["lat"]), float(row["lng"])) - # Index by city (first entry wins if duplicated names) - if row["city_ascii"] not in cls.db_location: - cls.db_location[row["city_ascii"]] = (float(row["lat"]), float(row["lng"])) + return cls._timezone + + @classproperty + def db_location(cls): # pylint: disable=no-self-argument + """Load the locations DB from CSV into a Dict.""" + if not cls._db_location: + with open(os.path.join(dirname, "data", "worldcities.csv")) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + # Index by city and country + cls._db_location[(row["city_ascii"], row["country"])] = (float(row["lat"]), float(row["lng"])) + # Index by city (first entry wins if duplicated names) + if row["city_ascii"] not in cls._db_location: + cls._db_location[row["city_ascii"]] = (float(row["lat"]), float(row["lng"])) + return cls._db_location def get_location(self, city: str) -> Tuple[float, float]: """Get location.""" @@ -64,7 +74,9 @@ def get_location_from_local_file(self, city: str) -> Tuple[float, float]: city_name = city.split(", ")[0] country = city.split(", ")[-1] - lat, lng = self.db_location.get((city_name, country), self.db_location.get(city_name, (None, None))) + lat, lng = self.db_location.get( # pylint: disable=no-member + (city_name, country), self.db_location.get(city_name, (None, None)) # pylint: disable=no-member + ) if lat and lng: logger.debug("Resolved %s to lat %s, lon %sfrom local locations DB.", city, lat, lng) return (lat, lng) @@ -92,12 +104,12 @@ def city_timezone(self, city: str) -> str: if self.timezone is not None: try: latitude, longitude = self.get_location(city) - timezone = self.timezone.tzNameAt(latitude, longitude) + timezone = self.timezone.tzNameAt(latitude, longitude) # pylint: disable=no-member if not timezone: # In some cases, given a latitued and longitued, the tzwhere library returns # an empty timezone, so we try with the coordinates from the API as an alternative latitude, longitude = self.get_location_from_api(city) - timezone = self.timezone.tzNameAt(latitude, longitude) + timezone = self.timezone.tzNameAt(latitude, longitude) # pylint: disable=no-member if timezone: logger.debug("Matched city %s to timezone %s", city, timezone) diff --git a/pyproject.toml b/pyproject.toml index b7b21615..08fb6eb3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "circuit-maintenance-parser" -version = "2.0.6" +version = "2.0.7" description = "Python library to parse Circuit Maintenance notifications and return a structured data back" authors = ["Network to Code "] license = "Apache-2.0" diff --git a/tests/unit/data/zayo/zayo7.eml b/tests/unit/data/zayo/zayo7.eml new file mode 100644 index 00000000..08c9e9d2 --- /dev/null +++ b/tests/unit/data/zayo/zayo7.eml @@ -0,0 +1,567 @@ +Delivered-To: nautobot.email@example.com +Received: by 2002:a05:7000:1f21:0:0:0:0 with SMTP id hs33csp7496624mab; + Tue, 16 Nov 2021 05:07:16 -0800 (PST) +X-Received: by 2002:a9d:343:: with SMTP id 61mr5945318otv.382.1637068035715; + Tue, 16 Nov 2021 05:07:15 -0800 (PST) +ARC-Seal: i=3; a=rsa-sha256; t=1637068035; cv=pass; + d=google.com; s=arc-20160816; + b=IB/8zXU0mGvMEPiGevys762Th4QW/WWOSMFGa/uZu3Mz9ZQaOH+b98tv7CNF4NHZtF + ufTzSRlbnjLJ7lr1gfImSCPvndVNPxqL7TjJSNxxoWoEbKoTClThBwEoaBs4sVzhJS4P + UKKcta4U7KnRtVKN2ykjEULsovnFXIy3Q1aWcUhwoGC3omJZd6R5r6Y3xu/44IRpN3K/ + dkmA5NJhgXB0rZIMfGpEWxDQS6ziWgbmT6lv/nUwMXjTaYxOQ78jx1tAp5P/AyhwoC/5 + tSKR2v5sL1QdR4TiwrspSuYARpyZ+tbI87xaNHcSdIVn5P/x8GCzoIGUnejQoYOWHnUF + cFYw== +ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; + h=list-unsubscribe:list-archive:list-help:list-post:list-id + :mailing-list:precedence:mime-version:subject:message-id:to:from + :date:sender:dkim-signature; + bh=WI7hatx2cY/zCiwLLfmT9tsATL4tdmlbsXu2SR2IL8s=; + b=C8RA6H3tFL1i61hRjo6HgYMp57PRDYnQTndRYrTMWGFUweDT41qj2sqGclu0fJCsGV + fi4bCjy7GeV3wN6/wVCfgPNvupiZBV0y9hAe60Wa6eMTeNm9Bqrb2dbTWU5HFIP7H60x + Ou1okXBKnCqwHEOlwlebZEyDflePbZhJ3jjvw866jRrh4bX1e9z2ER3AI8j7wb22hcQS + /x1zrHXddk6AEaWAR1o3jiCvRG55GqpyfHLeszQEaGPxoELC5ryQ2djKGR1sOZSiKjlY + AZ+QrxnHfZj8KeOBrc0pt86aFhZLJZ0q8yc6G2m+vK3dIrPz4iBKPenXj6TIdsxsba9U + J1aQ== +ARC-Authentication-Results: i=3; mx.google.com; + dkim=pass header.i=@example.com header.s=example header.b=oZnliWXn; + arc=pass (i=2 spf=pass spfdomain=a9wj63terdu8.6-79qkeai.na152.bnc.salesforce.com dkim=pass dkdomain=zayo.com dmarc=pass fromdomain=zayo.com); + spf=pass (google.com: domain of maint-notices+bncbcyp3io6yejbbag2z2gamgqenrxxxiq@example.com designates 209.85.220.97 as permitted sender) smtp.mailfrom=maint-notices+bncBCYP3IO6YEJBBAG2Z2GAMGQENRXXXIQ@example.com; + dmarc=fail (p=NONE sp=NONE dis=NONE arc=pass) header.from=zayo.com +Return-Path: +Received: from mail-sor-f97.google.com (mail-sor-f97.google.com. [209.85.220.97]) + by mx.google.com with SMTPS id h8sor6057870vsf.11.2021.11.16.05.07.15 + for + (Google Transport Security); + Tue, 16 Nov 2021 05:07:15 -0800 (PST) +Received-SPF: pass (google.com: domain of maint-notices+bncbcyp3io6yejbbag2z2gamgqenrxxxiq@example.com designates 209.85.220.97 as permitted sender) client-ip=209.85.220.97; +Authentication-Results: mx.google.com; + dkim=pass header.i=@example.com header.s=example header.b=oZnliWXn; + arc=pass (i=2 spf=pass spfdomain=a9wj63terdu8.6-79qkeai.na152.bnc.salesforce.com dkim=pass dkdomain=zayo.com dmarc=pass fromdomain=zayo.com); + spf=pass (google.com: domain of maint-notices+bncbcyp3io6yejbbag2z2gamgqenrxxxiq@example.com designates 209.85.220.97 as permitted sender) smtp.mailfrom=maint-notices+bncBCYP3IO6YEJBBAG2Z2GAMGQENRXXXIQ@example.com; + dmarc=fail (p=NONE sp=NONE dis=NONE arc=pass) header.from=zayo.com +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; + h=x-gm-message-state:dkim-signature:sender:date:from:to:message-id + :subject:mime-version:x-original-sender + :x-original-authentication-results:precedence:mailing-list:list-id + :list-post:list-help:list-archive:list-unsubscribe; + bh=WI7hatx2cY/zCiwLLfmT9tsATL4tdmlbsXu2SR2IL8s=; + b=GozK90s56Y3hVOd9yPN8oFZa1jSz4rOFLhWgqLoiSo0cI6lCXkp72r/uXZjlfdYX7/ + Dj5HlhIS7DAI4lVQnJnPoljayzge8TYHnBjzw9ofMbkcjY7c8QrOpAGTC/UrNe9ooBbU + H/QLHlzRTDwWvGHNMDb3TCM5aP0xGwAi96/YEYryWDiYYLgrSc084NbYqx2tezdrAd8W + zcH9o5qZUnzFl+i1KC3lbilzhaxmMD6i6cjOKDoGO8JVkNanD++YWafcRL9YtLp9YN1s + D3FpFn2aNiFxXKxxkiIuatPmI1HLBKMf12RIACs5rCByLc6hkMxB/kL0II4a2DYXwF6b + 7dfw== +X-Gm-Message-State: AOAM533fV8DxbMi88GwyXb8A6DqzYlFzXeyw9gzJ73BccuSjvakJAOkc + 6qR6AkOt0z33Ea1QWjvVIsxrnbneKvLMRUqhPpREB9GKfAsDlc6V +X-Google-Smtp-Source: ABdhPJxZLh2l9VwninnUEB05SPvOl0XpI3tntFkJRhFvneu65zx1x+a6dplC5URzMushL9aOgjEYQb9Nvf7+ +X-Received: by 2002:a05:6102:3ed4:: with SMTP id n20mr55971226vsv.57.1637068035229; + Tue, 16 Nov 2021 05:07:15 -0800 (PST) +Return-Path: +Received: from netskope.com ([8.36.116.139]) + by smtp-relay.gmail.com with ESMTPS id x123sm4927428vka.12.2021.11.16.05.07.14 + for + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Tue, 16 Nov 2021 05:07:15 -0800 (PST) +X-Relaying-Domain: example.com +Received: by mail-qk1-f199.google.com with SMTP id o19-20020a05620a22d300b0046754380e8asf13531940qki.13 + for ; Tue, 16 Nov 2021 05:07:14 -0800 (PST) +ARC-Seal: i=2; a=rsa-sha256; t=1637068033; cv=pass; + d=google.com; s=arc-20160816; + b=VwANNKk53QJSEQJyVTUFdSemKLAYMDumadGoj/JwiJgQJMgvvwmAvLO5t2vyPCRSzg + +M++oHhLRWsQ0Ofo180KPtTqcxPolo5WtmZb5WIXdWStiYRHYME5+eQqjJVVtyLhwquB + RiwzXReIp7J4ExHsjGuhfq2Sbs0tFRweX0S2hf5eHQu14AQXrss4NjaFenQ9JYJOwEwN + fhRezDm7U1n/VV6qh4C5fziDmd5zNKwCF0fJJNr9Dgo0m7QJrjXeE6LA1A/Y87DQ0aE3 + KH6o/tillafLZPPXp3T0TuOkdb2tYPgfpjl2wZDn0iy5VH6OMXVmfuPm/XtfovnEY5VD + +CiQ== +ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; + h=list-unsubscribe:list-archive:list-help:list-post:list-id + :mailing-list:precedence:mime-version:subject:message-id:to:from + :date:sender:dkim-signature; + bh=WI7hatx2cY/zCiwLLfmT9tsATL4tdmlbsXu2SR2IL8s=; + b=fJIz47nRfg/wLMPBPqbNTcctBCrmmqjczYQs7ID409Hag7o6io+T5S7bKGC4cgmJeU + 4g+PEVovOikB00gxUYOX9akyeNp5uOVCLO4vR1qU2aIGx4Be3aSBQ8HRaKO4LCxA7kGO + D8eHPcnY9OB31cvfMOkdWBuCk0+rJtu4A9ET5zbdnRFDEzSH0rUwQT0fZkNbcTIoxSsk + Kkhpui3eTpL5q9N8tUPb0GSOtsRW51V3yWdmw48qTA+IB6I6CWMcsK03OXYoU4Peo2t0 + 7zOFvNTkaNJIPVDDVah1MFSYyZ9VwlppCDhTq4WSEKbzh/vTH7LWNahnzTxpFX56HAtO + rsFw== +ARC-Authentication-Results: i=2; mx.google.com; + dkim=pass header.i=@zayo.com header.s=sf112018 header.b=cJQYD4No; + spf=pass (google.com: domain of mr=zayo.com__2tt0k2qfvnpvywkz@a9wj63terdu8.6-79qkeai.na152.bnc.salesforce.com designates 13.110.74.206 as permitted sender) smtp.mailfrom="mr=zayo.com__2tt0k2qfvnpvywkz@a9wj63terdu8.6-79qkeai.na152.bnc.salesforce.com"; + dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=zayo.com +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=example.com; s=example; + h=sender:date:from:to:message-id:subject:mime-version + :x-original-sender:x-original-authentication-results:precedence + :mailing-list:list-id:list-post:list-help:list-archive + :list-unsubscribe; + bh=WI7hatx2cY/zCiwLLfmT9tsATL4tdmlbsXu2SR2IL8s=; + b=oZnliWXnf3DrGuLqxUBXb2UKHVF3N2Q0jIpgIP5p8svgURWuwVaSACYTaRFo0zCmwG + Qh6I0MjDEY2YRD1FluWHqx8YYK5dsGXyCbUIyp2C4ZUScov9lAnJ+feje4yQ0cn7BJSG + Vbrkk/7e55yAp0YtDzKvJ0iOadVrzq4OuA9/w= +Sender: maint-notices@example.com +X-Received: by 2002:a05:622a:28b:: with SMTP id z11mr7382381qtw.242.1637068033308; + Tue, 16 Nov 2021 05:07:13 -0800 (PST) +X-Received: by 2002:a05:622a:28b:: with SMTP id z11mr7382332qtw.242.1637068032974; + Tue, 16 Nov 2021 05:07:12 -0800 (PST) +X-BeenThere: maint-notices@example.com +Received: by 2002:a05:620a:294b:: with SMTP id n11ls9420290qkp.3.gmail; Tue, + 16 Nov 2021 05:07:12 -0800 (PST) +X-Received: by 2002:a37:98d:: with SMTP id 135mr6125755qkj.166.1637068032336; + Tue, 16 Nov 2021 05:07:12 -0800 (PST) +ARC-Seal: i=1; a=rsa-sha256; t=1637068032; cv=none; + d=google.com; s=arc-20160816; + b=N6/9T3XZJXe8H0bOqPrlPxEVduOshcVhO30pZ6D7R054LZMMd3eRtjQY2dfTVSmF17 + G0KMx5b9/vcmWrdfZmxWDN7yrHUfkHJvA9IBNf3UQhULgwwcFRrO3gnX/THHYY5HPC0N + xvC7yA0BaEs90UQTHUXIvfm0CRxVB0x2bCwcIe2okhwM/AXLthLWu1FQ9ZXBlzjHyT/r + Gq6R+2VwcTuDhIhYbpAP7DshVJbw/mgiRozxcq06pB2H0z/V/PwZMFndXk3YjVyYUhxx + N81T/m+GzJW4kn5iiEzUd33Y0I6I+ZM6lhfQdBm25H/DeVsF9C/lrZEY/kYz13i7Q77b + fVKA== +ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; + h=mime-version:subject:message-id:to:from:date:dkim-signature; + bh=mG0dcEC2Pb90PeX1dDqfwdOjCjYOnK0F6TdfBb6kd7k=; + b=OFwQMT1ox8ED3fIeAVUVSfTzJoIRlzvSk1Vpfqw/U26D3UhNi/ogoSnXirDuOLeXzC + ULZrYlSvZt/leMC1T72XFStsT2t8YzL0UZZ4q6eAODBDU+m9J3t9B3EGJxnfWmJtZLed + QmKElNS8+gZmGl4hENaRkXLilFU77hTg8vVxil97aXlvJP5CzdPwSITvhriThOWWy+eV + YAIBpdjGpG4U/E5QW/KEzvAF0M2R9tlK1XajVhn0qIePIvtmjdfdmTdWHvudx7Mvgh0/ + lk9jkwb8cIuwaAuXRiIiJNcuKLL98j6YavpsEV1nUkog2UpD7vaIPS+CfOGeWEEhJcAt + vE3g== +ARC-Authentication-Results: i=1; mx.google.com; + dkim=pass header.i=@zayo.com header.s=sf112018 header.b=cJQYD4No; + spf=pass (google.com: domain of mr=zayo.com__2tt0k2qfvnpvywkz@a9wj63terdu8.6-79qkeai.na152.bnc.salesforce.com designates 13.110.74.206 as permitted sender) smtp.mailfrom="mr=zayo.com__2tt0k2qfvnpvywkz@a9wj63terdu8.6-79qkeai.na152.bnc.salesforce.com"; + dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=zayo.com +Received: from smtp15-ia4-sp3.mta.salesforce.com (smtp15-ia4-sp3.mta.salesforce.com. [13.110.74.206]) + by mx.google.com with ESMTPS id x7si27045370qko.306.2021.11.16.05.07.12 + for + (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); + Tue, 16 Nov 2021 05:07:12 -0800 (PST) +Received-SPF: pass (google.com: domain of mr=zayo.com__2tt0k2qfvnpvywkz@a9wj63terdu8.6-79qkeai.na152.bnc.salesforce.com designates 13.110.74.206 as permitted sender) client-ip=13.110.74.206; +Received: from [10.180.203.172] ([10.180.203.172:45648] helo=na152-app1-45-ia4.ops.sfdc.net) + by mx2-ia4-sp3.mta.salesforce.com (envelope-from ) + (ecelerity 4.2.38.62368 r(Core:release/4.2.38.0)) with ESMTPS (cipher=ECDHE-RSA-AES256-GCM-SHA384 + subject="/C=US/ST=California/L=San Francisco/O=salesforce.com, inc./OU=0:app;1:ia4;2:ia4-sp3;3:na152;4:prod/CN=na152-app1-45-ia4.ops.sfdc.net") + id CD/F9-06366-00DA3916; Tue, 16 Nov 2021 13:07:12 +0000 +Date: Tue, 16 Nov 2021 13:07:12 +0000 (GMT) +From: MR Zayo +To: "maint-notices@example.com" +Message-ID: +Subject: [maint-notices] END OF WINDOW NOTIFICATION***Example Inc.***ZAYO + TTN-0005432100 Planned*** +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="----=_Part_1041_614738999.1637068032082" +X-Priority: 3 +X-SFDC-LK: 00D6000000079Qk +X-SFDC-User: 00560000001fmpl +X-Sender: postmaster@salesforce.com +X-mail_abuse_inquiries: http://www.salesforce.com/company/abuse.jsp +X-SFDC-TLS-NoRelay: 1 +X-SFDC-Binding: 1WrIRBV94myi25uB +X-SFDC-EmailCategory: apiSingleMail +X-SFDC-Interface: internal +X-Original-Sender: mr@zayo.com +X-Original-Authentication-Results: mx.google.com; dkim=pass + header.i=@zayo.com header.s=sf112018 header.b=cJQYD4No; spf=pass + (google.com: domain of mr=zayo.com__2tt0k2qfvnpvywkz@a9wj63terdu8.6-79qkeai.na152.bnc.salesforce.com + designates 13.110.74.206 as permitted sender) smtp.mailfrom="mr=zayo.com__2tt0k2qfvnpvywkz@a9wj63terdu8.6-79qkeai.na152.bnc.salesforce.com"; + dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=zayo.com +Precedence: list +Mailing-list: list maint-notices@example.com; contact maint-notices+owners@example.com +List-ID: +X-Google-Group-Id: 536184160288 +List-Post: , +List-Help: , + +List-Archive: +List-Unsubscribe: , + +x-netskope-inspected: true + +------=_Part_1041_614738999.1637068032082 +Content-Type: multipart/alternative; + boundary="----=_Part_1040_551133997.1637068032082" + +------=_Part_1040_551133997.1637068032082 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + +Dear Zayo Customer,=20 + + +Please be advised that the scheduled maintenance window has closed for this= + event.=20 + +If your services are still being impacted please take a moment to review th= +e service and bounce any interfaces that may have been impacted. In the eve= +nt that this does not fully restore your service please contact the Zayo NC= +C at 1-866-236-2824 or at zayoncc@zayo.com. + + +Maintenance Ticket #: TTN-0005432100 + + + + +Maintenance Window=20 + +1st Activity Date=20 +14-Nov-2021 00:01 to 14-Nov-2021 05:00 ( Pacific )=20 + + 14-Nov-2021 08:01 to 14-Nov-2021 13:00 ( GMT )=20 + +2nd Activity Date=20 +15-Nov-2021 00:01 to 15-Nov-2021 05:00 ( Pacific )=20 + + 15-Nov-2021 08:01 to 15-Nov-2021 13:00 ( GMT )=20 + +3rd Activity Date=20 +16-Nov-2021 00:01 to 16-Nov-2021 05:00 ( Pacific )=20 + + 16-Nov-2021 08:01 to 16-Nov-2021 13:00 ( GMT )=20 + + + +Location of Maintenance: Intersection of Imperial Hwy & Nash St in El Segun= +do, CA + + +Reason for Maintenance: Zayo will implement maintenance to repair damaged f= +iber splice case, to prevent unplanned outages + + +Circuit(s) Affected:=20 + + +Circuit Id +Expected Impact +A Location Address + +Z Location Address +Legacy Circuit Id + +/IPYX/100722/ /ZYO / +Hard Down - up to 5 hours +1933 S Bundy Dr Los Angeles, CA. USA +600 W 7th St Los Angeles, CA. USA + + + + +If you have any questions or need any additional information, please contac= +t the MR group at mr@zayo.com or call 1-866-236-2824. + + +Regards, + + + + +Zayo=C2=A0Global Change Management Team/=C3=89quipe de Gestion du Changemen= +t Global=C2=A0Zayo + +Zayo | Our Fiber Fuels Global Innovation + +Toll free/No=C2=A0sans=C2=A0frais:=C2=A01.866.236.2824 + +United Kingdom Toll Free/No=C2=A0sans +frais Royaume-Uni:=C2=A00800.169.1646 + +Email/Courriel:=C2=A0mr@zayo.com=C2=A0 + +Website/Site Web:=C2=A0https://www.zayo.com + +Purpose=C2=A0|=C2=A0Network Map=C2=A0|=C2=A0Escalation List=C2=A0|=C2=A0Lin= +kedIn=C2=A0|=C2=A0Twitter=C2=A0|=C2=A0Tranzact=C2=A0 + +=C2=A0 + +This communication is the property of Zayo and may contain confidential or = +privileged information. If you have received this communication in error, p= +lease promptly notify the sender by reply e-mail and destroy all copies of = +the communication and any attachments. + +=C2=A0 + +--=20 +You received this message because you are subscribed to the Google Groups "= +Maintenance Notices" group. +To unsubscribe from this group and stop receiving emails from it, send an e= +mail to maint-notices+unsubscribe@example.com. +To view this discussion on the web visit https://groups.google.com/a/exampl= +e.com/d/msgid/maint-notices/tXhiD0000000000000000000000000000000000000000000= +00R2O1RM00YzkHXEK_RoinH1-Hiehd3w%40sfdc.net. + +------=_Part_1040_551133997.1637068032082 +Content-Type: text/html; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + +Dear Zayo Customer,=20 + +

Please be advised that the scheduled maintenance window has closed = +for this event.=20 +

If your services are still being impacted pl= +ease take a moment to review the service and bounce any interfaces that may= + have been impacted. In the event that this does not fully restore your se= +rvice please contact the Zayo NCC at 1-866-236-2824 or at zayoncc@zayo.c= +om. + +

Maintenance Ticket #: TTN-0005432100 + + + +

Maintenance Window

1st Activity Date <= +/b>
14-Nov-2021 00:01 to 14-Nov-2021 05:00 ( Pacific )=20 +
14-Nov-2021 08:01 to 14-Nov-2021 13:00 ( GMT )

2nd Activity Date
15-Nov-2021 00:01 to 15-Nov-2021 05:00 ( Pacific )= +=20 +
15-Nov-2021 08:01 to 15-Nov-2021 13:00 ( GMT )

3rd Activity Date
16-Nov-2021 00:01 to 16-Nov-2021 05:00 ( Pacific )= +=20 +
16-Nov-2021 08:01 to 16-Nov-2021 13:00 ( GMT )=20 + + +

Location of Maintenance: Intersection of Imperial Hwy & Nas= +h St in El Segundo, CA + +

Reason for Maintenance: Zayo will implement maintenance to = +repair damaged fiber splice case, to prevent unplanned outages + +

Circuit(s) Affected:
+ + + + + + + + + + + + + + + + +
Circuit IdExpected ImpactA Location AddressZ Location AddressLegacy Circuit Id
/IPYX/100722/ /ZYO /Hard Down - up to 5 hours1933 S Bundy Dr Los Angeles, CA. USA600 W 7th St Los Angeles, CA. USA
+ + +

If you have any questions or need any additional information, pleas= +e contact the MR group at mr@zayo.com or call 1-866-236-2824. + +

Regards,

+
+ +

Zayo Global Change Management Team/= +=C3=89quipe de Gestion d= +u Changement Global Zayo

+ +

Zayo | Our Fiber Fuels Global Inn= +ovation

+ +

Toll free/No s= +ans frais: 1.866.236.2824

+ +

United Kingdom Toll Free/No sans +frais Royaume-Uni:<= +/i> 0800.169.1646

+ +

Email/Cou= +rriel: mr@zayo.com<= +/u> 

+ +

Website/Site Web: https://www.zayo.com

+ +

Purpose | Network Map Escalation List LinkedIn <= +/span>Twitter Tranzact&n= +bsp; + +

&nbs= +p;

+ +

This communication is the property of Zayo and may contain confidential= + or privileged information. If you have received this communication in erro= +r, please promptly notify the sender by reply e-mail and destroy all copies= + of the communication and any attachments.

+ +

 

+ +
+ +

+ +--
+You received this message because you are subscribed to the Google Groups &= +quot;Maintenance Notices" group.
+To unsubscribe from this group and stop receiving emails from it, send an e= +mail to maint-notices+= +unsubscribe@example.com.
+To view this discussion on the web visit https://groups.google.com/a/example.com/d/msgid/maint-no= +tices/tXhiD000000000000000000000000000000000000000000000R2O1RM00YzkHXEK_Roi= +nH1-Hiehd3w%40sfdc.net.
+ +------=_Part_1040_551133997.1637068032082-- + +------=_Part_1041_614738999.1637068032082-- diff --git a/tests/unit/data/zayo/zayo7_html_parser_result.json b/tests/unit/data/zayo/zayo7_html_parser_result.json new file mode 100644 index 00000000..5d185420 --- /dev/null +++ b/tests/unit/data/zayo/zayo7_html_parser_result.json @@ -0,0 +1,15 @@ +[ + { + "circuits": [ + { + "circuit_id": "/IPYX/100722/ /ZYO /", + "impact": "OUTAGE" + } + ], + "end": 1637067600, + "maintenance_id": "TTN-0005432100", + "start": 1636876860, + "status": "COMPLETED", + "summary": "Zayo will implement maintenance to repair damaged fiber splice case, to prevent unplanned outages" + } +] diff --git a/tests/unit/data/zayo/zayo7_result.json b/tests/unit/data/zayo/zayo7_result.json new file mode 100644 index 00000000..ba5a64ec --- /dev/null +++ b/tests/unit/data/zayo/zayo7_result.json @@ -0,0 +1,17 @@ +[ + { + "account": "Example Inc.", + "circuits": [ + { + "circuit_id": "/IPYX/100722/ /ZYO /", + "impact": "OUTAGE" + } + ], + "end": 1637067600, + "maintenance_id": "TTN-0005432100", + "stamp": 1637068032, + "start": 1636876860, + "status": "COMPLETED", + "summary": "Zayo will implement maintenance to repair damaged fiber splice case, to prevent unplanned outages" + } +] diff --git a/tests/unit/data/zayo/zayo7_subject_parser_result.json b/tests/unit/data/zayo/zayo7_subject_parser_result.json new file mode 100644 index 00000000..5661a26c --- /dev/null +++ b/tests/unit/data/zayo/zayo7_subject_parser_result.json @@ -0,0 +1,6 @@ +[ + { + "account": "Example Inc.", + "maintenance_id": "TTN-0005432100" + } +] diff --git a/tests/unit/data/zayo/zayo_bad_html.html b/tests/unit/data/zayo/zayo_bad_html.html index 7c4a013e..a8318e91 100644 --- a/tests/unit/data/zayo/zayo_bad_html.html +++ b/tests/unit/data/zayo/zayo_bad_html.html @@ -1 +1 @@ -aaa \ No newline at end of file +Maintenance Ticket #: aaa diff --git a/tests/unit/data/zayo/zayo_missing_maintenance_id.html b/tests/unit/data/zayo/zayo_missing_maintenance_id.html index 4dc9e4a6..070517a8 100644 --- a/tests/unit/data/zayo/zayo_missing_maintenance_id.html +++ b/tests/unit/data/zayo/zayo_missing_maintenance_id.html @@ -12,7 +12,12 @@ 0=C2=A0

Customer:=C2=A0clientX=C2=A0

Maintenance Window=C2=A0 +Maintenance Ticket #:=C2=A0

+Maintenance Window=C2=A0
1st=C2=A0Activity Date=C2=A0
25-Sep-2020 00:01 to 25-Sep-2= diff --git a/tests/unit/data/zayo/zayo_subject_1.txt b/tests/unit/data/zayo/zayo_subject_1.txt new file mode 100644 index 00000000..87af9350 --- /dev/null +++ b/tests/unit/data/zayo/zayo_subject_1.txt @@ -0,0 +1,2 @@ +Subject: [maint-notices] CANCELLED NOTIFICATION***Some Customer,inc***ZAYO + TTN-0005432100 Planned** diff --git a/tests/unit/data/zayo/zayo_subject_1_result.json b/tests/unit/data/zayo/zayo_subject_1_result.json new file mode 100644 index 00000000..b92b9246 --- /dev/null +++ b/tests/unit/data/zayo/zayo_subject_1_result.json @@ -0,0 +1,6 @@ +[ + { + "account": "Some Customer,inc", + "maintenance_id": "TTN-0005432100" + } +] diff --git a/tests/unit/data/zayo/zayo_subject_2.txt b/tests/unit/data/zayo/zayo_subject_2.txt new file mode 100644 index 00000000..325e4f2b --- /dev/null +++ b/tests/unit/data/zayo/zayo_subject_2.txt @@ -0,0 +1,2 @@ +Subject: [maint-notices] Rescheduled Maintenance***ZAYO TTN-0005432100 + MAINTENANCE NOTIFICATION*** diff --git a/tests/unit/data/zayo/zayo_subject_2_result.json b/tests/unit/data/zayo/zayo_subject_2_result.json new file mode 100644 index 00000000..133536d3 --- /dev/null +++ b/tests/unit/data/zayo/zayo_subject_2_result.json @@ -0,0 +1,5 @@ +[ + { + "maintenance_id": "TTN-0005432100" + } +] diff --git a/tests/unit/test_e2e.py b/tests/unit/test_e2e.py index f4fef6f5..bc74586c 100644 --- a/tests/unit/test_e2e.py +++ b/tests/unit/test_e2e.py @@ -471,6 +471,11 @@ Zayo, [("email", Path(dir_path, "data", "zayo", "zayo6.eml")),], [Path(dir_path, "data", "zayo", "zayo6_result.json"),], + ), + ( + Zayo, + [("email", Path(dir_path, "data", "zayo", "zayo7.eml")),], + [Path(dir_path, "data", "zayo", "zayo7_result.json"),], ), # pylint: disable=too-many-locals ], ) @@ -596,7 +601,7 @@ def test_provider_get_maintenances(provider_class, test_data_files, result_parse Details: - Processor CombinedProcessor from Zayo failed due to: 1 validation error for Maintenance maintenance_id - field required (type=value_error.missing) + String is empty or 'None' (type=value_error) """, ), ( @@ -608,7 +613,7 @@ def test_provider_get_maintenances(provider_class, test_data_files, result_parse Failed creating Maintenance notification for Zayo. Details: - Processor CombinedProcessor from Zayo failed due to: HtmlParserZayo1 parser was not able to extract the expected data for each maintenance. - - Raw content: b'aaa' + - Raw content: b'Maintenance Ticket #: aaa\\n' - Result: [{}] """, ), diff --git a/tests/unit/test_parsers.py b/tests/unit/test_parsers.py index acfd9800..442dcc16 100644 --- a/tests/unit/test_parsers.py +++ b/tests/unit/test_parsers.py @@ -296,6 +296,16 @@ Path(dir_path, "data", "verizon", "verizon3_result.json"), ), # Zayo + ( + SubjectParserZayo1, + Path(dir_path, "data", "zayo", "zayo_subject_1.txt"), + Path(dir_path, "data", "zayo", "zayo_subject_1_result.json"), + ), + ( + SubjectParserZayo1, + Path(dir_path, "data", "zayo", "zayo_subject_2.txt"), + Path(dir_path, "data", "zayo", "zayo_subject_2_result.json"), + ), ( HtmlParserZayo1, Path(dir_path, "data", "zayo", "zayo1.html"), @@ -341,6 +351,16 @@ Path(dir_path, "data", "zayo", "zayo6.eml"), Path(dir_path, "data", "zayo", "zayo6_subject_parser_result.json"), ), + ( + HtmlParserZayo1, + Path(dir_path, "data", "zayo", "zayo7.eml"), + Path(dir_path, "data", "zayo", "zayo7_html_parser_result.json"), + ), + ( + SubjectParserZayo1, + Path(dir_path, "data", "zayo", "zayo7.eml"), + Path(dir_path, "data", "zayo", "zayo7_subject_parser_result.json"), + ), # Email Date ( EmailDateParser,