From 35cf7d4dd7135b638fe5bf450dd04eb67aa74225 Mon Sep 17 00:00:00 2001 From: Dmitrii Gudov Date: Wed, 11 Mar 2026 15:32:40 +0300 Subject: [PATCH] rewrite --- examples/{2hosts'n'switch => 2hostsswitch}/table.csv | 8 ++++---- examples/{4hosts'n'2switchs => 4hosts2switchs}/table.csv | 0 src/netdiag/base.py | 4 ++-- src/netdiag/domain/models.py | 8 ++++++++ src/netdiag/output/d2.py | 4 +++- src/netdiag/parse/__init__.py | 1 + 6 files changed, 18 insertions(+), 7 deletions(-) rename examples/{2hosts'n'switch => 2hostsswitch}/table.csv (64%) rename examples/{4hosts'n'2switchs => 4hosts2switchs}/table.csv (100%) diff --git a/examples/2hosts'n'switch/table.csv b/examples/2hostsswitch/table.csv similarity index 64% rename from examples/2hosts'n'switch/table.csv rename to examples/2hostsswitch/table.csv index cdb42e7..ddc651b 100644 --- a/examples/2hosts'n'switch/table.csv +++ b/examples/2hostsswitch/table.csv @@ -1,10 +1,10 @@ Name,Role,Adapter,Interface,Master Interface,Network,VLAN,Network IP,Mask,Device IP,Default Gateway -PC1,Host,Adapter1,eth1,vlan7,A,,,,,, +PC1,Host,Adapter1,eth1,vlan7,A,,,,, PC1,Host,,vlan7,,7,10.10.10.0,/24,10.10.10.7,0.0.0.0, -PC2,Host,Adapter1,eth1,vlan9,B,,,,,, +PC2,Host,Adapter1,eth1,vlan9,B,,,,, PC2,Host,,vlan9,,9,10.10.10.0,/24,10.10.10.9,0.0.0.0, -com,Switch,Adapter1,eth2,vlan7,A,7,,,,, -com,Switch,Adapter2,eth3,vlan9,B,9,,,,, +com,Switch,Adapter1,eth2,vlan7,A,7,,,, +com,Switch,Adapter2,eth3,vlan9,B,9,,,, com,Switch,,vlan7,bridge,,,,,, com,Switch,,vlan9,bridge,,,,,, com,Switch,,bridge,,,,,,, \ No newline at end of file diff --git a/examples/4hosts'n'2switchs/table.csv b/examples/4hosts2switchs/table.csv similarity index 100% rename from examples/4hosts'n'2switchs/table.csv rename to examples/4hosts2switchs/table.csv diff --git a/src/netdiag/base.py b/src/netdiag/base.py index 8aca63c..ae9202d 100644 --- a/src/netdiag/base.py +++ b/src/netdiag/base.py @@ -21,9 +21,9 @@ def run(argv: list[str] | None = None) -> None: raw_devices = parse_csv(Path(args.input)) topology = convert_raw_topology(raw_devices) - generate_diagram(topology, Path(args.output) / "diagram.png") + # generate_diagram(topology, Path(args.output) / "diagram.png") make_yaml(topology, Path(args.output) / "topology.yaml") - # generate_d2_diagram(topology, Path(args.output) / "diagram.d2") + generate_d2_diagram(topology, Path(args.output) / "diagram.d2") logging.info("All tasks completed successfully.") diff --git a/src/netdiag/domain/models.py b/src/netdiag/domain/models.py index 02fecdc..2a1855b 100644 --- a/src/netdiag/domain/models.py +++ b/src/netdiag/domain/models.py @@ -16,6 +16,8 @@ class Interface: def __init__( self, name: str, + adapter: Optional[str] = None, + master_interface: Optional[str] = None, ip_address: Optional[str] = None, network: Optional[str] = None, default_gateway: Optional[str] = None, @@ -28,11 +30,17 @@ class Interface: raise ValueError("Interface 'network' must be a string or None") if default_gateway is not None and not isinstance(default_gateway, str): raise ValueError("Interface 'default_gateway' must be a string or None") + if adapter is not None and not isinstance(adapter, str): + raise ValueError("Interface 'adapter' must be a string or None") + if master_interface is not None and not isinstance(master_interface, str): + raise ValueError("Interface 'master_interface' must be a string or None") self.name = name self.ip_address = ip_address self.network = network self.default_gateway = default_gateway + self.adapter = adapter + self.master_interface = master_interface def __repr__(self) -> str: return f"Interface(name={self.name}, ip_address={self.ip_address}, network={self.network}, default_gateway={self.default_gateway})" diff --git a/src/netdiag/output/d2.py b/src/netdiag/output/d2.py index d156e5f..64a1602 100644 --- a/src/netdiag/output/d2.py +++ b/src/netdiag/output/d2.py @@ -6,6 +6,7 @@ from ..domain.models import VirtualInterface from pathlib import Path from py_d2 import D2Diagram, D2Shape, D2Connection from py_d2.shape import Shape +from py_d2.connection import Direction # https://d2lang.com/tour/themes/ THEME_NUMBER = 200 @@ -71,6 +72,7 @@ def generate_d2_diagram(topology: Topology, output_path: Path) -> None: connection = D2Connection( shape_1=f"{device.name}.{interface.adapter}", shape_2=interface.network, + direction=Direction("--"), ) connections.append(connection) @@ -102,7 +104,7 @@ def _generate_picture(diagram: Path, output_path: Path) -> None: ) res = subprocess.run( - ["d2", f"--theme={THEME_NUMBER}", str(diagram), str(output_path)], + ["d2", f"--theme={THEME_NUMBER}", str(diagram)], check=True, capture_output=True, ) diff --git a/src/netdiag/parse/__init__.py b/src/netdiag/parse/__init__.py index f316b0e..2c72744 100644 --- a/src/netdiag/parse/__init__.py +++ b/src/netdiag/parse/__init__.py @@ -14,6 +14,7 @@ class RawDevices: if not isinstance(fields, dict): raise ValueError("RawDevices 'fields' must be a dictionary") if any(not isinstance(k, str) for k in fields.keys()): + print(fields.keys()) raise ValueError("RawDevices 'fields' keys must be strings") self.id = id