feat: standards, shared CI and release tooling for NAPALM drivers
STANDARDS.md binds every repository in the NAPALM org: one default branch, Conventional Commits, the device-types contract, test-driven development, clean-code limits, a quality ratchet for existing code, packaging rules and releases by tag to PyPI. napalm-standard holds what a tool can check: the conformance check (with release rules on a tag), the quality ratchet (ported from netOrk's quality_ratchet.py), and the Gitea release from the CHANGELOG section. .gitea/workflows/driver.yml is the CI every driver calls; template/ is a new driver's starting point and passes the check as it is.
This commit is contained in:
commit
db6b2e4ea7
37 files changed
+2894
No files matched your search
@@ -0,0 +1,45 @@
|
||||
"""Pure functions: device output in, typed values out. No I/O here."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import TypedDict
|
||||
|
||||
#: "Key : value" lines of `show version`.
|
||||
_FIELD = re.compile(r"^(?P<key>[^:\n]+?)\s*:\s*(?P<value>.*)$", re.MULTILINE)
|
||||
#: "3 days, 4:05:06" or "4:05:06".
|
||||
_UPTIME = re.compile(r"^(?:(?P<days>\d+) days?, )?(?P<h>\d+):(?P<m>\d\d):(?P<s>\d\d)$")
|
||||
_SECONDS_PER_DAY = 86400
|
||||
|
||||
|
||||
class VersionDict(TypedDict):
|
||||
model: str
|
||||
hostname: str
|
||||
os_version: str
|
||||
serial_number: str
|
||||
uptime: float
|
||||
|
||||
|
||||
def parse_uptime(text: str) -> float:
|
||||
"""Seconds from an uptime like ``3 days, 4:05:06``."""
|
||||
match = _UPTIME.match(text.strip())
|
||||
if not match:
|
||||
raise ValueError(f"unreadable uptime: {text!r}")
|
||||
days = int(match.group("days") or 0)
|
||||
hours, minutes, seconds = (int(match.group(k)) for k in ("h", "m", "s"))
|
||||
return float(days * _SECONDS_PER_DAY + hours * 3600 + minutes * 60 + seconds)
|
||||
|
||||
|
||||
def parse_version(text: str) -> VersionDict:
|
||||
"""Facts from ``show version``; a field the device did not print is an error."""
|
||||
fields = {m.group("key").strip(): m.group("value").strip() for m in _FIELD.finditer(text)}
|
||||
try:
|
||||
return {
|
||||
"model": text.splitlines()[0].removesuffix(" Switch").strip(),
|
||||
"hostname": fields["Hostname"],
|
||||
"os_version": fields["Firmware"],
|
||||
"serial_number": fields["Serial number"],
|
||||
"uptime": parse_uptime(fields["Uptime"]),
|
||||
}
|
||||
except KeyError as exc:
|
||||
raise ValueError(f"show version lacks {exc.args[0]}") from exc
|
||||
Reference in new issue
Block a user