from datetime import datetime from typing import Any, Literal from pydantic import BaseModel, Field class AssetCreate(BaseModel): name: str = Field(min_length=1, max_length=160) asset_type: str = Field(min_length=1, max_length=64) address: str | None = Field(default=None, max_length=255) metadata: dict[str, Any] = Field(default_factory=dict) class AssetUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=160) asset_type: str | None = Field(default=None, min_length=1, max_length=64) address: str | None = Field(default=None, max_length=255) status: str | None = Field(default=None, max_length=32) metadata: dict[str, Any] | None = None class AssetRead(AssetCreate): id: int status: str created_at: datetime updated_at: datetime model_config = {"from_attributes": True} class MonitorCreate(BaseModel): name: str = Field(min_length=1, max_length=160) monitor_type: str = Field(default="http", max_length=64) target: str = Field(min_length=1, max_length=512) asset_id: int | None = None config: dict[str, Any] = Field(default_factory=dict) interval_seconds: int = Field(default=60, ge=10) class MonitorUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=160) monitor_type: str | None = Field(default=None, max_length=64) target: str | None = Field(default=None, min_length=1, max_length=512) asset_id: int | None = None config: dict[str, Any] | None = None interval_seconds: int | None = Field(default=None, ge=10) status: str | None = Field(default=None, max_length=32) class MonitorRead(MonitorCreate): id: int status: str last_checked_at: datetime | None created_at: datetime updated_at: datetime model_config = {"from_attributes": True} class WebsiteMonitorCreate(BaseModel): name: str = Field(min_length=1, max_length=160) url: str = Field(min_length=1, max_length=512) asset_id: int | None = None expected_status: int = Field(default=200, ge=100, le=599) expected_text: str | None = None unexpected_text: str | None = None timeout_seconds: int = Field(default=10, ge=1, le=120) check_tls_expiry: bool = False tls_warning_days: int = Field(default=30, ge=1, le=365) interval_seconds: int = Field(default=60, ge=10) create_asset: bool = True alert_enabled: bool = True alert_severity: str = "critical" failure_threshold: int = Field(default=3, ge=1, le=20) class PingMonitorCreate(BaseModel): name: str = Field(min_length=1, max_length=160) host: str = Field(min_length=1, max_length=255) asset_id: int | None = None timeout_seconds: int = Field(default=5, ge=1, le=60) interval_seconds: int = Field(default=60, ge=10) create_asset: bool = True alert_enabled: bool = True alert_severity: str = "warning" failure_threshold: int = Field(default=3, ge=1, le=20) class TcpMonitorCreate(BaseModel): name: str = Field(min_length=1, max_length=160) host: str = Field(min_length=1, max_length=255) port: int = Field(ge=1, le=65535) asset_id: int | None = None timeout_seconds: int = Field(default=5, ge=1, le=60) interval_seconds: int = Field(default=60, ge=10) create_asset: bool = True alert_enabled: bool = True alert_severity: str = "warning" failure_threshold: int = Field(default=3, ge=1, le=20) class CheckResultRead(BaseModel): id: int monitor_id: int status: str response_time_ms: int | None message: str | None observed_at: datetime model_config = {"from_attributes": True} class AlertRuleCreate(BaseModel): monitor_id: int name: str = Field(min_length=1, max_length=160) severity: str = "warning" condition: dict[str, Any] = Field(default_factory=dict) failure_threshold: int = Field(default=3, ge=1) cooldown_seconds: int = Field(default=300, ge=0) is_enabled: bool = True class AlertRuleUpdate(BaseModel): monitor_id: int | None = None name: str | None = Field(default=None, min_length=1, max_length=160) severity: str | None = None condition: dict[str, Any] | None = None failure_threshold: int | None = Field(default=None, ge=1) cooldown_seconds: int | None = Field(default=None, ge=0) is_enabled: bool | None = None class AlertRuleRead(AlertRuleCreate): id: int created_at: datetime updated_at: datetime model_config = {"from_attributes": True} class IncidentRead(BaseModel): id: int asset_id: int | None monitor_id: int | None alert_rule_id: int | None title: str severity: str status: str opened_at: datetime resolved_at: datetime | None acknowledged_at: datetime | None silenced_until: datetime | None details: dict[str, Any] model_config = {"from_attributes": True} class NotificationChannelCreate(BaseModel): name: str = Field(min_length=1, max_length=160) channel_type: str = Field(min_length=1, max_length=64) settings: dict[str, Any] = Field(default_factory=dict) secret: str | None = None is_enabled: bool = True class NotificationChannelUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=160) channel_type: str | None = Field(default=None, min_length=1, max_length=64) settings: dict[str, Any] | None = None secret: str | None = None is_enabled: bool | None = None class NotificationChannelRead(BaseModel): id: int name: str channel_type: str settings: dict[str, Any] has_secret: bool is_enabled: bool created_at: datetime updated_at: datetime model_config = {"from_attributes": True} class SnmpCredentialProfileCreate(BaseModel): name: str = Field(min_length=1, max_length=160) version: Literal["2c"] = "2c" community: str = Field(min_length=1, max_length=255) port: int = Field(default=161, ge=1, le=65535) timeout_seconds: int = Field(default=5, ge=1, le=120) retries: int = Field(default=1, ge=0, le=10) class SnmpCredentialProfileUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=160) version: Literal["2c"] | None = None community: str | None = Field(default=None, min_length=1, max_length=255) port: int | None = Field(default=None, ge=1, le=65535) timeout_seconds: int | None = Field(default=None, ge=1, le=120) retries: int | None = Field(default=None, ge=0, le=10) class SnmpCredentialProfileRead(BaseModel): id: int name: str credential_type: str version: str port: int timeout_seconds: int retries: int has_secret: bool created_at: datetime updated_at: datetime class SnmpDiscoveryRequest(BaseModel): host: str = Field(min_length=1, max_length=255) credential_profile_id: int class SnmpDiscoveredInterfaceRead(BaseModel): index: int name: str description: str | None admin_status: str | None oper_status: str | None speed_bps: int | None class SnmpDiscoveryItemRead(BaseModel): item_id: str item_type: str group: str label: str unit: str | None = None class SnmpMonitorsCreate(BaseModel): host: str = Field(min_length=1, max_length=255) asset_id: int credential_profile_id: int selected_items: list[SnmpDiscoveryItemRead] = Field(min_length=1) interval_seconds: int = Field(default=60, ge=10) class SnmpDiscoveryRead(BaseModel): host: str credential_profile_id: int device_name: str | None description: str | None uptime_seconds: int | None interfaces: list[SnmpDiscoveredInterfaceRead] monitorable_items: list[SnmpDiscoveryItemRead]