Mark installed catalog modules as updates
This commit is contained in:
@@ -438,7 +438,7 @@ def _upsert_install_plan_item(session: Session, item: ModuleInstallPlanItem):
|
||||
return save_module_install_plan(session, [*retained, item])
|
||||
|
||||
|
||||
def _catalog_plan_item(module_id: str) -> tuple[ModuleInstallPlanItem, dict[str, object]]:
|
||||
def _catalog_plan_item(module_id: str, available_module_ids: set[str]) -> tuple[ModuleInstallPlanItem, dict[str, object]]:
|
||||
result = validate_module_package_catalog()
|
||||
if not result.get("valid"):
|
||||
raise HTTPException(
|
||||
@@ -448,15 +448,17 @@ def _catalog_plan_item(module_id: str) -> tuple[ModuleInstallPlanItem, dict[str,
|
||||
for raw_item in result.get("modules", []):
|
||||
if not isinstance(raw_item, dict):
|
||||
continue
|
||||
if raw_item.get("module_id") != module_id or raw_item.get("action") != "install":
|
||||
if raw_item.get("module_id") != module_id or raw_item.get("action") not in {"install", "update"}:
|
||||
continue
|
||||
raw_action = raw_item.get("action")
|
||||
action = "update" if raw_action == "update" or module_id in available_module_ids else "install"
|
||||
license_decision = module_license_decision(_catalog_license_features(raw_item))
|
||||
if not license_decision.get("allowed"):
|
||||
missing = license_decision.get("missing_features")
|
||||
missing_text = ", ".join(str(item) for item in missing) if isinstance(missing, list) else "required feature"
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail=f"License does not allow installing {module_id}: {missing_text}.",
|
||||
detail=f"License does not allow {action} for {module_id}: {missing_text}.",
|
||||
)
|
||||
notes = raw_item.get("notes") if isinstance(raw_item.get("notes"), str) else None
|
||||
if license_decision.get("reason") and license_decision.get("missing_features"):
|
||||
@@ -464,7 +466,7 @@ def _catalog_plan_item(module_id: str) -> tuple[ModuleInstallPlanItem, dict[str,
|
||||
notes = f"{prefix}License warning: {license_decision['reason']}"
|
||||
return ModuleInstallPlanItem(
|
||||
module_id=str(raw_item["module_id"]),
|
||||
action="install",
|
||||
action=action,
|
||||
source="catalog",
|
||||
catalog=_catalog_plan_metadata(result),
|
||||
python_package=raw_item.get("python_package") if isinstance(raw_item.get("python_package"), str) else None,
|
||||
@@ -473,7 +475,7 @@ def _catalog_plan_item(module_id: str) -> tuple[ModuleInstallPlanItem, dict[str,
|
||||
webui_ref=raw_item.get("webui_ref") if isinstance(raw_item.get("webui_ref"), str) else None,
|
||||
notes=notes,
|
||||
), result
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Catalog install entry not found: {module_id}")
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Catalog install/update entry not found: {module_id}")
|
||||
|
||||
|
||||
def _catalog_plan_metadata(validation: dict[str, object]) -> dict[str, object]:
|
||||
@@ -796,7 +798,9 @@ def plan_module_install_from_catalog(
|
||||
principal: ApiPrincipal = Depends(require_scope("system:settings:write")),
|
||||
):
|
||||
try:
|
||||
item, validation = _catalog_plan_item(module_id)
|
||||
lifecycle = getattr(request.app.state, "govoplan_lifecycle", None)
|
||||
available = dict(lifecycle.available_modules) if isinstance(lifecycle, ModuleLifecycleManager) else available_module_manifests(ignore_load_errors=True)
|
||||
item, validation = _catalog_plan_item(module_id, set(available))
|
||||
plan = _upsert_install_plan_item(session, item)
|
||||
record_module_package_catalog_acceptance(validation)
|
||||
except ModuleManagementError as exc:
|
||||
@@ -820,7 +824,8 @@ def plan_module_install_from_catalog(
|
||||
),
|
||||
)
|
||||
session.commit()
|
||||
return _module_install_plan_response(session, request, notes=[f"Catalog install entry planned for {module_id}."])
|
||||
planned_action = "update" if item.action == "update" else "install"
|
||||
return _module_install_plan_response(session, request, notes=[f"Catalog {planned_action} entry planned for {module_id}."])
|
||||
|
||||
|
||||
@router.post("/system/modules/{module_id}/uninstall-plan", response_model=ModuleInstallPlanResponse)
|
||||
|
||||
Reference in New Issue
Block a user