Skip to content

Commit

Permalink
Updates for 0.2.0 release
Browse files Browse the repository at this point in the history
Move to constants, fix doctest, make dns actions more clear, clean up wording to be more clear
  • Loading branch information
itdependsnetworks committed May 27, 2021
1 parent c2cdb90 commit cb249f0
Show file tree
Hide file tree
Showing 16 changed files with 211 additions and 243 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ before_script:
- "poetry config virtualenvs.create false"
- "poetry install --no-interaction"
script:
- "invoke coverage"
- "invoke pytest"

jobs:
include:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This library intends to keep the following tenets:

* Must not be any dependencies required to run the library.
* May be some optional dependencies, to be managed by the user in opt in fashion.
* Shall prefer functional programming over object oriented programming.
* Shall prefer functions over classes.
* Shall prefer a folder and file structure that is flat.
* Shall leverage docstrings as the primary documentation mechanism.
* Must provide examples in every public function.
Expand Down
31 changes: 1 addition & 30 deletions netutils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,3 @@
"""Initialization file for library."""

from . import asn
from . import dns
from . import constants
from . import interface
from . import ip
from . import lib_mapper
from . import mac
from . import password
from . import ping
from . import protocol_mapper
from . import route
from . import variables
from . import vlan

__all__ = [
"asn",
"constants",
"dns",
"interface",
"ip",
"lib_mapper",
"mac",
"password",
"ping",
"protocol_mapper",
"route",
"variables",
"vlan",
]
__version__ = "0.1.2"
__version__ = "0.2.0"
6 changes: 0 additions & 6 deletions netutils/config/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
"""Initialization file for config methods."""

from . import clean
from . import compliance
from . import parser

__all__ = ["clean", "compliance", "parser"]
7 changes: 3 additions & 4 deletions netutils/config/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@


import re
from ..variables import CLEAN_FILTERS, SANITIZE_FILTERS # pylint: disable=relative-beyond-top-level


def clean_config(config, filters=CLEAN_FILTERS): # pylint: disable=dangerous-default-value
def clean_config(config, filters):
r"""Given a list of regex patterns, delete those lines that match.
Args:
config (str): A string representation of a device configuration.
filters (list, optional): A list of regex patterns used to delete remove configuration. Defaults to an empty list.
filters (list): A list of regex patterns used to delete remove configuration.
Returns:
str: Stripped down configuration.
Expand Down Expand Up @@ -53,7 +52,7 @@ def clean_config(config, filters=CLEAN_FILTERS): # pylint: disable=dangerous-de
return config


def sanitize_config(config, filters=SANITIZE_FILTERS): # pylint: disable=dangerous-default-value
def sanitize_config(config, filters):
r"""Given a dictionary of filters, remove sensitive data from the provided config.
Args:
Expand Down
173 changes: 173 additions & 0 deletions netutils/constants.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,134 @@
"""Constant definitions used in project."""

# This variable provides mapping for known interface variants, to the associated long form.
BASE_INTERFACES = {
"ATM": "ATM",
"AT": "ATM",
"B": "Bdi",
"Bd": "Bdi",
"Bdi": "Bdi",
"EOBC": "EOBC",
"EO": "EOBC",
"Ethernet": "Ethernet",
"Eth": "Ethernet",
"eth": "Ethernet",
"Et": "Ethernet",
"et": "Ethernet",
"FastEthernet": "FastEthernet",
"FastEth": "FastEthernet",
"FastE": "FastEthernet",
"Fast": "FastEthernet",
"Fas": "FastEthernet",
"FE": "FastEthernet",
"Fa": "FastEthernet",
"fa": "FastEthernet",
"Fddi": "Fddi",
"FD": "Fddi",
"FortyGigabitEthernet": "FortyGigabitEthernet",
"FortyGigEthernet": "FortyGigabitEthernet",
"FortyGigEth": "FortyGigabitEthernet",
"FortyGigE": "FortyGigabitEthernet",
"FortyGig": "FortyGigabitEthernet",
"FGE": "FortyGigabitEthernet",
"FO": "FortyGigabitEthernet",
"Fo": "FortyGigabitEthernet",
"FiftyGigabitEthernet": "FiftyGigabitEthernet",
"FiftyGigEthernet": "FiftyGigabitEthernet",
"FiftyGigEth": "FiftyGigabitEthernet",
"FiftyGigE": "FiftyGigabitEthernet",
"FI": "FiftyGigabitEthernet",
"Fi": "FiftyGigabitEthernet",
"fi": "FiftyGigabitEthernet",
"GigabitEthernet": "GigabitEthernet",
"GigEthernet": "GigabitEthernet",
"GigEth": "GigabitEthernet",
"GigE": "GigabitEthernet",
"Gig": "GigabitEthernet",
"GE": "GigabitEthernet",
"Ge": "GigabitEthernet",
"ge": "GigabitEthernet",
"Gi": "GigabitEthernet",
"gi": "GigabitEthernet",
"HundredGigabitEthernet": "HundredGigabitEthernet",
"HundredGigEthernet": "HundredGigabitEthernet",
"HundredGigEth": "HundredGigabitEthernet",
"HundredGigE": "HundredGigabitEthernet",
"HundredGig": "HundredGigabitEthernet",
"Hu": "HundredGigabitEthernet",
"TwentyFiveGigabitEthernet": "TwentyFiveGigE",
"TwentyFiveGigEthernet": "TwentyFiveGigE",
"TwentyFiveGigEth": "TwentyFiveGigE",
"TwentyFiveGigE": "TwentyFiveGigE",
"TwentyFiveGig": "TwentyFiveGigE",
"TF": "TwentyFiveGigE",
"Tf": "TwentyFiveGigE",
"tf": "TwentyFiveGigE",
"TwoHundredGigabitEthernet": "TwoHundredGigabitEthernet",
"TwoHundredGigEthernet": "TwoHundredGigabitEthernet",
"TwoHundredGigEth": "TwoHundredGigabitEthernet",
"TwoHundredGigE": "TwoHundredGigabitEthernet",
"TwoHundredGig": "TwoHundredGigabitEthernet",
"TH": "TwoHundredGigabitEthernet",
"Th": "TwoHundredGigabitEthernet",
"th": "TwoHundredGigabitEthernet",
"FourHundredGigabitEthernet": "FourHundredGigabitEthernet",
"FourHundredGigEthernet": "FourHundredGigabitEthernet",
"FourHundredGigEth": "FourHundredGigabitEthernet",
"FourHundredGigE": "FourHundredGigabitEthernet",
"FourHundredGig": "FourHundredGigabitEthernet",
"F": "FourHundredGigabitEthernet",
"f": "FourHundredGigabitEthernet",
"Loopback": "Loopback",
"loopback": "Loopback",
"Lo": "Loopback",
"lo": "Loopback",
"Management": "Management",
"Mgmt": "Management",
"mgmt": "Management",
"Ma": "Management",
"Management_short": "Ma",
"MFR": "MFR",
"Multilink": "Multilink",
"Mu": "Multilink",
"n": "nve",
"nv": "nve",
"nve": "nve",
"PortChannel": "Port-channel",
"Port-channel": "Port-channel",
"Port-Channel": "Port-channel",
"port-channel": "Port-channel",
"po": "Port-channel",
"Po": "Port-channel",
"POS": "POS",
"PO": "POS",
"Serial": "Serial",
"Se": "Serial",
"S": "Serial",
"TenGigabitEthernet": "TenGigabitEthernet",
"TenGigEthernet": "TenGigabitEthernet",
"TenGigEth": "TenGigabitEthernet",
"TenGig": "TenGigabitEthernet",
"TeGig": "TenGigabitEthernet",
"Ten": "TenGigabitEthernet",
"T": "TenGigabitEthernet",
"Te": "TenGigabitEthernet",
"te": "TenGigabitEthernet",
"Tunnel": "Tunnel",
"Tun": "Tunnel",
"Tu": "Tunnel",
"Twe": "TwentyFiveGigE",
"Tw": "TwoGigabitEthernet",
"Two": "TwoGigabitEthernet",
"Virtual-Access": "Virtual-Access",
"Vi": "Virtual-Access",
"Virtual-Template": "Virtual-Template",
"Vt": "Virtual-Template",
"VLAN": "VLAN",
"V": "VLAN",
"Vl": "VLAN",
"Wlan-GigabitEthernet": "Wlan-GigabitEthernet",
}

# The default mac format
DEFAULT_MAC_FORMAT = "MAC_DOT_FOUR"

Expand All @@ -24,3 +153,47 @@
MAC_DOT_FOUR=r"([a-fA-F0-9]{4}[\.]){2}([a-fA-F0-9]{4})",
MAC_NO_SPECIAL=r"([a-fA-F0-9]{12})",
)

"""Variable definitions used in project, purposely not constants to signal to use these variables can be overridden."""

# This variable maps a full interface name, to an opinionated shortened name.
REVERSE_MAPPING = {
"ATM": "At",
"EOBC": "EO",
"Ethernet": "Et",
"FastEthernet": "Fa",
"Fddi": "FD",
"FortyGigabitEthernet": "Fo",
"GigabitEthernet": "Gi",
"HundredGigabitEthernet": "Hu",
"Loopback": "Lo",
"Management": "Ma",
"MFR": "MFR",
"Multilink": "Mu",
"Port-channel": "Po",
"POS": "PO",
"Serial": "Se",
"TenGigabitEthernet": "Te",
"Tunnel": "Tu",
"TwoGigabitEthernet": "Two",
"TwentyFiveGigE": "Twe",
"Virtual-Access": "Vi",
"Virtual-Template": "Vt",
"VLAN": "Vl",
"Wlan-GigabitEthernet": "Wl-Gi",
}

# These are base level filters to provide documentation of how a CLEAN_FILTER can be used, This is a private variable, and subject
# to change without notice between revisions.
_PROVIDED_CLEAN_FILTERS = [
{"regex": r"^Current\s+configuration.*\n"},
{"regex": r"^Building\s+configuration.*\n"},
{"regex": r"^ntp\s+clock-period.*\n"},
]

# These are base level filters to provide documentation of how a SANITIZE_FILTERS can be used, This is a private variable, and subject
# to change without notice between revisions.
_PROVIDED_SANITIZE_FILTERS = [
{"regex": r"(username\s+\S+\spassword\s+5\s+)\S+(\s+role\s+\S+)", "replace": "\\1<redacted_config>\\2"},
{"regex": r"(username\s+\S+\s+privilege\s+15\s+password\s+0\s+)\S+", "replace": "\\1<redacted_config>"},
]
29 changes: 20 additions & 9 deletions netutils/dns.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@


def fqdn_to_ip(hostname):
"""Provides the IP address of a resolvable name.
"""Provides the IP address of a resolvable name on the machine it is running from.
There are many reasons that a valid FQDN may not be resolvable, such as a network error
from your machine to the DNS server, an upstream DNS issue, etc.
Args:
hostname (str): An FQDN that may or may not be resolvable.
Expand All @@ -19,13 +22,17 @@ def fqdn_to_ip(hostname):
>>>
Raises:
socket.gaierror: If FQDN is not resolvable, leverage is_fqdn_valid to check first.
socket.gaierror: If FQDN is not resolvable, leverage is_fqdn_resolvable to check first.
"""
return socket.gethostbyname(hostname)
# The data structure is complex, only require the first item, and drill down from there.
return socket.getaddrinfo(hostname, 0)[0][4][0]


def is_fqdn_resolvable(hostname):
"""Verifies whether a hostname is resolvable on the machine it is running from.
def is_fqdn_valid(hostname):
"""Verifies whether a hostname is resolvable.
There are many reasons that a valid FQDN may not be resolvable, such as a network error
from your machine to the DNS server, an upstream DNS issue, etc.
Args:
hostname (str): A FQDN that may or may not be resolvable.
Expand All @@ -34,15 +41,19 @@ def is_fqdn_valid(hostname):
bool: The result as to whether or not the domain was valid.
Example:
>>> from netutils.dns import is_fqdn_valid
>>> is_fqdn_valid("google.com")
>>> from netutils.dns import is_fqdn_resolvable
>>> is_fqdn_resolvable("google.com")
True
>>> is_fqdn_valid("nevergonnagiveyouup.pizza")
>>> is_fqdn_resolvable("nevergonnagiveyouup.pizza")
False
>>>
"""
try:
socket.gethostbyname(hostname)
socket.getaddrinfo(hostname, 0)
return True
except socket.error:
return False


# Provide until transition to 1.0
is_fqdn_valid = is_fqdn_resolvable
2 changes: 1 addition & 1 deletion netutils/interface.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Functions for working with interface."""

from .variables import BASE_INTERFACES, REVERSE_MAPPING
from .constants import BASE_INTERFACES, REVERSE_MAPPING


def split_interface(interface):
Expand Down
4 changes: 2 additions & 2 deletions netutils/ip.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def is_netmask(netmask):
True
>>> is_netmask('24')
False
>>> is_netmask('255.255.266.0)
>>> is_netmask('255.255.266.0')
False
"""
try:
Expand Down Expand Up @@ -158,7 +158,7 @@ def cidr_to_netmask(cidr):
Example:
>>> from netutils.ip import netmask_to_cidr
>>> cidr_to_netmask(24)
'255.255.255.0
'255.255.255.0'
>>> cidr_to_netmask(17)
'255.255.128.0'
"""
Expand Down
2 changes: 1 addition & 1 deletion netutils/ping.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def tcp_ping(ip, port, timeout=1): # pylint: disable=invalid-name
>>> from netutils.ping import tcp_ping
>>> tcp_ping("1.1.1.1", 443)
True
>>> tcp_ping("1.0.100.0", 443)
>>> tcp_ping("1.0.100.0", 27)
False
>>>
"""
Expand Down
2 changes: 1 addition & 1 deletion netutils/route.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def longest_prefix_match(ip_addr, routes):
>>> lookup = "10.1.1.245"
>>> routes = [{"network": "192.168.1.1", "mask": "255.255.255.255"},{"network": "10.1.1.0", "mask": "24"}]
>>> longest_prefix_match(lookup, routes)
IPv4Network('10.1.1.0/24')
'10.1.1.0/24'
"""
if not isinstance(routes, list):
raise TypeError(f"'routing_table' should be a list, got {type(routes)}")
Expand Down
Loading

0 comments on commit cb249f0

Please sign in to comment.