Expose nmap_os in INI loader and update test-full.ini

- ini_loader.py: DeckySpec gains nmap_os field; load_ini parses nmap_os=
  (also accepts nmap-os= hyphen alias) and propagates it to amount-expanded deckies
- cli.py: _build_deckies_from_ini resolves nmap_os with priority:
  explicit INI key > archetype default > "linux"
- test-full.ini: every decky now carries nmap_os=; [windows-workstation]
  gains archetype= so its OS family is set correctly; decky-winbox/fileserv/
  ldapdc → windows, decky-iot → embedded, decky-legacy → bsd, rest → linux
- tests/test_ini_loader.py: 7 new tests covering nmap_os parsing, defaults,
  hyphen alias, and amount= expansion propagation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-04 13:23:45 -03:00
parent 6610856749
commit 086643ef5a
4 changed files with 258 additions and 2 deletions

View File

@@ -53,6 +53,7 @@ class DeckySpec:
services: list[str] | None = None
archetype: str | None = None
service_config: dict[str, dict] = field(default_factory=dict)
nmap_os: str | None = None # explicit OS family override (linux/windows/bsd/embedded/cisco)
@dataclass
@@ -113,6 +114,7 @@ def load_ini(path: str | Path) -> IniConfig:
svc_raw = s.get("services")
services = [sv.strip() for sv in svc_raw.split(",")] if svc_raw else None
archetype = s.get("archetype")
nmap_os = s.get("nmap_os") or s.get("nmap-os") or None
amount_raw = s.get("amount", "1")
try:
amount = int(amount_raw)
@@ -123,7 +125,7 @@ def load_ini(path: str | Path) -> IniConfig:
if amount == 1:
cfg.deckies.append(DeckySpec(
name=section, ip=ip, services=services, archetype=archetype,
name=section, ip=ip, services=services, archetype=archetype, nmap_os=nmap_os,
))
else:
# Expand into N deckies; explicit ip is ignored (can't share one IP)
@@ -138,6 +140,7 @@ def load_ini(path: str | Path) -> IniConfig:
ip=None,
services=services,
archetype=archetype,
nmap_os=nmap_os,
))
# Second pass: collect per-service subsections [decky-name.service]