summaryrefslogtreecommitdiff
path: root/pyvyos/specs
diff options
context:
space:
mode:
authorRoberto Bertó <463349+robertoberto@users.noreply.github.com>2025-11-02 19:55:55 -0300
committerGitHub <noreply@github.com>2025-11-02 19:55:55 -0300
commit6ca1269b138696b69c33d2db4bcf7dd03ea4caeb (patch)
tree4c0a634730df2123ff506252cbec050de006dac8 /pyvyos/specs
parent1ada32975f0bb559ec7526e0dd545700dde1cb94 (diff)
parent6b4e9015744ab8c9f17a6b8e23387cd676b1d827 (diff)
downloadpyvyos-6ca1269b138696b69c33d2db4bcf7dd03ea4caeb.tar.gz
pyvyos-6ca1269b138696b69c33d2db4bcf7dd03ea4caeb.zip
Merge pull request #27 from vyos-contrib/feat/architecture-and-quality-improvements
feat: v0.4.0 - Architecture refactor, bug fixes, and quality improvem…
Diffstat (limited to 'pyvyos/specs')
-rw-r--r--pyvyos/specs/__init__.py12
-rw-r--r--pyvyos/specs/commands/__init__.py13
-rw-r--r--pyvyos/specs/commands/config_file.py36
-rw-r--r--pyvyos/specs/commands/configure.py38
-rw-r--r--pyvyos/specs/commands/generate.py20
-rw-r--r--pyvyos/specs/commands/image.py33
-rw-r--r--pyvyos/specs/commands/reset.py20
-rw-r--r--pyvyos/specs/commands/retrieve.py27
-rw-r--r--pyvyos/specs/commands/show.py20
-rw-r--r--pyvyos/specs/commands/system.py27
-rw-r--r--pyvyos/specs/models.py31
11 files changed, 277 insertions, 0 deletions
diff --git a/pyvyos/specs/__init__.py b/pyvyos/specs/__init__.py
new file mode 100644
index 0000000..d12c764
--- /dev/null
+++ b/pyvyos/specs/__init__.py
@@ -0,0 +1,12 @@
+"""PyVyOS Pydantic specs for optional request/response validation."""
+
+# Feature detection: gracefully degrade if pydantic not available
+try:
+ from pydantic import BaseModel
+ PYDANTIC_AVAILABLE = True
+except ImportError:
+ PYDANTIC_AVAILABLE = False
+ BaseModel = None # type: ignore
+
+__all__ = ["PYDANTIC_AVAILABLE"]
+
diff --git a/pyvyos/specs/commands/__init__.py b/pyvyos/specs/commands/__init__.py
new file mode 100644
index 0000000..1d8e8b3
--- /dev/null
+++ b/pyvyos/specs/commands/__init__.py
@@ -0,0 +1,13 @@
+"""Pydantic models for individual VyOS API commands."""
+
+from .config_file import ConfigFileSaveRequest, ConfigFileLoadRequest
+from .configure import ConfigureSetRequest, ConfigureDeleteRequest, ConfigureMultipleOpRequest
+
+__all__ = [
+ "ConfigFileSaveRequest",
+ "ConfigFileLoadRequest",
+ "ConfigureSetRequest",
+ "ConfigureDeleteRequest",
+ "ConfigureMultipleOpRequest",
+]
+
diff --git a/pyvyos/specs/commands/config_file.py b/pyvyos/specs/commands/config_file.py
new file mode 100644
index 0000000..911b094
--- /dev/null
+++ b/pyvyos/specs/commands/config_file.py
@@ -0,0 +1,36 @@
+"""Pydantic models for config-file operations."""
+
+from typing import List, Literal, Optional
+
+try:
+ from pydantic import BaseModel, Field
+ from ..models import ApiRequest
+except ImportError:
+ BaseModel = None # type: ignore
+ Field = None # type: ignore
+ ApiRequest = None # type: ignore
+
+
+if BaseModel:
+
+ class ConfigFileSaveRequest(ApiRequest):
+ """Request model for config-file save operation."""
+
+ op: Literal["save"] = "save"
+ path: List[str] = Field(
+ default_factory=list,
+ description="Required by VyOS API, typically empty array"
+ )
+ file: Optional[str] = None
+
+
+ class ConfigFileLoadRequest(ApiRequest):
+ """Request model for config-file load operation."""
+
+ op: Literal["load"] = "load"
+ path: List[str] = Field(
+ default_factory=list,
+ description="Required by VyOS API, typically empty array"
+ )
+ file: str # Required for load
+
diff --git a/pyvyos/specs/commands/configure.py b/pyvyos/specs/commands/configure.py
new file mode 100644
index 0000000..d80aa3f
--- /dev/null
+++ b/pyvyos/specs/commands/configure.py
@@ -0,0 +1,38 @@
+"""Pydantic models for configure operations."""
+
+from typing import Dict, List, Literal, Union, Any
+
+try:
+ from pydantic import BaseModel, Field
+ from ..models import ApiRequest
+except ImportError:
+ BaseModel = None # type: ignore
+ Field = None # type: ignore
+ ApiRequest = None # type: ignore
+
+
+if BaseModel:
+
+ class ConfigureSetRequest(ApiRequest):
+ """Request model for configure set operation."""
+
+ op: Literal["set"] = "set"
+ path: Union[List[str], List[List[str]]] # Required
+
+
+ class ConfigureDeleteRequest(ApiRequest):
+ """Request model for configure delete operation."""
+
+ op: Literal["delete"] = "delete"
+ path: List[str] # Required
+
+
+ class ConfigureMultipleOpRequest(BaseModel):
+ """Request model for configure multiple operations."""
+
+ op: Literal["set", "delete"]
+ path: Union[List[str], List[List[str]]]
+
+ class Config:
+ extra = "allow"
+
diff --git a/pyvyos/specs/commands/generate.py b/pyvyos/specs/commands/generate.py
new file mode 100644
index 0000000..40aa2a4
--- /dev/null
+++ b/pyvyos/specs/commands/generate.py
@@ -0,0 +1,20 @@
+"""Pydantic models for generate operations."""
+
+from typing import List, Literal, Optional
+
+try:
+ from pydantic import BaseModel
+ from ..models import ApiRequest
+except ImportError:
+ BaseModel = None # type: ignore
+ ApiRequest = None # type: ignore
+
+
+if BaseModel:
+
+ class GenerateRequest(ApiRequest):
+ """Request model for generate operation."""
+
+ op: Literal["generate"] = "generate"
+ path: Optional[List[str]] = None
+
diff --git a/pyvyos/specs/commands/image.py b/pyvyos/specs/commands/image.py
new file mode 100644
index 0000000..973bae4
--- /dev/null
+++ b/pyvyos/specs/commands/image.py
@@ -0,0 +1,33 @@
+"""Pydantic models for image operations."""
+
+from typing import List, Literal, Optional
+
+try:
+ from pydantic import BaseModel
+ from ..models import ApiRequest
+except ImportError:
+ BaseModel = None # type: ignore
+ ApiRequest = None # type: ignore
+
+
+if BaseModel:
+
+ class ImageAddRequest(ApiRequest):
+ """Request model for image add operation."""
+
+ op: Literal["add"] = "add"
+ path: Optional[List[str]] = None
+ url: Optional[str] = None
+ file: Optional[str] = None
+ name: Optional[str] = None
+
+
+ class ImageDeleteRequest(ApiRequest):
+ """Request model for image delete operation."""
+
+ op: Literal["delete"] = "delete"
+ path: Optional[List[str]] = None
+ url: Optional[str] = None
+ file: Optional[str] = None
+ name: Optional[str] = None
+
diff --git a/pyvyos/specs/commands/reset.py b/pyvyos/specs/commands/reset.py
new file mode 100644
index 0000000..ac02bfe
--- /dev/null
+++ b/pyvyos/specs/commands/reset.py
@@ -0,0 +1,20 @@
+"""Pydantic models for reset operations."""
+
+from typing import List, Literal, Optional
+
+try:
+ from pydantic import BaseModel
+ from ..models import ApiRequest
+except ImportError:
+ BaseModel = None # type: ignore
+ ApiRequest = None # type: ignore
+
+
+if BaseModel:
+
+ class ResetRequest(ApiRequest):
+ """Request model for reset operation."""
+
+ op: Literal["reset"] = "reset"
+ path: Optional[List[str]] = None
+
diff --git a/pyvyos/specs/commands/retrieve.py b/pyvyos/specs/commands/retrieve.py
new file mode 100644
index 0000000..65efbbf
--- /dev/null
+++ b/pyvyos/specs/commands/retrieve.py
@@ -0,0 +1,27 @@
+"""Pydantic models for retrieve operations."""
+
+from typing import List, Literal, Optional
+
+try:
+ from pydantic import BaseModel
+ from ..models import ApiRequest
+except ImportError:
+ BaseModel = None # type: ignore
+ ApiRequest = None # type: ignore
+
+
+if BaseModel:
+
+ class RetrieveShowConfigRequest(ApiRequest):
+ """Request model for retrieve showConfig operation."""
+
+ op: Literal["showConfig"] = "showConfig"
+ path: Optional[List[str]] = None
+
+
+ class RetrieveReturnValuesRequest(ApiRequest):
+ """Request model for retrieve returnValues operation."""
+
+ op: Literal["returnValues"] = "returnValues"
+ path: Optional[List[str]] = None
+
diff --git a/pyvyos/specs/commands/show.py b/pyvyos/specs/commands/show.py
new file mode 100644
index 0000000..2fb2b97
--- /dev/null
+++ b/pyvyos/specs/commands/show.py
@@ -0,0 +1,20 @@
+"""Pydantic models for show operations."""
+
+from typing import List, Literal, Optional
+
+try:
+ from pydantic import BaseModel
+ from ..models import ApiRequest
+except ImportError:
+ BaseModel = None # type: ignore
+ ApiRequest = None # type: ignore
+
+
+if BaseModel:
+
+ class ShowRequest(ApiRequest):
+ """Request model for show operation."""
+
+ op: Literal["show"] = "show"
+ path: Optional[List[str]] = None
+
diff --git a/pyvyos/specs/commands/system.py b/pyvyos/specs/commands/system.py
new file mode 100644
index 0000000..9f5e5c9
--- /dev/null
+++ b/pyvyos/specs/commands/system.py
@@ -0,0 +1,27 @@
+"""Pydantic models for system operations (reboot, poweroff)."""
+
+from typing import List, Literal
+
+try:
+ from pydantic import BaseModel
+ from ..models import ApiRequest
+except ImportError:
+ BaseModel = None # type: ignore
+ ApiRequest = None # type: ignore
+
+
+if BaseModel:
+
+ class RebootRequest(ApiRequest):
+ """Request model for reboot operation."""
+
+ op: Literal["reboot"] = "reboot"
+ path: List[str] = ["now"]
+
+
+ class PoweroffRequest(ApiRequest):
+ """Request model for poweroff operation."""
+
+ op: Literal["poweroff"] = "poweroff"
+ path: List[str] = ["now"]
+
diff --git a/pyvyos/specs/models.py b/pyvyos/specs/models.py
new file mode 100644
index 0000000..a57ac82
--- /dev/null
+++ b/pyvyos/specs/models.py
@@ -0,0 +1,31 @@
+"""Base Pydantic models for PyVyOS API requests and responses."""
+
+from typing import Any, Dict, List, Optional, Union
+
+if False: # type checking only
+ from pydantic import BaseModel
+else:
+ try:
+ from pydantic import BaseModel, Field
+ except ImportError:
+ BaseModel = None # type: ignore
+ Field = None # type: ignore
+
+
+class ApiRequest(BaseModel):
+ """Base request model for VyOS API operations."""
+
+ op: str
+ path: Optional[Union[List[str], List[List[str]], List[Dict[str, Any]]]] = None
+
+ class Config:
+ extra = "allow" # Allow additional fields (file, url, name, etc.)
+
+
+class ApiResponse(BaseModel):
+ """Base response model for VyOS API responses."""
+
+ success: bool
+ data: Union[Dict[str, Any], List[Any], str, None]
+ error: Optional[str] = None
+