Source code for pybatfish.datamodel.acl

#   Copyright 2018 The Batfish Open Source Project
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

from typing import Dict, List, Optional  # noqa: F401

import attr
from pandas.core.indexes.frozen import FrozenList

from .primitives import DataModelElement

__all__ = [
    "AclTrace",
    "AclTraceEvent",
    "Fragment",
    "LinkFragment",
    "TextFragment",
    "TraceElement",
    "TraceTree",
    "VendorStructureId",
]


[docs]@attr.s(frozen=True) class AclTraceEvent(DataModelElement): """One event corresponding to a packet's life through an ACL. :ivar description: The description of the event """ description = attr.ib(type=Optional[str], default=None) @classmethod def from_dict(cls, json_dict): # type: (Dict) -> AclTraceEvent return AclTraceEvent(json_dict.get("description")) def __str__(self): # type: () -> str return str(self.description)
[docs]@attr.s(frozen=True) class AclTrace(DataModelElement): """The trace of a packet's life through an ACL. :ivar events: A list of :py:class:`AclTraceEvent` """ events = attr.ib(type=List[AclTraceEvent], factory=list) @classmethod def from_dict(cls, json_dict): # type: (Dict) -> AclTrace return AclTrace( [AclTraceEvent.from_dict(event) for event in json_dict.get("events", [])] ) def __str__(self): # type: () -> str return "\n".join( str(event) for event in self.events if event.description is not None )
[docs]@attr.s(frozen=True) class VendorStructureId(DataModelElement): """Identifies a vendor structure in a configuration file. :ivar filename: Filename of the configuration file :ivar structureType: Type of the vendor structure :ivar structureName: Name of the vendor structure """ filename = attr.ib(type=str) structureType = attr.ib(type=str) structureName = attr.ib(type=str) @classmethod def from_dict(cls, json_dict: Dict) -> "VendorStructureId": return VendorStructureId( filename=json_dict.get("filename", ""), structureType=json_dict.get("structureType", ""), structureName=json_dict.get("structureName", ""), )
[docs]class Fragment(DataModelElement): """An element in :py:attr:`TraceElement.fragments`, can be one of :py:class:`TextFragment` or :py:class:`LinkFragment`. """ @classmethod def from_dict(cls, json_dict: Dict) -> "Fragment": if json_dict["class"] == "org.batfish.datamodel.TraceElement$TextFragment": return TextFragment.from_dict(json_dict) elif json_dict["class"] == "org.batfish.datamodel.TraceElement$LinkFragment": return LinkFragment.from_dict(json_dict) raise ValueError("Unknown Fragment type {}".format(json_dict["class"]))
[docs]@attr.s(frozen=True) class TextFragment(Fragment): """Represents a plain-text :py:class:`Fragment`. :ivar text: Text content of the fragment """ text = attr.ib(type=str) @classmethod def from_dict(cls, json_dict: Dict) -> "TextFragment": return TextFragment(json_dict.get("text", "")) def __str__(self) -> str: return self.text
[docs]@attr.s(frozen=True) class LinkFragment(Fragment): """Represents a :py:class:`Fragment` that links to a vendor structure. :ivar text: Text content of the fragment :ivar vendorStructureId: Link of the fragment """ text = attr.ib(type=str) vendorStructureId = attr.ib(type=VendorStructureId) @classmethod def from_dict(cls, json_dict: Dict) -> "LinkFragment": return LinkFragment( json_dict.get("text", ""), VendorStructureId.from_dict(json_dict.get("vendorStructureId", {})), ) def __str__(self) -> str: return self.text
[docs]@attr.s(frozen=True) class TraceElement(DataModelElement): """Metadata used to create human-readable traces. :ivar fragments: A list of :py:class:`Fragment` which describes an element of a trace """ fragments = attr.ib(type=List[Fragment]) @classmethod def from_dict(cls, json_dict: Dict) -> "TraceElement": return TraceElement( [Fragment.from_dict(f) for f in json_dict.get("fragments", [])] ) def __str__(self) -> str: return "".join(str(fragment) for fragment in self.fragments)
[docs]@attr.s(frozen=True) class TraceTree(DataModelElement): """Represents a filter trace tree. :ivar traceElement: Metadata and description of the node :ivar children: A list of sub-traces, i.e. children of the node """ traceElement = attr.ib(type=TraceElement) children = attr.ib(type=List["TraceTree"]) @classmethod def from_dict(cls, json_dict: Dict) -> "TraceTree": return TraceTree( TraceElement.from_dict(json_dict.get("traceElement", {})), [TraceTree.from_dict(child) for child in json_dict.get("children", [])], ) def __str__(self) -> str: lines = [str(self.traceElement)] stack = [iter(self.children)] while stack: children_iter = stack[-1] try: child = next(children_iter) lines.append(" " * len(stack) + "- " + str(child.traceElement)) stack.append(iter(child.children)) except StopIteration: stack.pop() return "\n".join(lines) def _repr_html_(self) -> str: if self.children: children_section = [] for child in self.children: children_section.append("<li>{}</li>".format(child._repr_html_())) return "{} <ul>{}</ul>".format(self.traceElement, "".join(children_section)) return str(self.traceElement)
class TraceTreeList(FrozenList): """Custom list wrapper class for List<TraceTree> that prettifies console and HTML output""" def __str__(self) -> str: return "\n".join("- " + str(tree) for tree in self) def _repr_html_(self) -> str: list_items = ["<li>" + tree._repr_html_() + "</li>" for tree in self] return "<ul>" + "".join(list_items) + "</ul>"