Merge branch 'main' into feat/apt-proxy-verify
driver / standard (pull_request) Successful in 13s
driver / lint (pull_request) Successful in 1m24s
driver / types (pull_request) Successful in 44s
driver / test (3.10) (pull_request) Successful in 50s
driver / test (3.11) (pull_request) Successful in 48s
driver / test (3.12) (pull_request) Successful in 48s
driver / test (3.13) (pull_request) Successful in 41s
driver / lowest (pull_request) Successful in 24s
driver / security (pull_request) Successful in 46s
driver / build (pull_request) Successful in 23s
CI / driver (pull_request) Successful in 7m2s
driver / publish (pull_request) Skipped

The NAPALM driver standard landed on main (#52, 4.21.1). apt_proxy follows
it: builtin generics, strict mypy, complexity 10 at most (parse_apt_proxy,
same_proxy_url and the comment-out step split into helpers), 100 % covered.
Its TypedDicts live in apt_proxy.py, since models.py is over 1000 lines and
may not grow. Version 4.22.0 with its CHANGELOG section.
This commit is contained in:
christianmanivong committed 2026-10-23 00:14:59 +02:00
commit a07ced2df6
83 files changed
+1698 -1284

No files matched your search

+40 -26
View File
@@ -6,14 +6,14 @@ Instead of inheriting directly from `napalm.base.NetworkDriver`, a driver can in
```python
# without napalm-device-types
class OpenWrtDriver(NetworkDriver):
...
class OpenWrtDriver(NetworkDriver): ...
# with napalm-device-types
from napalm_device_types import AccessPointDriver
class OpenWrtDriver(AccessPointDriver):
...
class OpenWrtDriver(AccessPointDriver): ...
```
## Why?
@@ -29,8 +29,9 @@ OpenMediaVault box is a NAS built on Debian. So a driver inherits **one role bas
role its device fills**, and **the order it lists them in is the ranking**:
```python
class QnapQtsDriver(StorageDriver, HypervisorDriver, LinuxDriver):
... # primary_role_of(...) == "storage"
class QnapQtsDriver(
StorageDriver, HypervisorDriver, LinuxDriver
): ... # primary_role_of(...) == "storage"
```
`roles_of(cls)`, `role_keys_of(cls)` and `primary_role_of(cls)` read that back. Nothing
@@ -54,10 +55,12 @@ host OS's load; it has no `HealthMetricsMixin` (SNMP) and no command channel.
```python
class StorageDriver(DeviceTypeDriver):
"""Contract, not code."""
ROLE: str = "storage"
TYPE_LABEL: str = "Storage"
if TYPE_CHECKING: # nothing exists at runtime
if TYPE_CHECKING: # nothing exists at runtime
def get_disks(self) -> List[PhysicalDiskDict]: ...
```
@@ -321,20 +324,27 @@ generic data shapes belong here. Only the actual device communication belongs in
**Worked example — firewall rule diff/apply** (`FirewallRuleMixin`, in `FirewallDriver`):
```python
class FirewallRuleMixin: # mixed into FirewallDriver
class FirewallRuleMixin: # mixed into FirewallDriver
# Declared only — every driver implements its own device communication.
if TYPE_CHECKING:
def get_firewall_rules(self) -> List[FirewallRuleDict]: ...
def apply_firewall_rule(self, rule: FirewallRuleDict, *, uuid: Optional[str] = None) -> Dict[str, Any]: ...
def apply_firewall_rule(
self, rule: FirewallRuleDict, *, uuid: Optional[str] = None
) -> Dict[str, Any]: ...
def commit_firewall_rules(self) -> Dict[str, Any]: ...
# Concrete — the matching/comparison/orchestration algorithm is identical
# for every firewall vendor, so it lives here once.
def diff_firewall_rules(self, desired: List[FirewallRuleDict]) -> FirewallRuleDiffDict:
... # matches self.get_firewall_rules() against `desired` by description
def diff_firewall_rules(
self, desired: List[FirewallRuleDict]
) -> (
FirewallRuleDiffDict
): ... # matches self.get_firewall_rules() against `desired` by description
def apply_firewall_ruleset(self, desired: List[FirewallRuleDict]):
... # computes the diff, calls apply_firewall_rule() per change, commits
def apply_firewall_ruleset(
self, desired: List[FirewallRuleDict]
): ... # computes the diff, calls apply_firewall_rule() per change, commits
```
The same split applies to `DhcpServerMixin`: `get_dhcp_reservations`/
@@ -430,8 +440,8 @@ HTTP_FINGERPRINT = [
```python
from napalm_device_types import AccessPointDriver
class OpenWrtDriver(AccessPointDriver):
class OpenWrtDriver(AccessPointDriver):
def get_wireless_clients(self):
# return List[WirelessClientDict]
...
@@ -446,8 +456,8 @@ class OpenWrtDriver(AccessPointDriver):
```python
from napalm_device_types import SwitchDriver
class CiscoIOSDriver(SwitchDriver):
class CiscoIOSDriver(SwitchDriver):
def get_spanning_tree(self):
# return Dict[str, SpanningTreeDict]
...
@@ -462,8 +472,8 @@ class CiscoIOSDriver(SwitchDriver):
```python
from napalm_device_types import FirewallDriver
class PfSenseDriver(FirewallDriver):
class PfSenseDriver(FirewallDriver):
def get_nat_translations(self):
# return List[NATTranslationDict]
...
@@ -483,14 +493,13 @@ class PfSenseDriver(FirewallDriver):
```python
from napalm_device_types import HypervisorDriver
class ProxmoxDriver(HypervisorDriver):
class ProxmoxDriver(HypervisorDriver):
def get_vms(self):
# return List[VMDict]
...
def create_vm_snapshot(self, name, snapshot, description="", include_memory=False):
...
def create_vm_snapshot(self, name, snapshot, description="", include_memory=False): ...
def get_vm_cpu_types(self):
# optional — return List[VMCpuTypeDict]: the CPU models a new VM may get
@@ -514,8 +523,8 @@ unpacked; both are the same for every hypervisor.
```python
from napalm_device_types import OSDriver
class LinuxDriver(OSDriver):
class LinuxDriver(OSDriver):
def get_packages(self):
# return List[PackageDict]
...
@@ -542,8 +551,8 @@ class LinuxDriver(OSDriver):
```python
from napalm_device_types import StorageDriver
class TrueNASDriver(StorageDriver):
class TrueNASDriver(StorageDriver):
def get_disks(self):
# return List[PhysicalDiskDict]
...
@@ -569,7 +578,7 @@ from napalm_device_types.models import (
## Development
```bash
git clone https://github.com/chrismanivong/napalm-device-types.git
git clone https://git.netork.io/NAPALM/napalm-device-types.git
cd napalm-device-types
pip install -e ".[dev]"
```
@@ -582,10 +591,15 @@ mypy napalm_device_types
## Contributing
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/router-driver`)
3. Implement your changes
4. Open a Pull Request
This package follows the
[NAPALM driver standard](https://git.netork.io/NAPALM/driver-standard/src/branch/main/STANDARDS.md):
test first, ruff and strict mypy, Conventional Commits, one pull request per change
against `main`. CI checks what a tool can check:
```bash
pip install "napalm-standard @ git+https://git.netork.io/NAPALM/driver-standard.git"
napalm-standard check && napalm-standard ratchet
```
## License