18 Commits

Author SHA1 Message Date
IluaAir
ae1e69d5fd Refactor dump_json method to use model_dump_json
All checks were successful
CI / lint (pull_request) Successful in 1m0s
CI / test (3.10) (pull_request) Successful in 27s
CI / test (3.11) (pull_request) Successful in 35s
CI / test (3.12) (pull_request) Successful in 36s
CI / test (3.13) (pull_request) Successful in 37s
CI / ci-success (pull_request) Successful in 2s
- Fix the `dump_json` method in the `ModelView` class to call `model_dump_json` instead of `model_dump`, ensuring consistency in JSON serialization.
- Added a new test case in `TestListModelView` to verify the functionality of `dump_json` and check for correct IP address serialization.
2026-07-23 11:15:10 +03:00
IluaAir
260c02f81d Add type hints and docstrings for VLANs, Interfaces, and System properties in NodeConfig
- Enhanced the `vlans`, `interfaces`, and `system` properties with type hints for better clarity and type checking.
- Added detailed docstrings to each property, describing the return types and structure of the associated configurations.
2026-07-23 10:24:51 +03:00
sttarsky
6bc47f1b4f Merge branch 'main' into dev 2026-07-19 10:28:04 +03:00
IluaAir
9575450811 Update CI workflow to use custom runner and container
All checks were successful
CI / lint (pull_request) Successful in 3m11s
CI / test (3.10) (pull_request) Successful in 27s
CI / test (3.11) (pull_request) Successful in 36s
CI / test (3.12) (pull_request) Successful in 36s
CI / test (3.13) (pull_request) Successful in 37s
CI / ci-success (pull_request) Successful in 1s
- Changed the runner from `ubuntu-latest` to `rassbery` for the `ci-success` job.
- Specified a custom container `catthehacker/ubuntu:act-22.04` for the job environment, enhancing compatibility and consistency in the CI process.
2026-07-19 10:24:25 +03:00
IluaAir
27d8931dee Update Mikrotik template to use 'shutdown' attribute for interface management
- Replaced 'disabled' with 'shutdown' in the Mikrotik template to align with the new interface state management.
- Updated expected configuration JSON to set 'shutdown' to true for accurate testing and validation of interface configurations.
2026-07-16 00:21:10 +03:00
IluaAir
099869ff6d Add shutdown command to Huawei interface template and update configuration files
- Included the `shutdown` command in the Huawei interface template to manage interface states.
- Added a new interface configuration in `config.conf` with the `shutdown` command.
- Updated the expected output JSON to reflect the new interface and its shutdown state for accurate testing and validation of configurations.
2026-07-15 16:26:46 +03:00
sttarsky
472508d51d Merge pull request #4 from sttarsky/sttarsky-patch-1
Bump version from 0.1.1 to 0.1.2
2026-07-15 16:02:05 +03:00
sttarsky
663cbad352 Bump version from 0.1.1 to 0.1.2 2026-07-15 16:01:21 +03:00
sttarsky
79dbb99186 Merge pull request #3 from sttarsky/dev
Dev v0.1.2
2026-07-15 15:58:14 +03:00
IluaAir
6846b30df0 Add shutdown command to Qtech interface template and update expected configuration files
- Included the `shutdown` command in the Qtech interface template to manage interface states.
- Updated expected output JSON files to set the `shutdown` attribute to true for accurate testing and validation of interface configurations.
2026-07-15 15:51:48 +03:00
IluaAir
6009f0bf9c Add shutdown command to H3C interface template and update related configuration files
- Included the `shutdown` command in the H3C interface template to reflect the new interface state management.
- Updated the `config.conf` file to include the `shutdown` command for the `HundredGigE1/0/3` interface.
- Modified the expected output JSON to set the `shutdown` attribute to true, ensuring accurate testing and validation of interface configurations.
2026-07-15 15:48:28 +03:00
sttarsky
721d4b27ca Merge pull request #2 from sttarsky/dev
Dev
2026-07-15 00:54:46 +03:00
IluaAir
da2bf2f876 Update version to 0.1.1 and add coverage file to .gitignore
- Incremented the project version in `pyproject.toml` from 0.1.0 to 0.1.1.
- Added `.coverage` to `.gitignore` to prevent tracking of coverage reports.
2026-07-15 00:47:56 +03:00
IluaAir
a521c60d76 Add shutdown attribute to Interfaces class and update related templates
- Added a `shutdown` boolean attribute to the `Interfaces` class to manage interface states.
- Updated the `eltex.ttp` template to include the `shutdown` command based on the new attribute.
- Modified expected configuration JSON files for various devices to reflect the new `shutdown` attribute, ensuring accurate testing and validation of interface configurations.
2026-07-15 00:47:10 +03:00
sttarsky
62530980aa Merge dev into main: initial oxipy release
Oxidized API client with TTP-based, multi-vendor config parsing into
Pydantic models.
- Core API: OxiAPI, Node, NodeView, NodeConfig, ModelView
- HTTP layer with retries/timeout and OxiAPIError (NodeNotFound -> 404)
- Vendor parsers: Keenetic, MikroTik, Qtech, Huawei, Eltex, H3C, Quasar
- Shared utils: VLAN range expansion, UTF-8 decoding
- Test suite: golden fixtures per vendor + unit/network/view tests
- Tooling: Ruff lint/format config, CI for GitHub and Gitea
- Docs: README + extending-models and templates guides
2026-06-12 20:41:34 +03:00
IluaAir
fb2d135187 Add CI success verification step to workflows
- Introduced a new job `ci-success` in both Gitea and GitHub CI workflows to verify that all previous jobs (lint and test) succeeded.
- The job runs on `ubuntu-latest` and exits with a failure status if any prior job has failed or been cancelled, enhancing the reliability of the CI process.
2026-06-12 20:36:27 +03:00
IluaAir
074f2e9340 Update .gitignore and remove .python-version file
All checks were successful
CI / lint (pull_request) Successful in 45s
CI / test (3.10) (pull_request) Successful in 28s
CI / test (3.11) (pull_request) Successful in 42s
CI / test (3.12) (pull_request) Successful in 47s
CI / test (3.13) (pull_request) Successful in 39s
- Added .python-version to .gitignore to prevent tracking of Python version files.
- Deleted the .python-version file as it is no longer needed for the project.
2026-06-12 00:03:55 +03:00
IluaAir
dd7f117380 Add CI workflows for Gitea and GitHub
- Created a CI workflow for Gitea with linting and testing jobs using Python versions 3.10 to 3.13.
- Established a CI workflow for GitHub with similar linting and testing jobs, ensuring consistency across platforms.
- Both workflows utilize the `uv` tool for dependency management and testing, enhancing the project's CI/CD capabilities.
2026-06-11 23:57:11 +03:00
24 changed files with 241 additions and 8 deletions

50
.gitea/workflows/ci.yml Normal file
View File

@@ -0,0 +1,50 @@
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
lint:
runs-on: rassbery
container: catthehacker/ubuntu:act-22.04
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v6
- name: Sync dependencies
run: uv sync --group dev
- name: Ruff lint
run: uv run ruff check --output-format=github .
- name: Ruff format check
run: uv run ruff format --check .
test:
runs-on: rassbery
container: catthehacker/ubuntu:act-22.04
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
python-version: ${{ matrix.python-version }}
- name: Sync dependencies
run: uv sync --group dev
- name: Run tests
run: uv run pytest -q
ci-success:
if: always()
needs: [lint, test]
runs-on: rassbery
container: catthehacker/ubuntu:act-22.04
steps:
- name: Verify all jobs succeeded
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
run: exit 1

47
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v6
- name: Sync dependencies
run: uv sync --group dev
- name: Ruff lint
run: uv run ruff check --output-format=github .
- name: Ruff format check
run: uv run ruff format --check .
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
python-version: ${{ matrix.python-version }}
- name: Sync dependencies
run: uv sync --group dev
- name: Run tests
run: uv run pytest -q
ci-success:
if: always()
needs: [lint, test]
runs-on: ubuntu-latest
steps:
- name: Verify all jobs succeeded
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
run: exit 1

2
.gitignore vendored
View File

@@ -6,8 +6,10 @@ dist/
wheels/ wheels/
*.egg-info *.egg-info
main.py main.py
.coverage
# Virtual environments # Virtual environments
.venv .venv
.python-version
.idea .idea
.DS_Store .DS_Store
.vscode .vscode

View File

@@ -1 +0,0 @@
3.13

View File

@@ -10,6 +10,9 @@ from .interfaces import BaseDevice, device_registry
if TYPE_CHECKING: if TYPE_CHECKING:
from requests import Session from requests import Session
from oxi.interfaces.contract import Interfaces, System, Vlans
TModel = TypeVar("TModel", bound=BaseModel) TModel = TypeVar("TModel", bound=BaseModel)
@@ -20,7 +23,7 @@ class ModelView(Generic[TModel]):
def dump_json(self) -> str: def dump_json(self) -> str:
if isinstance(self._model, list): if isinstance(self._model, list):
return json.dumps( return json.dumps(
[item.model_dump(by_alias=True) for item in self._model], [item.model_dump_json(by_alias=True) for item in self._model],
ensure_ascii=False, ensure_ascii=False,
) )
return self._model.model_dump_json(by_alias=True) return self._model.model_dump_json(by_alias=True)
@@ -83,13 +86,42 @@ class NodeConfig:
return self.text return self.text
@property @property
def vlans(self): def vlans(self) -> list["Vlans"]:
"""
Returns the list of VLAN configurations for the node.
:return: List of Vlans associated with the device.
vlan_id: int
name: str | None = Field(default=None, alias="description")
:rtype: list[oxi.interfaces.contract.Vlans]
"""
return ModelView(self._parsed_data.vlans)
return ModelView(self._parsed_data.vlans) return ModelView(self._parsed_data.vlans)
@property @property
def interfaces(self): def interfaces(self) -> list["Interfaces"]:
"""
Returns the list of Interfaces configurations for the node.
:return: List of Interfaces associated with the device.
name: str = Field(alias="interface")
ip_address: IPv4Address | None = None
mask: int | None = None
description: str | None = None
shutdown: bool = False
:rtype: list[oxi.interfaces.contract.Interfaces]
"""
return ModelView(self._parsed_data.interfaces) return ModelView(self._parsed_data.interfaces)
@property @property
def system(self): def system(self) -> "System":
"""
Returns the Systems configurations for the node.
:return: System associated with the device.
model: str
serial_number: str
version: str
:rtype: oxi.interfaces.contract.System
"""
return ModelView(self._parsed_data.system) return ModelView(self._parsed_data.system)

View File

@@ -26,6 +26,7 @@ class Interfaces(Base):
ip_address: IPv4Address | None = None ip_address: IPv4Address | None = None
mask: int | None = None mask: int | None = None
description: str | None = None description: str | None = None
shutdown: bool = False
class Vlans(Base): class Vlans(Base):

View File

@@ -25,6 +25,7 @@ Active-image: {{ ignore }} {{ _start_ }}
<group name="interfaces"> <group name="interfaces">
interface {{ interface | ORPHRASE }} interface {{ interface | ORPHRASE }}
shutdown {{ shutdown | set(True) }}
ip address {{ ip_address }} {{ mask | to_cidr }} ip address {{ ip_address }} {{ mask | to_cidr }}
name {{ description | ORPHRASE}} name {{ description | ORPHRASE}}
description {{ description | ORPHRASE }} description {{ description | ORPHRASE }}

View File

@@ -23,6 +23,7 @@ default_system = {
interface {{ interface }} interface {{ interface }}
description {{ description | ORPHRASE }} description {{ description | ORPHRASE }}
ip address {{ ip_address }} {{ mask | to_cidr }} ip address {{ ip_address }} {{ mask | to_cidr }}
shutdown {{ shutdown | set(True) }}
</group> </group>
<group name="vlans"> <group name="vlans">

View File

@@ -21,6 +21,7 @@ default_system = {
<group name="interfaces"> <group name="interfaces">
interface {{ interface }} interface {{ interface }}
description {{ description | ORPHRASE }} description {{ description | ORPHRASE }}
shutdown {{ shutdown | set(True) }}
ip address {{ ip_address }} {{ mask | to_cidr }} ip address {{ ip_address }} {{ mask | to_cidr }}
</group> </group>
<group name="vlans"> <group name="vlans">

View File

@@ -28,9 +28,9 @@ add address={{ ip_address | _start_ }}/{{ mask }} interface={{ name }} network={
## not disabled and comment with/without quotes ## not disabled and comment with/without quotes
add address={{ ip_address | _start_ }}/{{ mask }} comment={{ description | ORPHRASE | exclude("disabled=") | strip('"')}} interface={{ name }} network={{ network }} add address={{ ip_address | _start_ }}/{{ mask }} comment={{ description | ORPHRASE | exclude("disabled=") | strip('"')}} interface={{ name }} network={{ network }}
## disabled no comment ## disabled no comment
add address={{ ip_address | _start_ }}/{{ mask }} disabled={{ disabled | replace("yes","True") | strip('"')}} interface={{ name }} network={{ network }} add address={{ ip_address | _start_ }}/{{ mask }} disabled={{ shutdown | replace("yes","True") | strip('"')}} interface={{ name }} network={{ network }}
## disabled with comment with/without quotes ## disabled with comment with/without quotes
add address={{ ip_address | _start_ }}/{{ mask }} comment={{ description | ORPHRASE | exclude("disabled=") | strip('"') }} disabled={{ disabled }} interface={{ name }} network={{ network }} add address={{ ip_address | _start_ }}/{{ mask }} comment={{ description | ORPHRASE | exclude("disabled=") | strip('"') }} disabled={{ shutdown | replace("yes","True") | strip('"')}} interface={{ name }} network={{ network }}
</group> </group>
<group name="vlans"> <group name="vlans">

View File

@@ -29,6 +29,7 @@ default_system = {
<group name="interfaces"> <group name="interfaces">
interface {{ interface | ORPHRASE }} interface {{ interface | ORPHRASE }}
shutdown {{ shutdown | set(True) }}
description {{ description | ORPHRASE }} description {{ description | ORPHRASE }}
ip address {{ ip_address }} {{ mask | to_cidr }} ip address {{ ip_address }} {{ mask | to_cidr }}
</group> </group>

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "oxipy" name = "oxipy"
version = "0.1.0" version = "0.1.4"
description = "Python client for Oxidized API with TTP-based config parsing" description = "Python client for Oxidized API with TTP-based config parsing"
readme = "README.md" readme = "README.md"
license = "Apache-2.0" license = "Apache-2.0"

View File

@@ -7,30 +7,35 @@
"interfaces": [ "interfaces": [
{ {
"interface": "TenGigabitEthernet1/0/2", "interface": "TenGigabitEthernet1/0/2",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "FREE" "description": "FREE"
}, },
{ {
"interface": "TenGigabitEthernet1/0/11", "interface": "TenGigabitEthernet1/0/11",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "FREE" "description": "FREE"
}, },
{ {
"interface": "vlan 1700", "interface": "vlan 1700",
"shutdown": false,
"ip_address": "13.36.8.1", "ip_address": "13.36.8.1",
"mask": 24, "mask": 24,
"description": "sw-test_HW" "description": "sw-test_HW"
}, },
{ {
"interface": "vlan 666", "interface": "vlan 666",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "test" "description": "test"
}, },
{ {
"interface": "vlan 777", "interface": "vlan 777",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "test2" "description": "test2"

View File

@@ -152,6 +152,7 @@ interface HundredGigE1/0/3
port link-type trunk port link-type trunk
undo port trunk permit vlan 1 undo port trunk permit vlan 1
port trunk permit vlan 221 1112 to 1116 1512 port trunk permit vlan 221 1112 to 1116 1512
shutdown
storm-constrain broadcast pps 1100 1000 storm-constrain broadcast pps 1100 1000
storm-constrain multicast pps 1100 1000 storm-constrain multicast pps 1100 1000
storm-constrain control shutdown storm-constrain control shutdown

View File

@@ -7,72 +7,84 @@
"interfaces": [ "interfaces": [
{ {
"interface": "Bridge-Aggregation1", "interface": "Bridge-Aggregation1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "HW_TEST_1" "description": "HW_TEST_1"
}, },
{ {
"interface": "Bridge-Aggregation2", "interface": "Bridge-Aggregation2",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "HW_TEST_2" "description": "HW_TEST_2"
}, },
{ {
"interface": "Bridge-Aggregation3", "interface": "Bridge-Aggregation3",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "HW_TEST_3" "description": "HW_TEST_3"
}, },
{ {
"interface": "Bridge-Aggregation4", "interface": "Bridge-Aggregation4",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "HW_TEST_4" "description": "HW_TEST_4"
}, },
{ {
"interface": "NULL0", "interface": "NULL0",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "Vlan-interface1", "interface": "Vlan-interface1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "Vlan-interface12", "interface": "Vlan-interface12",
"shutdown": false,
"ip_address": "15.12.16.246", "ip_address": "15.12.16.246",
"mask": 30, "mask": 30,
"description": "BGP to OSPF1" "description": "BGP to OSPF1"
}, },
{ {
"interface": "Vlan-interface3000", "interface": "Vlan-interface3000",
"shutdown": false,
"ip_address": "192.168.19.254", "ip_address": "192.168.19.254",
"mask": 25, "mask": 25,
"description": "L3 to HW_TEST_3" "description": "L3 to HW_TEST_3"
}, },
{ {
"interface": "HundredGigE1/0/3", "interface": "HundredGigE1/0/3",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "HW_TEST_1" "description": "HW_TEST_1"
}, },
{ {
"interface": "HundredGigE1/0/63", "interface": "HundredGigE1/0/63",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "HW_TEST_2" "description": "HW_TEST_2"
}, },
{ {
"interface": "M-GigabitEthernet0/0/0", "interface": "M-GigabitEthernet0/0/0",
"shutdown": false,
"ip_address": "192.168.10.101", "ip_address": "192.168.10.101",
"mask": 24, "mask": 24,
"description": null "description": null
}, },
{ {
"interface": "M-GigabitEthernet0/0/1", "interface": "M-GigabitEthernet0/0/1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null

View File

@@ -30,6 +30,17 @@ interface GigabitEthernet0/0/33
storm-control multicast min-rate 1000 max-rate 2000 storm-control multicast min-rate 1000 max-rate 2000
storm-control action error-down storm-control action error-down
# #
interface GigabitEthernet1/0/43
description FREE
shutdown
port link-type access
port default vlan 102
loopback-detect enable
stp disable
storm-control broadcast min-rate 1500 max-rate 2500
storm-control multicast min-rate 1000 max-rate 2000
storm-control action error-down
#
interface Vlanif120 interface Vlanif120
description SSH description SSH
ip address 10.26.196.254 255.255.255.0 ip address 10.26.196.254 255.255.255.0

View File

@@ -7,12 +7,21 @@
"interfaces": [ "interfaces": [
{ {
"interface": "GigabitEthernet0/0/33", "interface": "GigabitEthernet0/0/33",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{
"interface": "GigabitEthernet1/0/43",
"shutdown": true,
"ip_address": null,
"mask": null,
"description": "FREE"
},
{ {
"interface": "Vlanif120", "interface": "Vlanif120",
"shutdown": false,
"ip_address": "10.26.196.254", "ip_address": "10.26.196.254",
"mask": 24, "mask": 24,
"description": "SSH" "description": "SSH"

View File

@@ -7,138 +7,161 @@
"interfaces": [ "interfaces": [
{ {
"interface": "GigabitEthernet0", "interface": "GigabitEthernet0",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "GigabitEthernet0/1", "interface": "GigabitEthernet0/1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "GigabitEthernet0/2", "interface": "GigabitEthernet0/2",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "GigabitEthernet0/3", "interface": "GigabitEthernet0/3",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "GigabitEthernet0/0", "interface": "GigabitEthernet0/0",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster0", "interface": "WifiMaster0",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster0/AccessPoint0", "interface": "WifiMaster0/AccessPoint0",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster0/AccessPoint1", "interface": "WifiMaster0/AccessPoint1",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster0/AccessPoint2", "interface": "WifiMaster0/AccessPoint2",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster0/WifiStation0", "interface": "WifiMaster0/WifiStation0",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster1", "interface": "WifiMaster1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster1/AccessPoint0", "interface": "WifiMaster1/AccessPoint0",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster1/AccessPoint1", "interface": "WifiMaster1/AccessPoint1",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster1/AccessPoint2", "interface": "WifiMaster1/AccessPoint2",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "WifiMaster1/WifiStation0", "interface": "WifiMaster1/WifiStation0",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "Bridge0", "interface": "Bridge0",
"shutdown": false,
"ip_address": "17.36.1.1", "ip_address": "17.36.1.1",
"mask": 24, "mask": 24,
"description": "Home network" "description": "Home network"
}, },
{ {
"interface": "Bridge1", "interface": "Bridge1",
"shutdown": true,
"ip_address": "10.1.30.1", "ip_address": "10.1.30.1",
"mask": 24, "mask": 24,
"description": "Guest network" "description": "Guest network"
}, },
{ {
"interface": "Bridge2", "interface": "Bridge2",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": null "description": null
}, },
{ {
"interface": "OpenVPN0", "interface": "OpenVPN0",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "test_HW-udp" "description": "test_HW-udp"
}, },
{ {
"interface": "OpenVPN2", "interface": "OpenVPN2",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "test_HW-tcp" "description": "test_HW-tcp"
}, },
{ {
"interface": "Wireguard0", "interface": "Wireguard0",
"shutdown": false,
"ip_address": "10.3.100.1", "ip_address": "10.3.100.1",
"mask": 24, "mask": 24,
"description": "test_HW" "description": "test_HW"
}, },
{ {
"interface": "Wireguard1", "interface": "Wireguard1",
"shutdown": false,
"ip_address": "10.1.100.1", "ip_address": "10.1.100.1",
"mask": 24, "mask": 24,
"description": "test_HW" "description": "test_HW"
}, },
{ {
"interface": "Wireguard2", "interface": "Wireguard2",
"shutdown": false,
"ip_address": "10.2.100.1", "ip_address": "10.2.100.1",
"mask": 24, "mask": 24,
"description": "test_HW" "description": "test_HW"

View File

@@ -7,24 +7,28 @@
"interfaces": [ "interfaces": [
{ {
"interface": "bridge.LAN", "interface": "bridge.LAN",
"shutdown": false,
"ip_address": "172.16.3.1", "ip_address": "172.16.3.1",
"mask": 24, "mask": 24,
"description": null "description": null
}, },
{ {
"interface": "ether1", "interface": "ether1",
"shutdown": false,
"ip_address": "10.38.3.245", "ip_address": "10.38.3.245",
"mask": 24, "mask": 24,
"description": null "description": null
}, },
{ {
"interface": "wireguard2", "interface": "wireguard2",
"shutdown": false,
"ip_address": "10.1.100.2", "ip_address": "10.1.100.2",
"mask": 24, "mask": 24,
"description": null "description": null
}, },
{ {
"interface": "ether4", "interface": "ether4",
"shutdown": true,
"ip_address": "100.10.10.1", "ip_address": "100.10.10.1",
"mask": 24, "mask": 24,
"description": null "description": null

View File

@@ -7,18 +7,21 @@
"interfaces": [ "interfaces": [
{ {
"interface": "GigaEthernet1/0/9", "interface": "GigaEthernet1/0/9",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "FREE" "description": "FREE"
}, },
{ {
"interface": "VLAN1", "interface": "VLAN1",
"shutdown": false,
"ip_address": "192.168.0.1", "ip_address": "192.168.0.1",
"mask": 16, "mask": 16,
"description": null "description": null
}, },
{ {
"interface": "VLAN1002", "interface": "VLAN1002",
"shutdown": false,
"ip_address": "13.36.8.1", "ip_address": "13.36.8.1",
"mask": 24, "mask": 24,
"description": "test-1002" "description": "test-1002"

View File

@@ -7,18 +7,21 @@
"interfaces": [ "interfaces": [
{ {
"interface": "GigaEthernet1/0/9", "interface": "GigaEthernet1/0/9",
"shutdown": true,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "FREE" "description": "FREE"
}, },
{ {
"interface": "VLAN1", "interface": "VLAN1",
"shutdown": false,
"ip_address": "192.168.0.1", "ip_address": "192.168.0.1",
"mask": 16, "mask": 16,
"description": null "description": null
}, },
{ {
"interface": "VLAN1002", "interface": "VLAN1002",
"shutdown": false,
"ip_address": "13.36.8.1", "ip_address": "13.36.8.1",
"mask": 24, "mask": 24,
"description": "test-1002" "description": "test-1002"

View File

@@ -7,48 +7,56 @@
"interfaces": [ "interfaces": [
{ {
"interface": "7/4", "interface": "7/4",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "IN DWDM / OUT TEST_HW_08_N0_p1" "description": "IN DWDM / OUT TEST_HW_08_N0_p1"
}, },
{ {
"interface": "8/1", "interface": "8/1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "IN DWDM / OUT TEST_HW_09_N1_p0" "description": "IN DWDM / OUT TEST_HW_09_N1_p0"
}, },
{ {
"interface": "8/2", "interface": "8/2",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "IN DWDM / OUT TEST_HW_09_N0_p0" "description": "IN DWDM / OUT TEST_HW_09_N0_p0"
}, },
{ {
"interface": "8/3", "interface": "8/3",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "IN DWDM / OUT TEST_HW_10_N1_p0" "description": "IN DWDM / OUT TEST_HW_10_N1_p0"
}, },
{ {
"interface": "8/4", "interface": "8/4",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "IN DWDM / OUT TEST_HW_10_N0_p0" "description": "IN DWDM / OUT TEST_HW_10_N0_p0"
}, },
{ {
"interface": "9/1", "interface": "9/1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "IN DWDM / OUT TEST_HW_11_N0_p0" "description": "IN DWDM / OUT TEST_HW_11_N0_p0"
}, },
{ {
"interface": "9/2", "interface": "9/2",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "IN DWDM / OUT TEST_HW_11_N0_p1" "description": "IN DWDM / OUT TEST_HW_11_N0_p1"
}, },
{ {
"interface": "ethernet", "interface": "ethernet",
"shutdown": false,
"ip_address": "25.25.1.221", "ip_address": "25.25.1.221",
"mask": 24, "mask": 24,
"description": null "description": null

View File

@@ -7,84 +7,98 @@
"interfaces": [ "interfaces": [
{ {
"interface": "1/1", "interface": "1/1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_1_1" "description": "TEST_HW_1_1"
}, },
{ {
"interface": "1/3", "interface": "1/3",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_1_3" "description": "TEST_HW_1_3"
}, },
{ {
"interface": "2/1", "interface": "2/1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_2_1" "description": "TEST_HW_2_1"
}, },
{ {
"interface": "2/2", "interface": "2/2",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_2_2" "description": "TEST_HW_2_2"
}, },
{ {
"interface": "2/3", "interface": "2/3",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_2_3" "description": "TEST_HW_2_3"
}, },
{ {
"interface": "2/4", "interface": "2/4",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_2_4" "description": "TEST_HW_2_4"
}, },
{ {
"interface": "3/1", "interface": "3/1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_3_1" "description": "TEST_HW_3_1"
}, },
{ {
"interface": "3/3", "interface": "3/3",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_3_3" "description": "TEST_HW_3_3"
}, },
{ {
"interface": "3/4", "interface": "3/4",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_3_4" "description": "TEST_HW_3_4"
}, },
{ {
"interface": "4/1", "interface": "4/1",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_4_1" "description": "TEST_HW_4_1"
}, },
{ {
"interface": "4/2", "interface": "4/2",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_4_2" "description": "TEST_HW_4_2"
}, },
{ {
"interface": "4/3", "interface": "4/3",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_4_3" "description": "TEST_HW_4_3"
}, },
{ {
"interface": "4/4", "interface": "4/4",
"shutdown": false,
"ip_address": null, "ip_address": null,
"mask": null, "mask": null,
"description": "TEST_HW_4_4" "description": "TEST_HW_4_4"
}, },
{ {
"interface": "ethernet", "interface": "ethernet",
"shutdown": false,
"ip_address": "25.25.18.19", "ip_address": "25.25.18.19",
"mask": 24, "mask": 24,
"description": null "description": null

View File

@@ -1,4 +1,5 @@
import json import json
from ipaddress import IPv4Address
import pytest import pytest
@@ -66,6 +67,10 @@ class TestListModelView:
def test_dump_uses_aliases(self, interfaces_view): def test_dump_uses_aliases(self, interfaces_view):
dumped = interfaces_view.dump() dumped = interfaces_view.dump()
assert dumped[0]["interface"] == "eth0" assert dumped[0]["interface"] == "eth0"
assert dumped[0]["ip_address"] == IPv4Address("192.168.1.1")
def test_dump_json(self, interfaces_view):
assert interfaces_view.dump_json()
def test_dump_json_keeps_unicode(self): def test_dump_json_keeps_unicode(self):
view = ModelView([Interfaces(interface="eth0", description="Дом")]) view = ModelView([Interfaces(interface="eth0", description="Дом")])