test script be
All checks were successful
Build and Deploy MITM Webserver / build (push) Successful in 9s
All checks were successful
Build and Deploy MITM Webserver / build (push) Successful in 9s
This commit is contained in:
@@ -19,7 +19,8 @@ import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import logging
|
||||
from typing import Optional, List, Dict, Any
|
||||
from typing import Optional, List, Dict, Any, Tuple, DefaultDict
|
||||
from collections import defaultdict
|
||||
|
||||
from fastapi import APIRouter, UploadFile, File, Form, HTTPException, Query
|
||||
from fastapi.responses import FileResponse, JSONResponse
|
||||
@@ -377,7 +378,7 @@ class ScriptWithStatus(ScriptInfo):
|
||||
- mappings: list of UnitMapping for that script
|
||||
- requirements_exists: whether a requirements file exists on disk
|
||||
"""
|
||||
mappings: List[UnitMapping] = []
|
||||
mappings: List[UnitMapping] = Field(default_factory=list)
|
||||
requirements_exists: bool = False
|
||||
|
||||
|
||||
@@ -405,6 +406,35 @@ class OperationResult(BaseModel):
|
||||
python: Optional[str] = None
|
||||
|
||||
|
||||
# ---------- Helper: group parsed units by script name ----------
|
||||
def _group_units_by_script(units: List[str]) -> Dict[str, List[Tuple[str, UnitParsed, bool]]]:
|
||||
"""
|
||||
Parse each unit and group by parsed.name (script name). Returns a dict:
|
||||
{ script_name: [ (svc, parsed, active), ... ], ... }
|
||||
If parsed.name is None, attempt to extract script name from service string using pattern.
|
||||
"""
|
||||
groups: DefaultDict[str, List[Tuple[str, UnitParsed, bool]]] = defaultdict(list)
|
||||
for svc in units:
|
||||
parsed = parse_unit_execstart(svc)
|
||||
try:
|
||||
active = is_unit_active(svc)
|
||||
except Exception:
|
||||
active = False
|
||||
|
||||
script_name = parsed.name
|
||||
if not script_name:
|
||||
# attempt to extract from service name like 'fw-script-<name>-q<N>'
|
||||
m = re.match(rf'^{re.escape(UNIT_PREFIX)}-(?P<name>[A-Za-z0-9_.-]+)-q\d+$', svc)
|
||||
if m:
|
||||
script_name = m.group("name")
|
||||
if not script_name:
|
||||
# fallback: group under special key so they won't be lost; use svc as key
|
||||
script_name = svc
|
||||
|
||||
groups[script_name].append((svc, parsed, active))
|
||||
return groups
|
||||
|
||||
|
||||
# ---------- Endpoints ----------
|
||||
# NOTE: combined status info into GET /scripts below (replaces separate /status & /{name}/status endpoints)
|
||||
|
||||
@@ -420,27 +450,23 @@ def list_scripts_with_status() -> List[ScriptWithStatus]:
|
||||
"""
|
||||
out: List[ScriptWithStatus] = []
|
||||
|
||||
# build a list of units once for efficiency
|
||||
# build a list of units once for efficiency and group them by parsed script name
|
||||
all_units = list_fw_units()
|
||||
logger.debug("list_scripts_with_status: discovered %d fw units", len(all_units))
|
||||
grouped = _group_units_by_script(all_units)
|
||||
|
||||
# iterate script files on disk
|
||||
for fn in os.listdir(SCRIPT_DIR):
|
||||
if not fn.endswith(".py"):
|
||||
continue
|
||||
name = fn.rsplit(".", 1)[0]
|
||||
spath = os.path.join(SCRIPT_DIR, fn)
|
||||
|
||||
# find units matching this script
|
||||
prefix = f"{UNIT_PREFIX}-{name}-q"
|
||||
mappings: List[UnitMapping] = []
|
||||
for svc in all_units:
|
||||
if svc.startswith(prefix):
|
||||
parsed = parse_unit_execstart(svc)
|
||||
try:
|
||||
active = is_unit_active(svc)
|
||||
except Exception:
|
||||
active = False
|
||||
mappings.append(UnitMapping(service=svc, parsed=parsed, active=active))
|
||||
# take groups[name] if present
|
||||
entries = grouped.get(name, [])
|
||||
for svc, parsed, active in entries:
|
||||
mappings.append(UnitMapping(service=svc, parsed=parsed, active=active))
|
||||
|
||||
req_exists = os.path.exists(requirements_path_for(name))
|
||||
out.append(ScriptWithStatus(name=name, path=spath, mappings=mappings, requirements_exists=req_exists))
|
||||
@@ -520,6 +546,9 @@ async def upload_script(
|
||||
logger.exception("Cleanup after pip failure partially failed for %s", name)
|
||||
# Return pip failure as 500 with message
|
||||
raise HTTPException(status_code=500, detail=f"pip install failed: {err_msg}")
|
||||
else:
|
||||
# If no requirements provided on upload, we simply keep uploaded script. (Per earlier conversation you can require requirements always if you want.)
|
||||
logger.debug("No requirements uploaded with script %s", name)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user