kb-audit: fix парсер — ловит table-rows и раздел 🗑️ удалённых
This commit is contained in:
@@ -53,20 +53,38 @@ def parse_live():
|
||||
|
||||
|
||||
def parse_inventory(path: Path):
|
||||
"""Парсит inventory-файл. Извлекает упомянутые VMID + связанный контекст."""
|
||||
"""Парсит inventory-файл. Извлекает упомянутые VMID + связанный контекст.
|
||||
Ловит два формата:
|
||||
1. "LXC 132" / "VM 250" — в заголовках и тексте
|
||||
2. Table rows: | 132 | debian | ... | — в таблицах
|
||||
"""
|
||||
text = path.read_text()
|
||||
found = {}
|
||||
# Ищем все упоминания "LXC NNN" или "VM NNN" в заголовках и таблицах
|
||||
for m in re.finditer(r"(?:LXC|VM)\s+(\d{2,4})\b", text):
|
||||
vmid = m.group(1)
|
||||
|
||||
def add(vmid: str, idx: int):
|
||||
if vmid not in found:
|
||||
# контекст: 80 символов вокруг
|
||||
start = max(0, m.start() - 20)
|
||||
end = min(len(text), m.end() + 60)
|
||||
start = max(0, idx - 20)
|
||||
end = min(len(text), idx + 80)
|
||||
found[vmid] = text[start:end].replace("\n", " ").strip()
|
||||
|
||||
for m in re.finditer(r"(?:LXC|VM)\s+(\d{2,4})\b", text):
|
||||
add(m.group(1), m.start())
|
||||
# table rows: строка начинается с `| NNN |` (игнорируем header-row с тире)
|
||||
for m in re.finditer(r"^\s*\|\s*(\d{2,4})\s*\|", text, re.MULTILINE):
|
||||
add(m.group(1), m.start())
|
||||
return found
|
||||
|
||||
|
||||
def find_deleted_section(path: Path) -> set:
|
||||
"""Ищет VMID в секции '## 🗑️ Удалённые' чтобы не флагать их как missing."""
|
||||
text = path.read_text()
|
||||
# блок между '🗑️ Удалённые' и следующим '##'
|
||||
m = re.search(r"##\s*🗑[^\n]*Удал[^\n]*\n(.*?)(?=\n##|\Z)", text, re.DOTALL)
|
||||
if not m:
|
||||
return set()
|
||||
return set(re.findall(r"\|\s*(\d{2,4})\s*\|", m.group(1)))
|
||||
|
||||
|
||||
def compare(live: dict, inventory: dict):
|
||||
live_ids = set(live.keys())
|
||||
inv_ids = set(inventory.keys())
|
||||
@@ -84,7 +102,13 @@ def main():
|
||||
|
||||
live = parse_live()
|
||||
inventory = parse_inventory(INVENTORY)
|
||||
only_live, only_inv, common = compare(live, inventory)
|
||||
deleted = find_deleted_section(INVENTORY)
|
||||
only_live, only_inv_raw, common = compare(live, inventory)
|
||||
# разделяем "в inventory но не в live" на 2 группы:
|
||||
# - known-deleted (есть в секции "🗑️ Удалённые") — это ок
|
||||
# - truly missing (нет и в live, и не в секции deleted) — проблема
|
||||
only_inv = [v for v in only_inv_raw if v not in deleted]
|
||||
known_deleted = [v for v in only_inv_raw if v in deleted]
|
||||
|
||||
lines = [
|
||||
"---",
|
||||
@@ -100,7 +124,8 @@ def main():
|
||||
"",
|
||||
f"- Живых гостей Proxmox: **{len(live)}**",
|
||||
f"- Упомянуто в inventory: **{len(inventory)}**",
|
||||
f"- В обоих: {len(common)} / только в live: {len(only_live)} / только в inventory: {len(only_inv)}",
|
||||
f"- В обоих: {len(common)} / только в live: {len(only_live)} / отсутствуют в live: {len(only_inv)}",
|
||||
f"- Известны как удалённые: {len(known_deleted)} (в `## 🗑️ Удалённые`)",
|
||||
"",
|
||||
]
|
||||
|
||||
@@ -113,13 +138,16 @@ def main():
|
||||
lines += [""]
|
||||
|
||||
if only_inv:
|
||||
lines += ["## 🗑 В inventory есть, в Proxmox НЕТ (удалён? переименован?)", ""]
|
||||
lines += ["## ❓ В inventory есть, в Proxmox НЕТ (не в секции 🗑️ — проверить вручную)", ""]
|
||||
lines += ["| VMID | Контекст из inventory |", "|---|---|"]
|
||||
for vmid in only_inv:
|
||||
ctx = inventory[vmid][:100]
|
||||
lines += [f"| {vmid} | `...{ctx}...` |"]
|
||||
lines += [""]
|
||||
|
||||
if known_deleted:
|
||||
lines += [f"## ✓ Удалённые хосты (задокументированы): {', '.join(sorted(known_deleted, key=int))}", ""]
|
||||
|
||||
if not only_live and not only_inv:
|
||||
lines += ["## ✓ Inventory полностью совпадает с живой инфраструктурой", ""]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user