Files
Unraid-AppOps-Gateway-Public/backend/app/schemas/forge_runtime_readiness.py
T

158 lines
6.5 KiB
Python

from __future__ import annotations
import re
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr, model_validator
from .forge_secret_delivery import ForgeSecretDeliveryControllerArtifactV1
_REVISION = re.compile(r"^[0-9a-f]{40}$")
_DIGEST = re.compile(r"^sha256:[0-9a-f]{64}$")
_REQUEST = re.compile(r"^[0-9a-f]{64}$")
_NONCE = re.compile(r"^[0-9a-f]{32}$")
_JOB = re.compile(r"^forge-install-[0-9a-f]{64}$")
_RUNTIME_SERVICES = ("api", "dashboard", "itworx-forge", "postgres", "worker")
class ForgeRuntimeReadinessProfileV1(BaseModel):
model_config = ConfigDict(extra="forbid", frozen=True, strict=True)
revision: StrictStr = Field(pattern=_REVISION.pattern)
workspace_image_digest: StrictStr = Field(alias="workspaceImageDigest", pattern=_DIGEST.pattern)
frontdoor_image_digest: StrictStr = Field(alias="frontdoorImageDigest", pattern=_DIGEST.pattern)
class ForgeRuntimeServiceHealthV1(BaseModel):
model_config = ConfigDict(extra="forbid", frozen=True, strict=True)
name: Literal["api", "dashboard", "itworx-forge", "postgres", "worker"]
status: Literal["healthy", "not_ready", "unavailable"]
class ForgeRuntimeHealthV1(BaseModel):
model_config = ConfigDict(extra="forbid", frozen=True, strict=True)
status: Literal["healthy", "not_ready", "unavailable"]
services: list[ForgeRuntimeServiceHealthV1]
@model_validator(mode="after")
def fixed_service_set(self) -> ForgeRuntimeHealthV1:
if tuple(item.name for item in self.services) != _RUNTIME_SERVICES:
raise ValueError("runtime service set is invalid")
return self
class ForgeRuntimeReadinessV1(BaseModel):
"""Strict controller response for one fresh, fixed Forge observation."""
model_config = ConfigDict(extra="forbid", frozen=True, populate_by_name=True, strict=True)
api_version: Literal["itworx.forge-runtime-readiness/v1"] = Field(alias="apiVersion")
status: Literal["ready", "not_ready", "unavailable"]
repository: Literal["jens/itworx-forge"]
operation: Literal["forge_first_install"]
request: StrictStr = Field(pattern=_REQUEST.pattern)
profile: ForgeRuntimeReadinessProfileV1
observed_at: StrictInt = Field(alias="observedAt", ge=0)
nonce: StrictStr = Field(pattern=_NONCE.pattern)
health: ForgeRuntimeHealthV1
migration_completed: StrictBool = Field(alias="migrationCompleted")
controller_artifact: ForgeSecretDeliveryControllerArtifactV1 = Field(alias="controllerArtifact")
@model_validator(mode="after")
def readiness_consistency(self) -> ForgeRuntimeReadinessV1:
service_statuses = {item.status for item in self.health.services}
expected_health = (
"unavailable"
if "unavailable" in service_statuses
else "not_ready"
if "not_ready" in service_statuses
else "healthy"
)
valid_overall = (
self.status == "unavailable"
if expected_health == "unavailable"
else self.status in {"not_ready", "unavailable"}
if expected_health == "not_ready"
else self.status == "ready"
if self.migration_completed
else self.status in {"not_ready", "unavailable"}
)
if self.health.status != expected_health or not valid_overall:
raise ValueError("readiness status does not match current health proof")
return self
class ForgeRuntimeReadinessResultV1(BaseModel):
"""Bounded operator projection; upstream diagnostics and nonce are omitted."""
model_config = ConfigDict(extra="forbid", frozen=True, populate_by_name=True, strict=True)
status: Literal["ready", "not_ready", "unavailable"]
message: Literal[
"forge_runtime_ready",
"forge_runtime_not_ready",
"forge_runtime_readiness_unavailable",
]
target: Literal["itworx-forge"] = "itworx-forge"
job_id: StrictStr | None = Field(default=None, alias="jobId", pattern=_JOB.pattern)
revision: StrictStr | None = Field(default=None, pattern=_REVISION.pattern)
workspace_image_digest: StrictStr | None = Field(
default=None, alias="workspaceImageDigest", pattern=_DIGEST.pattern
)
frontdoor_image_digest: StrictStr | None = Field(
default=None, alias="frontdoorImageDigest", pattern=_DIGEST.pattern
)
observed_at: StrictInt | None = Field(default=None, alias="observedAt", ge=0)
health: ForgeRuntimeHealthV1
migration_completed: StrictBool = Field(default=False, alias="migrationCompleted")
controller_artifact: ForgeSecretDeliveryControllerArtifactV1 | None = Field(
default=None, alias="controllerArtifact"
)
@model_validator(mode="after")
def public_status_message(self) -> ForgeRuntimeReadinessResultV1:
expected = {
"ready": "forge_runtime_ready",
"not_ready": "forge_runtime_not_ready",
"unavailable": "forge_runtime_readiness_unavailable",
}[self.status]
if self.message != expected:
raise ValueError("readiness message does not match status")
service_statuses = {item.status for item in self.health.services}
expected_health = (
"unavailable"
if "unavailable" in service_statuses
else "not_ready"
if "not_ready" in service_statuses
else "healthy"
)
valid_overall = (
self.status == "unavailable"
if expected_health == "unavailable"
else self.status in {"not_ready", "unavailable"}
if expected_health == "not_ready"
else self.status == "ready"
if self.migration_completed
else self.status in {"not_ready", "unavailable"}
)
if self.health.status != expected_health or not valid_overall:
raise ValueError("public readiness is inconsistent")
identity_fields = (
self.job_id,
self.revision,
self.workspace_image_digest,
self.frontdoor_image_digest,
self.observed_at,
self.controller_artifact,
)
if self.job_id is None and (
self.status != "unavailable"
or any(value is not None for value in identity_fields[1:])
):
raise ValueError("public readiness identity is incomplete")
if self.job_id is not None and any(value is None for value in identity_fields):
raise ValueError("public readiness identity is incomplete")
return self