mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
fix: reject non-VPCS nodes in the VPCS config tool
VPCS syntax typed into another node's console is silently discarded (IOS answers % Invalid input) while the tool still reports success. get_device_ports_from_topology now carries the GNS3 node type through to callers, and VPCSCommands fails device preparation with a per-device error unless the node type is vpcs.
This commit is contained in:
4 files changed
+93
No files matched your search
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
Device config tool tests with mocked topology and Nornir layers.
|
||||
|
||||
Covers the VPCS node-type guard and the error contract shared by
|
||||
device_config_send / device_show_run / vpcs_config_set.
|
||||
"""
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
VPCS_MOD = "gns3server.agent.gns3_copilot.tools_v2.vpcs_tools_netmiko"
|
||||
|
||||
|
||||
def _topology_ports(node_type):
|
||||
"""Mocked get_device_ports_from_topology return value for one device."""
|
||||
return {"PC1": {"port": 5000, "node_type": node_type}}
|
||||
|
||||
|
||||
class TestVPCSNodeTypeGuard:
|
||||
|
||||
def test_non_vpcs_node_is_rejected(self):
|
||||
from gns3server.agent.gns3_copilot.tools_v2.vpcs_tools_netmiko import VPCSCommands
|
||||
|
||||
with patch(f"{VPCS_MOD}.get_device_ports_from_topology",
|
||||
return_value=_topology_ports("iou")) as topo:
|
||||
result = VPCSCommands()._run(json.dumps({
|
||||
"project_id": "0c0fde25-6ead-4413-a283-ea8fd2324291",
|
||||
"device_configs": [{"device_name": "PC1", "commands": ["ip 10.0.0.1/24"]}],
|
||||
}))
|
||||
assert topo.called
|
||||
assert len(result) == 1
|
||||
assert result[0]["device_name"] == "PC1"
|
||||
assert result[0]["status"] == "failed"
|
||||
assert "not a VPCS node" in result[0]["error"]
|
||||
|
||||
def test_missing_node_type_is_rejected(self):
|
||||
from gns3server.agent.gns3_copilot.tools_v2.vpcs_tools_netmiko import VPCSCommands
|
||||
|
||||
with patch(f"{VPCS_MOD}.get_device_ports_from_topology",
|
||||
return_value={"PC1": {"port": 5000}}):
|
||||
result = VPCSCommands()._run(json.dumps({
|
||||
"project_id": "0c0fde25-6ead-4413-a283-ea8fd2324291",
|
||||
"device_configs": [{"device_name": "PC1", "commands": ["ip 10.0.0.1/24"]}],
|
||||
}))
|
||||
assert result[0]["status"] == "failed"
|
||||
assert "unknown-type" in result[0]["error"]
|
||||
|
||||
def test_vpcs_node_passes_the_guard(self):
|
||||
from gns3server.agent.gns3_copilot.tools_v2.vpcs_tools_netmiko import VPCSCommands
|
||||
|
||||
tool = VPCSCommands()
|
||||
nornir = MagicMock()
|
||||
host_result = MagicMock(failed=False)
|
||||
host_result.result = "OK"
|
||||
nornir.run.return_value = {"PC1": host_result}
|
||||
with patch(f"{VPCS_MOD}.get_device_ports_from_topology",
|
||||
return_value=_topology_ports("vpcs")), \
|
||||
patch.object(VPCSCommands, "_initialize_nornir", return_value=nornir):
|
||||
result = tool._run(json.dumps({
|
||||
"project_id": "0c0fde25-6ead-4413-a283-ea8fd2324291",
|
||||
"device_configs": [{"device_name": "PC1", "commands": ["ip 10.0.0.1/24"]}],
|
||||
}))
|
||||
assert result[0]["status"] == "success"
|
||||
assert result[0]["output"] == "OK"
|
||||
Reference in new issue
Block a user