Add error detection

This commit is contained in:
pierre.geeraert
2026-06-25 08:48:26 +01:00
parent a383fca9fc
commit 05fc220c4b
+85 -34
View File
@@ -1,51 +1,87 @@
import re import re
import sys import sys
from collections import defaultdict
def parse_file(file_path): def parse_file(file_path):
results = [] recap_results = []
failed_tasks = defaultdict(list)
with open(file_path, "r", encoding="utf-8", errors="ignore") as f: with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
for line in f: lines = f.readlines()
# Look for lines containing recap info current_task = None
if "ok=" in line and "failed=" in line and "unreachable=" in line:
# Extract host (first non-time token before :) for i, line in enumerate(lines):
host_match = re.search(r"(?:\d{2}:\d{2}:\d{2}\s+)?(\S+)\s+:", line)
if not host_match:
continue
host = host_match.group(1) # -------------------------
# 1. Detect TASK name
# -------------------------
task_match = re.search(r"TASK \[(.*?)\]", line)
if task_match:
current_task = task_match.group(1)
# Extract values individually (order-independent) # -------------------------
def get_value(field): # 2. Detect FAILED lines
match = re.search(rf"{field}=(\d+)", line) # -------------------------
return int(match.group(1)) if match else 0 fail_match = re.search(r"fatal: \[(.*?)\]: FAILED!", line)
if fail_match:
host = fail_match.group(1)
ok = get_value("ok") # Try to grab error message from same or next lines
changed = get_value("changed") error_msg = ""
unreachable = get_value("unreachable")
failed = get_value("failed")
status = ( # Look ahead a few lines to capture reason
"UNREACHABLE" if unreachable > 0 for j in range(i, min(i + 5, len(lines))):
else "FAILED" if failed > 0 if "msg" in lines[j] or "stderr" in lines[j]:
else "OK" error_msg += lines[j].strip() + " "
)
results.append({ if not error_msg:
"host": host, error_msg = "Unknown error"
"ok": ok,
"changed": changed,
"unreachable": unreachable,
"failed": failed,
"status": status
})
return results failed_tasks[host].append({
"task": current_task,
"error": error_msg.strip()
})
# -------------------------
# 3. Parse PLAY RECAP lines
# -------------------------
if "ok=" in line and "failed=" in line and "unreachable=" in line:
host_match = re.search(r"(?:\d{2}:\d{2}:\d{2}\s+)?(\S+)\s+:", line)
if not host_match:
continue
host = host_match.group(1)
def get_value(field):
match = re.search(rf"{field}=(\d+)", line)
return int(match.group(1)) if match else 0
ok = get_value("ok")
changed = get_value("changed")
unreachable = get_value("unreachable")
failed = get_value("failed")
status = (
"UNREACHABLE" if unreachable > 0
else "FAILED" if failed > 0
else "OK"
)
recap_results.append({
"host": host,
"ok": ok,
"changed": changed,
"unreachable": unreachable,
"failed": failed,
"status": status
})
return recap_results, failed_tasks
def print_report(results): def print_report(results, failed_tasks):
unreachable_hosts = [] unreachable_hosts = []
failed_hosts = [] failed_hosts = []
@@ -68,7 +104,22 @@ def print_report(results):
print("\nFAILED HOSTS:") print("\nFAILED HOSTS:")
print("\n".join(failed_hosts) if failed_hosts else " None") print("\n".join(failed_hosts) if failed_hosts else " None")
# -------------------------
# NEW SECTION
# -------------------------
print("\n=== FAILED TASK DETAILS ===")
if not failed_tasks:
print(" No failed tasks detected")
return
for host, tasks in failed_tasks.items():
print(f"\n{host}")
for t in tasks:
print(f" Task: {t['task']}")
print(f" Error: {t['error']}")
if __name__ == "__main__": if __name__ == "__main__":
results = parse_file(sys.argv[1]) results, failed_tasks = parse_file(sys.argv[1])
print_report(results) print_report(results, failed_tasks)