Refactor BaseDevice and update Device model structure
- Enhanced the `BaseDevice` class with methods for loading templates and parsing configuration data using TTP. - Updated the `Device` model to use lists for `interfaces` and `vlans`, allowing for multiple entries. - Introduced new TTP template files for structured data parsing.
This commit is contained in:
@@ -2,11 +2,21 @@ from abc import ABC, abstractmethod
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ttp import ttp
|
||||
from oxi.interfaces.contract import Device
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from oxi.interfaces.contract import Interfaces, System, Vlans
|
||||
|
||||
|
||||
class BaseDevice(ABC):
|
||||
_REQUIRED_SECTIONS: frozenset[str] = frozenset({"system", "interfaces", "vlans"})
|
||||
|
||||
def __init__(self, config: str):
|
||||
self.config: str = config
|
||||
self._loaded_template = self._load_template()
|
||||
self._raw: dict = self._run_ttp()
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def template(self) -> str:
|
||||
@@ -15,23 +25,37 @@ class BaseDevice(ABC):
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def vlans(self) -> "Vlans": ...
|
||||
def vlans(self) -> list["Vlans"]: ...
|
||||
|
||||
@abstractmethod
|
||||
def interfaces(self) -> "Interfaces": ...
|
||||
def interfaces(self) -> list["Interfaces"]: ...
|
||||
|
||||
@abstractmethod
|
||||
def system(self) -> "System": ...
|
||||
|
||||
def __load_template(self):
|
||||
def _load_template(self):
|
||||
path = Path(__file__).parent / "template" / self.template
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(f"Template {self.template} not found")
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
def run(self):
|
||||
self.load = self.__load_template()
|
||||
return self.load
|
||||
def _run_ttp(self) -> dict:
|
||||
p = ttp(data=self.config, template=self._loaded_template)
|
||||
p.parse()
|
||||
raw: dict = p.result()[0][0]
|
||||
missing = self._REQUIRED_SECTIONS - raw.keys()
|
||||
if missing:
|
||||
raise ValueError(
|
||||
f"{self.__class__.__name__}: TTP template '{self.template}' "
|
||||
f"did not produce required sections: {sorted(missing)}. "
|
||||
f"Got: {sorted(raw.keys())}"
|
||||
)
|
||||
return raw
|
||||
|
||||
|
||||
BaseDevice()
|
||||
def parse(self) -> Device:
|
||||
data = {
|
||||
"system": self.system(),
|
||||
"interfaces": self.interfaces(),
|
||||
"vlans": self.vlans(),
|
||||
}
|
||||
return Device(**data)
|
||||
|
||||
@@ -16,10 +16,10 @@ class System(BaseModel):
|
||||
|
||||
class Vlans(BaseModel):
|
||||
id: int
|
||||
name: str = Field(alias="description")
|
||||
name: str | None = Field(default=None, alias="description")
|
||||
|
||||
|
||||
class Device(BaseModel):
|
||||
system: System
|
||||
interfaces: Interfaces
|
||||
vlans: Vlans
|
||||
interfaces: list[Interfaces] = []
|
||||
vlans: list[Vlans] = []
|
||||
|
||||
7
oxi/interfaces/models/templates/_template.ttp
Normal file
7
oxi/interfaces/models/templates/_template.ttp
Normal file
@@ -0,0 +1,7 @@
|
||||
<doc>
|
||||
</doc>
|
||||
<var>
|
||||
</var>
|
||||
|
||||
<group>
|
||||
</group>
|
||||
7
oxi/interfaces/models/templates/mikrotik.ttp
Normal file
7
oxi/interfaces/models/templates/mikrotik.ttp
Normal file
@@ -0,0 +1,7 @@
|
||||
<doc>
|
||||
</doc>
|
||||
<var>
|
||||
</var>
|
||||
|
||||
<group>
|
||||
</group>
|
||||
Reference in New Issue
Block a user