Files
napalm-tplink-jetstream/tests/unit/test_snmp_agent.py
T
Christian Manivong c2f0f7c20a
Tests / Test (Python 3.10) (pull_request) Successful in 17s
Tests / Test (Python 3.11) (pull_request) Successful in 17s
Tests / Test (Python 3.12) (pull_request) Successful in 21s
feat!: configure_snmp_agent with the caller's values replaces fix_snmp (0.3.0)
fix_snmp hard-coded community "public" and found the management VLAN
for the source interface with a substring match, so 10.0.0.1 matched
10.0.0.10 and a DNS name never matched (#3).

The driver implements napalm-device-types 4.13's configure_snmp_agent
steps: the caller's community (read-only, viewDefault), the source
interface set to the VLAN whose address is exactly the listen address
or the management address, configuration saved, and the community
checked in show snmp community. Contact and location are reported as
not set; there is no verified CLI for them on this switch. A value
that would break the CLI is refused.

The requirements now name napalm-device-types 4.13 in both files.

BREAKING CHANGE: run_device_action is removed.

Part of #3 and #4.
2026-10-17 08:36:52 +02:00

85 lines
2.8 KiB
Python

"""The SNMP agent through napalm-device-types' configure_snmp_agent (netOrk #1105).
fix_snmp hard-coded community "public" and found the management VLAN by a
substring match (10.0.0.1 matched 10.0.0.10, #3). The community is the caller's
now, and the source interface is the VLAN that carries exactly the management
address.
"""
from __future__ import annotations
from unittest.mock import MagicMock
import pytest
from napalm_tplink_jetstream.tplink_jetstream import TPLinkJetstreamDriver
SETTINGS = {"community": "c0mm", "allowed_sources": ["10.7.224.20"], "contact": "ops"}
SHOW_IP_INTERFACE = """\
VLAN1 is up, line protocol is up
Primary IP address: 10.0.0.10/24
VLAN8 is up, line protocol is up
Primary IP address: 10.0.0.1/24
"""
@pytest.fixture
def driver():
d = TPLinkJetstreamDriver("10.0.0.1", "admin", "pw")
d.device = MagicMock()
d.sent: list[str] = []
d.device.send_command.side_effect = lambda cmd, **kw: d.sent.append(cmd) or ""
d._conf_prompt = lambda: r"\(config\)#"
d._enter_config_mode = MagicMock()
d._exit_config_mode = MagicMock()
d._save_config = MagicMock()
d._send_command = MagicMock(
side_effect=lambda cmd: SHOW_IP_INTERFACE
if cmd == "show ip interface"
else "Index Community-Name Access\n1 c0mm read-only\n"
)
return d
def test_the_callers_community(driver):
result = driver.configure_snmp_agent(SETTINGS)
assert result["success"] is True
assert 'snmp-server community "c0mm" read-only "viewDefault"' in driver.sent
assert not any("public" in c for c in driver.sent)
driver._save_config.assert_called_once()
def test_the_source_interface_is_the_vlan_of_exactly_the_management_address(driver):
driver.configure_snmp_agent(SETTINGS)
assert "snmp-server source-interface vlan 8" in driver.sent
def test_contact_and_location_are_reported_as_not_set(driver):
steps = {s["step"]: s for s in driver.configure_snmp_agent(SETTINGS)["steps"]}
assert "contact" in steps["configure"]["output"]
def test_a_community_the_switch_does_not_list_fails(driver):
driver._send_command.side_effect = lambda cmd: (
SHOW_IP_INTERFACE if cmd == "show ip interface" else "1 public read-only\n"
)
assert driver.configure_snmp_agent(SETTINGS)["success"] is False
@pytest.mark.parametrize("community", ["two words", 'q"uote', ""])
def test_a_community_that_would_break_the_cli_is_refused(driver, community):
result = driver.configure_snmp_agent({"community": community, "allowed_sources": []})
assert result["success"] is False
assert driver.sent == []
def test_the_old_action_is_gone():
for name in ("run_device_action", "_action_fix_snmp", "_detect_management_vlan"):
assert not hasattr(TPLinkJetstreamDriver, name), name