Publish curated Unraid-AppOps-Gateway source from ba66029223865607deddc234e283c11127324eb8
This commit is contained in:
1 parent
820244dbb3
commit
8dd4b40252
52 files changed
+11814
-288
No files matched your search
@@ -6,11 +6,13 @@ for command execution, Compose upload, arbitrary host paths or raw secrets.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Annotated, Literal
|
||||
|
||||
from fastapi import APIRouter, Depends, Header, HTTPException, Query, Request
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from sqlmodel import Session
|
||||
from starlette.concurrency import run_in_threadpool
|
||||
|
||||
from ..core.security import require_operator_request
|
||||
from ..db.session import get_session
|
||||
@@ -22,6 +24,7 @@ from ..schemas.forge_secret_delivery import (
|
||||
ForgeSecretDeliveryResultV1,
|
||||
)
|
||||
from ..schemas.forge_runtime_readiness import ForgeRuntimeReadinessResultV1
|
||||
from ..schemas.forge_route_stage import ForgeRouteStageResultV1
|
||||
from ..services.deployment_broker import DeploymentBrokerClient
|
||||
from ..services.deployment_control_plane import (
|
||||
DeploymentControlError,
|
||||
@@ -56,6 +59,27 @@ class WorkMeshPromotionPreflightRequest(BaseModel):
|
||||
DeploymentSession = Annotated[Session, Depends(get_session)]
|
||||
DeploymentIdempotencyKey = Annotated[str | None, Header(alias="Idempotency-Key")]
|
||||
DeploymentLimit = Annotated[int, Query(ge=1, le=250)]
|
||||
_FORGE_ROUTE_JOB_ID = re.compile(r"^forge-install-[0-9a-f]{64}$")
|
||||
_FORGE_ROUTE_IDEMPOTENCY_KEY = re.compile(r"^[A-Za-z0-9._:-]{8,128}$")
|
||||
|
||||
|
||||
async def _require_empty_forge_route_request(request: Request) -> None:
|
||||
lengths = request.headers.getlist("content-length")
|
||||
if (
|
||||
request.query_params
|
||||
or len(lengths) > 1
|
||||
or (lengths and lengths[0] != "0")
|
||||
or request.headers.getlist("transfer-encoding")
|
||||
):
|
||||
raise HTTPException(status_code=400, detail="invalid_forge_route_request")
|
||||
try:
|
||||
async for chunk in request.stream():
|
||||
if chunk:
|
||||
raise HTTPException(status_code=400, detail="invalid_forge_route_request")
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception: # noqa: BLE001 - transport detail is not part of this contract.
|
||||
raise HTTPException(status_code=400, detail="invalid_forge_route_request") from None
|
||||
|
||||
|
||||
def _idempotency_header(value: str | None) -> str:
|
||||
@@ -232,6 +256,70 @@ def get_forge_first_install_readiness(
|
||||
return ForgeBootstrapApplyService().current_readiness(session, job_id)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/forge-bootstrap/first-install/{job_id}/route",
|
||||
response_model=ForgeRouteStageResultV1,
|
||||
description=(
|
||||
"Stages only the fixed Forge NPM host in a disabled state after fresh runtime and network checks. "
|
||||
"The request body must be empty; this operation does not issue certificates or activate routing."
|
||||
),
|
||||
)
|
||||
async def stage_forge_first_install_route(
|
||||
job_id: str,
|
||||
request: Request,
|
||||
actor: Annotated[str, Depends(_require_deployment_operator)],
|
||||
session: DeploymentSession,
|
||||
):
|
||||
if _FORGE_ROUTE_JOB_ID.fullmatch(job_id) is None:
|
||||
raise HTTPException(status_code=404, detail="Forge first-install request not found.")
|
||||
await _require_empty_forge_route_request(request)
|
||||
keys = request.headers.getlist("idempotency-key")
|
||||
if len(keys) != 1 or _FORGE_ROUTE_IDEMPOTENCY_KEY.fullmatch(keys[0]) is None:
|
||||
raise HTTPException(status_code=400, detail="invalid_forge_route_idempotency_key")
|
||||
from ..services.forge_route_stage import stage_forge_route
|
||||
|
||||
try:
|
||||
return await run_in_threadpool(
|
||||
stage_forge_route,
|
||||
session,
|
||||
job_id=job_id,
|
||||
idempotency_key=keys[0],
|
||||
actor_identity=actor,
|
||||
)
|
||||
except Exception: # noqa: BLE001 - no controller/NPM details may reach the caller.
|
||||
raise HTTPException(status_code=503, detail="forge_route_operation_unavailable") from None
|
||||
|
||||
|
||||
@router.get(
|
||||
"/forge-bootstrap/first-install/{job_id}/route",
|
||||
response_model=ForgeRouteStageResultV1,
|
||||
description=(
|
||||
"Reads and reconciles the fixed disabled Forge host using NPM GET requests only. "
|
||||
"It never retries a host creation."
|
||||
),
|
||||
)
|
||||
async def get_forge_first_install_route(
|
||||
job_id: str,
|
||||
request: Request,
|
||||
actor_identity: Annotated[str, Depends(_require_deployment_operator)],
|
||||
session: DeploymentSession,
|
||||
):
|
||||
if _FORGE_ROUTE_JOB_ID.fullmatch(job_id) is None:
|
||||
raise HTTPException(status_code=404, detail="Forge first-install request not found.")
|
||||
await _require_empty_forge_route_request(request)
|
||||
from ..services.forge_route_stage import reconcile_forge_route
|
||||
|
||||
try:
|
||||
return await run_in_threadpool(
|
||||
reconcile_forge_route,
|
||||
session,
|
||||
job_id=job_id,
|
||||
actor_identity=actor_identity,
|
||||
)
|
||||
except Exception: # noqa: BLE001 - no controller/NPM details may reach the caller.
|
||||
raise HTTPException(status_code=503, detail="forge_route_reconcile_unavailable") from None
|
||||
|
||||
|
||||
@router.get("")
|
||||
def list_deployments(session: DeploymentSession, limit: DeploymentLimit = 100):
|
||||
return {"items": DeploymentControlPlane().list_jobs(session, limit=limit)}
|
||||
|
||||
Reference in new issue
Block a user