from typing import Literal from pydantic import BaseModel, Field, field_validator class LokiQueryRangeRequest(BaseModel): query: str start: str end: str cluster_id: str env: str deploy_type: str limit: int = Field(default=100, ge=1, le=10000) direction: Literal["forward", "backward"] = "backward" step: str | None = None @field_validator("query") @classmethod def validate_query(cls, v: str) -> str: if not v or not v.strip(): raise ValueError("query cannot be empty") if "{" not in v or "}" not in v: raise ValueError("query must contain {}") return v @field_validator("start", "end") @classmethod def validate_timestamp(cls, v: str) -> str: if not v or not v.strip(): raise ValueError("timestamp cannot be empty") return v class LokiQueryInstantRequest(BaseModel): query: str cluster_id: str env: str deploy_type: str time: str | None = None limit: int = Field(default=100, ge=1, le=10000) direction: Literal["forward", "backward"] = "backward" @field_validator("query") @classmethod def validate_query(cls, v: str) -> str: if not v or not v.strip(): raise ValueError("query cannot be empty") if "{" not in v or "}" not in v: raise ValueError("query must contain {}") return v class LokiLabelsRequest(BaseModel): cluster_id: str env: str deploy_type: str start: str | None = None end: str | None = None query: str | None = None class LokiLabelValuesRequest(BaseModel): label_name: str cluster_id: str env: str deploy_type: str start: str | None = None end: str | None = None query: str | None = None @field_validator("label_name") @classmethod def validate_label_name(cls, v: str) -> str: if not v or not v.strip(): raise ValueError("label_name cannot be empty") return v class LokiSeriesRequest(BaseModel): match: list[str] cluster_id: str env: str deploy_type: str start: str | None = None end: str | None = None @field_validator("match") @classmethod def validate_match(cls, v: list[str]) -> list[str]: if not v or len(v) < 1: raise ValueError("match must have at least 1 item") return v