"""Server inventory model. Credentials are NOT stored centrally. `credential_ref` is a symbolic name that the satellite resolves against its local credentials.yaml. """ import enum from datetime import UTC, datetime from sqlalchemy import DateTime, Enum, ForeignKey, String, Text, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column, relationship from app.core.database import Base class ServerType(enum.StrEnum): WINDOWS = "windows" # WinRM LINUX = "linux" # SSH CAU_CLUSTER = "cau_cluster" # Cluster-Aware Updating class Server(Base): __tablename__ = "servers" __table_args__ = ( UniqueConstraint("customer_id", "name", name="uq_server_customer_name"), ) id: Mapped[int] = mapped_column(primary_key=True) customer_id: Mapped[int] = mapped_column( ForeignKey("customers.id"), index=True ) customer: Mapped["Customer"] = relationship(back_populates="servers") # noqa: F821 name: Mapped[str] = mapped_column(String(255), index=True) hostname: Mapped[str] = mapped_column(String(255)) port: Mapped[int] = mapped_column(default=5985) type: Mapped[ServerType] = mapped_column(Enum(ServerType), default=ServerType.WINDOWS) description: Mapped[str | None] = mapped_column(Text, nullable=True) tags: Mapped[str | None] = mapped_column(String(500), nullable=True) # comma-separated # Symbolic reference to a credential stored locally on the satellite credential_ref: Mapped[str | None] = mapped_column(String(255), nullable=True) # Last health result reported by a satellite last_health_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) last_health_ok: Mapped[bool | None] = mapped_column(nullable=True) last_health_message: Mapped[str | None] = mapped_column(Text, nullable=True) # Set by network scan jobs discovered_by_scan: Mapped[bool] = mapped_column(default=False) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(UTC) ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC), ) jobs: Mapped[list["UpdateJob"]] = relationship( # noqa: F821 back_populates="server" )