Skip to content

Commit a01e040

Browse files
updated based on feedback.
1 parent f14c8a0 commit a01e040

File tree

3 files changed

+39
-46
lines changed

3 files changed

+39
-46
lines changed

docs/user/lib_use_cases_lib_mapper.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ sot_driver = device.platform.napalm_driver
2020

2121

2222
# Connect to device via Napalm
23-
driver = napalm.get_network_driver("ios")
23+
driver = napalm.get_network_driver(sot_driver)
2424

2525
device = driver(
2626
hostname="device.name",
@@ -38,6 +38,20 @@ net_con = NTC(host=device.name, username="demo", password="secret", device_type=
3838

3939
Another use case could be using an example like the above in an Ansible filter. That would allow you to write a filter utilizing whichever automation library you needed without having to store the driver for each one in your Source of Truth.
4040

41+
There is also a dynamically built mapping that gives you all of the libraries given a normalized name, here is a condensed snippet to understand the data structure of `KEY_TO_LIB_MAPPER`:
42+
43+
```python
44+
{
45+
"cisco_ios": {
46+
"ansible": "cisco.ios.ios",
47+
"napalm": "ios",
48+
},
49+
"cisco_nxos": {
50+
"ansible": "cisco.nxos.nxos",
51+
"napalm": "nxos",
52+
}
53+
}
54+
```
4155

4256
## Aerleon Mapper
4357

netutils/lib_mapper.py

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -684,36 +684,19 @@
684684
}
685685

686686

687-
def get_lib_mappings(
688-
lib_mapping_reverse: t.Optional[t.Dict[str, t.Dict[str, str]]] = None
689-
) -> t.Dict[str, t.Dict[str, str]]:
690-
"""Generates a dictionary of all available network driver mappings.
691-
692-
Args:
693-
lib_mapping_reverse: A reverse mapping of library names to their normalized names. Defaults to NAME_TO_LIB_MAPPER_REVERSE if not provided.
694-
695-
Returns:
696-
A dictionary where the keys are normalized driver names and the values are dictionaries mapping tool names to their respective driver names.
697-
698-
Examples:
699-
>>> from netutils.lib_mapper import get_lib_mappings
700-
>>> mappings = get_lib_mappings()
701-
>>> mappings["a10"]
702-
{'ansible': 'a10.acos_axapi.a10', 'netmiko': 'a10', 'ntc_templates': 'a10'}
703-
>>> mappings["cisco_ios"]["ansible"]
704-
'cisco.ios.ios'
705-
>>> mappings["cisco_ios"]["netmiko"]
706-
'cisco_ios'
707-
>>>
708-
"""
709-
if not lib_mapping_reverse:
710-
lib_mapping_reverse = NAME_TO_LIB_MAPPER_REVERSE
711-
network_driver_mappings: t.Dict[str, t.Dict[str, str]] = {}
712-
713-
# initialize mapping from netutils library
714-
for tool_name, mappings in lib_mapping_reverse.items():
715-
for normalized_name, mapped_name in mappings.items():
716-
network_driver_mappings.setdefault(normalized_name, {})
717-
network_driver_mappings[normalized_name][tool_name] = mapped_name
718-
719-
return network_driver_mappings
687+
# Creates a structure like this:
688+
# {
689+
# "cisco_ios": {
690+
# "ansible": "cisco.ios.ios",
691+
# "napalm": "ios",
692+
# },
693+
# "cisco_nxos": {
694+
# "ansible": "cisco.nxos.nxos",
695+
# "napalm": "nxos",
696+
# },
697+
KEY_TO_LIB_MAPPER: t.Dict[str, t.Dict[str, str]] = {}
698+
699+
for tool_name, mappings in NAME_TO_LIB_MAPPER_REVERSE.items():
700+
for normalized_name, mapped_name in mappings.items():
701+
KEY_TO_LIB_MAPPER.setdefault(normalized_name, {})
702+
KEY_TO_LIB_MAPPER[normalized_name][tool_name] = mapped_name

tests/unit/test_lib_mapper.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"""Test for the lib_mapper definitions."""
22

33
import unittest
4-
import importlib.util
5-
import sys
64

75
import pytest
86

@@ -100,11 +98,11 @@ def test_lib_mapper_ntctemplates_reverse_only():
10098
assert lib_mapper.NTCTEMPLATES_LIB_MAPPER["cisco_xe"] == "cisco_xe"
10199

102100

103-
def test_get_lib_mappings():
101+
def test_key_to_lib_mapper():
104102
"""Test that the data structure returns as expected in get_lib_mappings."""
105-
assert lib_mapper.get_lib_mappings()["arista_eos"]["ansible"] == "arista.eos.eos"
106-
assert lib_mapper.get_lib_mappings()["arista_eos"]["pyntc"] == "arista_eos_eapi"
107-
assert lib_mapper.get_lib_mappings()["cisco_ios"]["dna_center"] == "IOS"
103+
assert lib_mapper.KEY_TO_LIB_MAPPER["arista_eos"]["ansible"] == "arista.eos.eos"
104+
assert lib_mapper.KEY_TO_LIB_MAPPER["arista_eos"]["pyntc"] == "arista_eos_eapi"
105+
assert lib_mapper.KEY_TO_LIB_MAPPER["cisco_ios"]["dna_center"] == "IOS"
108106

109107

110108
@pytest.mark.parametrize("lib", LIBRARIES)
@@ -139,15 +137,13 @@ def setUp(self):
139137
"""Gather all mapper dictionaries from the module."""
140138
self.mappers = {}
141139
self.reverse_mappers = {}
142-
spec = importlib.util.spec_from_file_location("lib_mapper", lib_mapper.__file__)
143-
lib_mapper_module = importlib.util.module_from_spec(spec)
144-
sys.modules["lib_mapper"] = lib_mapper_module
145-
spec.loader.exec_module(lib_mapper_module)
146140

147141
# Collect all variables ending with _LIB_MAPPER and _LIB_MAPPER_REVERSE
148-
for name, value in vars(lib_mapper_module).items():
142+
for name in dir(lib_mapper):
143+
value = getattr(lib_mapper, name)
144+
149145
if not isinstance(value, dict) or any(
150-
name.startswith(prefix) for prefix in ["NAME_TO", "_", "MAIN", "DNA_CENTER"]
146+
name.startswith(prefix) for prefix in ["NAME_TO", "KEY_TO", "_", "MAIN", "DNA_CENTER"]
151147
):
152148
continue
153149
if name.endswith("_LIB_MAPPER") and isinstance(value, dict):

0 commit comments

Comments
 (0)