Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/dev/code_reference/hash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Hash

::: netutils.hash
options:
show_submodules: True
1 change: 1 addition & 0 deletions docs/user/include_jinja_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
| paloalto_panos_brace_to_set | netutils.config.conversion.paloalto_panos_brace_to_set |
| fqdn_to_ip | netutils.dns.fqdn_to_ip |
| is_fqdn_resolvable | netutils.dns.is_fqdn_resolvable |
| hash_data | netutils.hash.hash_data |
| abbreviated_interface_name | netutils.interface.abbreviated_interface_name |
| abbreviated_interface_name_list | netutils.interface.abbreviated_interface_name_list |
| canonical_interface_name | netutils.interface.canonical_interface_name |
Expand Down
1 change: 1 addition & 0 deletions docs/user/lib_use_cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Functions are grouped with like functions, such as IP or MAC address based funct
- Conversion - Provides the ability to convert between different syntax's within the same OS.
- Parsing - Provides the ability to parse configuration for the minor differences that are there.
- DNS - Provides the ability to work with DNS, such as validating that a FQDN is resolvable.
- Hash - Provide a convenience method for hashlib to be used in Jinja2
- Interface - Provides the ability to work with interface names, expanding, abbreviating, and splitting the names.
- IP Address - Provides the ability to work with IP addresses, primarily exposing Python `ipaddress` functionality.
- Library Helpers - Provides helpers to pull useful information, e.g. NAPALM getters.
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ nav:
- Banner: "dev/code_reference/banner.md"
- Configs: "dev/code_reference/configs.md"
- DNS: "dev/code_reference/dns.md"
- Hash: "dev/code_reference/hash.md"
- Interface: "dev/code_reference/interface.md"
- IP: "dev/code_reference/ip.md"
- Library Helpers: "dev/code_reference/lib_helpers.md"
Expand Down
39 changes: 39 additions & 0 deletions netutils/hash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Functions for hashing data."""
import hashlib
import typing as t


def hash_data(data: bytes, algorithm: str) -> t.Any:
"""Convenience function primarily built to expose hashlib to Jinja.

Args:
data (bytes): Data to hash.
algorithm (str): Hashing algorithm to use.

Returns:
bytes: Hashed data.

Raises:
AttributeError: Invalid algorithm specified.

Examples:
>>> from netutils.hash import hash_data
>>> hash_data("test", "md5")
'098f6bcd4621d373cade4e832627b4f6'

>>> from jinja2 import Environment
>>> from netutils.utils import jinja2_convenience_function
>>>
>>> env = Environment(trim_blocks=True, lstrip_blocks=True)
>>> env.filters.update(jinja2_convenience_function())
>>> template_str = "{{ 'test' | hash_data('md5') }}"
>>> template = env.from_string(template_str)
>>> result = template.render()
>>> print(result)
098f6bcd4621d373cade4e832627b4f6
"""
if not isinstance(data, bytes):
data = str(data).encode()
algorithm = algorithm.lower()
hasher = getattr(hashlib, algorithm)
return hasher(data).hexdigest()
1 change: 1 addition & 0 deletions netutils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"get_napalm_getters": "lib_helpers.get_napalm_getters",
"paloalto_panos_brace_to_set": "config.conversion.paloalto_panos_brace_to_set",
"get_upgrade_path": "os_version.get_upgrade_path",
"hash_data": "hash.hash_data",
}


Expand Down
70 changes: 70 additions & 0 deletions tests/unit/test_hash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Tests for the hash functions."""
import pytest

from netutils.hash import hash_data


EXPECTED_HASHES = [
(
"md5",
"b31be8e621f7d7cb80289c3634a2463f",
),
(
"sha1",
"696de4dae5e77515f0460c78dc712f9b055ae7f2",
),
(
"sha224",
"bead2aad3706b211e825f5919db78dceca775cae4bd5b58078652ad2",
),
(
"sha256",
"a9675e13424e5009161f7b7da6c1bb7e091f1401459176e8efce23c0f1fc5ba9",
),
(
"sha384",
"4476744d8167497e9cbc85901a753be7bef5a33a1ce36926c5a21b68c7c2d420daa6cd347d515dd21af1e93927c7ba5c",
),
(
"sha512",
"75dc2cbd4b2e025f8c0a1f495bc321343eef8d5561dfa02e29f77b32b9685f7add41169e7f9fb085f5110ac4635de286437c758c115b8eadacc20f086e39cc28",
),
(
"blake2b",
"82a094789746f0a0405845ced806282e1bd6f317dd8a9464b6e660105e16108f6582c0f091d787a833c8d8fd5c53004dac2571113045fefe25d1f159f8c1f934",
),
(
"blake2s",
"b8fecb4ff8b866c7638985eb66d4ba9cb5f908d0b1a25def4c593ba140b791af",
),
(
"sha3_224",
"f0b2b40e360489e0e2da83094238e9591677e1d304d70a1feb1188f2",
),
(
"sha3_256",
"308a5dd839eb055ee84f0b2c99344526a716c58a14dffb704b6784437aee91ba",
),
(
"sha3_384",
"80e4d0e43bf447ef4d3a6dcd1a795a3573bc6f34d42b81ee78bb757bd86ed6bc9210d752797fd62bfbdb6fc17eb52ed1",
),
(
"sha3_512",
"13dddfadbe95282b6b0da1c7c3c7dc28c086cdcc3de39baafb1fb45913ac39c0d9744927c10fb1d858ab257069d3ef367c8913553e7f7eabb1f4ffe6480e5924",
),
]


@pytest.mark.parametrize("algorithm,expected", EXPECTED_HASHES)
def test_hash_data(algorithm, expected):
"""Test the hash_data function."""
data = "Network To Code"
assert hash_data(data, algorithm) == expected


def test_hash_data_invalid_algorithm():
"""Test the hash_data function with an invalid algorithm."""
data = "Network To Code"
with pytest.raises(AttributeError):
hash_data(data, "invalid")