diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index b3189ca..4ebe6af 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -38,3 +38,13 @@ jobs: 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 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f5da988..c81c9da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,3 +36,12 @@ jobs: 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 diff --git a/.gitignore b/.gitignore index 517cdfa..97443eb 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ dist/ wheels/ *.egg-info main.py +.coverage # Virtual environments .venv .python-version diff --git a/oxi/interfaces/contract.py b/oxi/interfaces/contract.py index 44a289f..5a9923d 100644 --- a/oxi/interfaces/contract.py +++ b/oxi/interfaces/contract.py @@ -26,6 +26,7 @@ class Interfaces(Base): ip_address: IPv4Address | None = None mask: int | None = None description: str | None = None + shutdown: bool = False class Vlans(Base): diff --git a/oxi/interfaces/models/templates/eltex.ttp b/oxi/interfaces/models/templates/eltex.ttp index 57240b6..8dc529f 100644 --- a/oxi/interfaces/models/templates/eltex.ttp +++ b/oxi/interfaces/models/templates/eltex.ttp @@ -25,6 +25,7 @@ Active-image: {{ ignore }} {{ _start_ }} interface {{ interface | ORPHRASE }} + shutdown {{ shutdown | set(True) }} ip address {{ ip_address }} {{ mask | to_cidr }} name {{ description | ORPHRASE}} description {{ description | ORPHRASE }} diff --git a/oxi/interfaces/models/templates/h3c.ttp b/oxi/interfaces/models/templates/h3c.ttp index dcf1e2c..410ad69 100644 --- a/oxi/interfaces/models/templates/h3c.ttp +++ b/oxi/interfaces/models/templates/h3c.ttp @@ -23,6 +23,7 @@ default_system = { interface {{ interface }} description {{ description | ORPHRASE }} ip address {{ ip_address }} {{ mask | to_cidr }} + shutdown {{ shutdown | set(True) }} diff --git a/oxi/interfaces/models/templates/huawei.ttp b/oxi/interfaces/models/templates/huawei.ttp index 4464e2c..4940748 100644 --- a/oxi/interfaces/models/templates/huawei.ttp +++ b/oxi/interfaces/models/templates/huawei.ttp @@ -21,6 +21,7 @@ default_system = { interface {{ interface }} description {{ description | ORPHRASE }} + shutdown {{ shutdown | set(True) }} ip address {{ ip_address }} {{ mask | to_cidr }} diff --git a/oxi/interfaces/models/templates/mikrotik.ttp b/oxi/interfaces/models/templates/mikrotik.ttp index 47b5028..b170f44 100644 --- a/oxi/interfaces/models/templates/mikrotik.ttp +++ b/oxi/interfaces/models/templates/mikrotik.ttp @@ -28,9 +28,9 @@ add address={{ ip_address | _start_ }}/{{ mask }} interface={{ name }} network={ ## not disabled and comment with/without quotes add address={{ ip_address | _start_ }}/{{ mask }} comment={{ description | ORPHRASE | exclude("disabled=") | strip('"')}} interface={{ name }} network={{ network }} ## 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 -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 }} diff --git a/oxi/interfaces/models/templates/qtech.ttp b/oxi/interfaces/models/templates/qtech.ttp index 1db628d..98385fe 100644 --- a/oxi/interfaces/models/templates/qtech.ttp +++ b/oxi/interfaces/models/templates/qtech.ttp @@ -29,6 +29,7 @@ default_system = { interface {{ interface | ORPHRASE }} + shutdown {{ shutdown | set(True) }} description {{ description | ORPHRASE }} ip address {{ ip_address }} {{ mask | to_cidr }} diff --git a/pyproject.toml b/pyproject.toml index e1a6eb2..9b9700f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "oxipy" -version = "0.1.0" +version = "0.1.3" description = "Python client for Oxidized API with TTP-based config parsing" readme = "README.md" license = "Apache-2.0" diff --git a/tests/fixtures/eltex/config.expected.json b/tests/fixtures/eltex/config.expected.json index c6b9ead..31631b4 100644 --- a/tests/fixtures/eltex/config.expected.json +++ b/tests/fixtures/eltex/config.expected.json @@ -7,30 +7,35 @@ "interfaces": [ { "interface": "TenGigabitEthernet1/0/2", + "shutdown": true, "ip_address": null, "mask": null, "description": "FREE" }, { "interface": "TenGigabitEthernet1/0/11", + "shutdown": true, "ip_address": null, "mask": null, "description": "FREE" }, { "interface": "vlan 1700", + "shutdown": false, "ip_address": "13.36.8.1", "mask": 24, "description": "sw-test_HW" }, { "interface": "vlan 666", + "shutdown": false, "ip_address": null, "mask": null, "description": "test" }, { "interface": "vlan 777", + "shutdown": false, "ip_address": null, "mask": null, "description": "test2" diff --git a/tests/fixtures/h3c/config.conf b/tests/fixtures/h3c/config.conf index 81eca56..58a5408 100644 --- a/tests/fixtures/h3c/config.conf +++ b/tests/fixtures/h3c/config.conf @@ -152,6 +152,7 @@ interface HundredGigE1/0/3 port link-type trunk undo port trunk permit vlan 1 port trunk permit vlan 221 1112 to 1116 1512 + shutdown storm-constrain broadcast pps 1100 1000 storm-constrain multicast pps 1100 1000 storm-constrain control shutdown diff --git a/tests/fixtures/h3c/config.expected.json b/tests/fixtures/h3c/config.expected.json index f255686..22a2fde 100644 --- a/tests/fixtures/h3c/config.expected.json +++ b/tests/fixtures/h3c/config.expected.json @@ -7,72 +7,84 @@ "interfaces": [ { "interface": "Bridge-Aggregation1", + "shutdown": false, "ip_address": null, "mask": null, "description": "HW_TEST_1" }, { "interface": "Bridge-Aggregation2", + "shutdown": false, "ip_address": null, "mask": null, "description": "HW_TEST_2" }, { "interface": "Bridge-Aggregation3", + "shutdown": false, "ip_address": null, "mask": null, "description": "HW_TEST_3" }, { "interface": "Bridge-Aggregation4", + "shutdown": false, "ip_address": null, "mask": null, "description": "HW_TEST_4" }, { "interface": "NULL0", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "Vlan-interface1", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "Vlan-interface12", + "shutdown": false, "ip_address": "15.12.16.246", "mask": 30, "description": "BGP to OSPF1" }, { "interface": "Vlan-interface3000", + "shutdown": false, "ip_address": "192.168.19.254", "mask": 25, "description": "L3 to HW_TEST_3" }, { "interface": "HundredGigE1/0/3", + "shutdown": true, "ip_address": null, "mask": null, "description": "HW_TEST_1" }, { "interface": "HundredGigE1/0/63", + "shutdown": false, "ip_address": null, "mask": null, "description": "HW_TEST_2" }, { "interface": "M-GigabitEthernet0/0/0", + "shutdown": false, "ip_address": "192.168.10.101", "mask": 24, "description": null }, { "interface": "M-GigabitEthernet0/0/1", + "shutdown": false, "ip_address": null, "mask": null, "description": null diff --git a/tests/fixtures/huawei/config.conf b/tests/fixtures/huawei/config.conf index 990fb8f..f634786 100644 --- a/tests/fixtures/huawei/config.conf +++ b/tests/fixtures/huawei/config.conf @@ -30,6 +30,17 @@ interface GigabitEthernet0/0/33 storm-control multicast min-rate 1000 max-rate 2000 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 description SSH ip address 10.26.196.254 255.255.255.0 diff --git a/tests/fixtures/huawei/config.expected.json b/tests/fixtures/huawei/config.expected.json index 39280d0..0de69c3 100644 --- a/tests/fixtures/huawei/config.expected.json +++ b/tests/fixtures/huawei/config.expected.json @@ -7,12 +7,21 @@ "interfaces": [ { "interface": "GigabitEthernet0/0/33", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, + { + "interface": "GigabitEthernet1/0/43", + "shutdown": true, + "ip_address": null, + "mask": null, + "description": "FREE" + }, { "interface": "Vlanif120", + "shutdown": false, "ip_address": "10.26.196.254", "mask": 24, "description": "SSH" diff --git a/tests/fixtures/keenetic/config.expected.json b/tests/fixtures/keenetic/config.expected.json index fee724e..98477bd 100644 --- a/tests/fixtures/keenetic/config.expected.json +++ b/tests/fixtures/keenetic/config.expected.json @@ -7,138 +7,161 @@ "interfaces": [ { "interface": "GigabitEthernet0", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "GigabitEthernet0/1", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "GigabitEthernet0/2", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "GigabitEthernet0/3", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "GigabitEthernet0/0", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster0", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster0/AccessPoint0", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster0/AccessPoint1", + "shutdown": true, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster0/AccessPoint2", + "shutdown": true, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster0/WifiStation0", + "shutdown": true, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster1", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster1/AccessPoint0", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster1/AccessPoint1", + "shutdown": true, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster1/AccessPoint2", + "shutdown": true, "ip_address": null, "mask": null, "description": null }, { "interface": "WifiMaster1/WifiStation0", + "shutdown": true, "ip_address": null, "mask": null, "description": null }, { "interface": "Bridge0", + "shutdown": false, "ip_address": "17.36.1.1", "mask": 24, "description": "Home network" }, { "interface": "Bridge1", + "shutdown": true, "ip_address": "10.1.30.1", "mask": 24, "description": "Guest network" }, { "interface": "Bridge2", + "shutdown": false, "ip_address": null, "mask": null, "description": null }, { "interface": "OpenVPN0", + "shutdown": false, "ip_address": null, "mask": null, "description": "test_HW-udp" }, { "interface": "OpenVPN2", + "shutdown": true, "ip_address": null, "mask": null, "description": "test_HW-tcp" }, { "interface": "Wireguard0", + "shutdown": false, "ip_address": "10.3.100.1", "mask": 24, "description": "test_HW" }, { "interface": "Wireguard1", + "shutdown": false, "ip_address": "10.1.100.1", "mask": 24, "description": "test_HW" }, { "interface": "Wireguard2", + "shutdown": false, "ip_address": "10.2.100.1", "mask": 24, "description": "test_HW" diff --git a/tests/fixtures/mikrotik/config.expected.json b/tests/fixtures/mikrotik/config.expected.json index 04427e6..0cf1a84 100644 --- a/tests/fixtures/mikrotik/config.expected.json +++ b/tests/fixtures/mikrotik/config.expected.json @@ -7,24 +7,28 @@ "interfaces": [ { "interface": "bridge.LAN", + "shutdown": false, "ip_address": "172.16.3.1", "mask": 24, "description": null }, { "interface": "ether1", + "shutdown": false, "ip_address": "10.38.3.245", "mask": 24, "description": null }, { "interface": "wireguard2", + "shutdown": false, "ip_address": "10.1.100.2", "mask": 24, "description": null }, { "interface": "ether4", + "shutdown": true, "ip_address": "100.10.10.1", "mask": 24, "description": null diff --git a/tests/fixtures/qtech/config_1.expected.json b/tests/fixtures/qtech/config_1.expected.json index e9721f4..b45406a 100644 --- a/tests/fixtures/qtech/config_1.expected.json +++ b/tests/fixtures/qtech/config_1.expected.json @@ -7,18 +7,21 @@ "interfaces": [ { "interface": "GigaEthernet1/0/9", + "shutdown": true, "ip_address": null, "mask": null, "description": "FREE" }, { "interface": "VLAN1", + "shutdown": false, "ip_address": "192.168.0.1", "mask": 16, "description": null }, { "interface": "VLAN1002", + "shutdown": false, "ip_address": "13.36.8.1", "mask": 24, "description": "test-1002" diff --git a/tests/fixtures/qtech/config_2.expected.json b/tests/fixtures/qtech/config_2.expected.json index e9a4a80..63faa43 100644 --- a/tests/fixtures/qtech/config_2.expected.json +++ b/tests/fixtures/qtech/config_2.expected.json @@ -7,18 +7,21 @@ "interfaces": [ { "interface": "GigaEthernet1/0/9", + "shutdown": true, "ip_address": null, "mask": null, "description": "FREE" }, { "interface": "VLAN1", + "shutdown": false, "ip_address": "192.168.0.1", "mask": 16, "description": null }, { "interface": "VLAN1002", + "shutdown": false, "ip_address": "13.36.8.1", "mask": 24, "description": "test-1002" diff --git a/tests/fixtures/quasar/config_1.expected.json b/tests/fixtures/quasar/config_1.expected.json index 592ffbd..012027e 100644 --- a/tests/fixtures/quasar/config_1.expected.json +++ b/tests/fixtures/quasar/config_1.expected.json @@ -7,48 +7,56 @@ "interfaces": [ { "interface": "7/4", + "shutdown": false, "ip_address": null, "mask": null, "description": "IN DWDM / OUT TEST_HW_08_N0_p1" }, { "interface": "8/1", + "shutdown": false, "ip_address": null, "mask": null, "description": "IN DWDM / OUT TEST_HW_09_N1_p0" }, { "interface": "8/2", + "shutdown": false, "ip_address": null, "mask": null, "description": "IN DWDM / OUT TEST_HW_09_N0_p0" }, { "interface": "8/3", + "shutdown": false, "ip_address": null, "mask": null, "description": "IN DWDM / OUT TEST_HW_10_N1_p0" }, { "interface": "8/4", + "shutdown": false, "ip_address": null, "mask": null, "description": "IN DWDM / OUT TEST_HW_10_N0_p0" }, { "interface": "9/1", + "shutdown": false, "ip_address": null, "mask": null, "description": "IN DWDM / OUT TEST_HW_11_N0_p0" }, { "interface": "9/2", + "shutdown": false, "ip_address": null, "mask": null, "description": "IN DWDM / OUT TEST_HW_11_N0_p1" }, { "interface": "ethernet", + "shutdown": false, "ip_address": "25.25.1.221", "mask": 24, "description": null diff --git a/tests/fixtures/quasar/config_2.expected.json b/tests/fixtures/quasar/config_2.expected.json index 1ddaf5a..2947acd 100644 --- a/tests/fixtures/quasar/config_2.expected.json +++ b/tests/fixtures/quasar/config_2.expected.json @@ -7,84 +7,98 @@ "interfaces": [ { "interface": "1/1", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_1_1" }, { "interface": "1/3", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_1_3" }, { "interface": "2/1", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_2_1" }, { "interface": "2/2", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_2_2" }, { "interface": "2/3", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_2_3" }, { "interface": "2/4", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_2_4" }, { "interface": "3/1", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_3_1" }, { "interface": "3/3", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_3_3" }, { "interface": "3/4", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_3_4" }, { "interface": "4/1", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_4_1" }, { "interface": "4/2", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_4_2" }, { "interface": "4/3", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_4_3" }, { "interface": "4/4", + "shutdown": false, "ip_address": null, "mask": null, "description": "TEST_HW_4_4" }, { "interface": "ethernet", + "shutdown": false, "ip_address": "25.25.18.19", "mask": 24, "description": null