""" Service model for applications running on infrastructure. Services represent applications, databases, web servers, and other software running on infrastructure components. """ from typing import TYPE_CHECKING, Optional from sqlalchemy import CHAR, CheckConstraint, ForeignKey, Index, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from .base import Base, TimestampMixin, UUIDMixin if TYPE_CHECKING: from .deployment import Deployment class Service(Base, UUIDMixin, TimestampMixin): """ Service model representing applications running on infrastructure. Tracks applications, services, databases, web servers, and other software components running on infrastructure with URLs, ports, and status. Attributes: infrastructure_id: Reference to the infrastructure hosting this service service_name: Name of the service (e.g., "Gitea", "PostgreSQL") service_type: Type of service (e.g., "git_hosting", "database") external_url: External URL for accessing the service internal_url: Internal URL for accessing the service port: Port number the service runs on protocol: Protocol used (https, ssh, smb, etc.) status: Current status (running, stopped, error, maintenance) version: Version of the service notes: Additional notes """ __tablename__ = "services" # Foreign keys infrastructure_id: Mapped[Optional[str]] = mapped_column( CHAR(36), ForeignKey("infrastructure.id", ondelete="CASCADE"), doc="Reference to the infrastructure hosting this service" ) # Service identification service_name: Mapped[str] = mapped_column( String(255), nullable=False, doc="Name of the service (e.g., 'Gitea', 'PostgreSQL', 'Apache')" ) service_type: Mapped[Optional[str]] = mapped_column( String(100), doc="Type of service (e.g., 'git_hosting', 'database', 'web_server')" ) # URLs and connectivity external_url: Mapped[Optional[str]] = mapped_column( String(500), doc="External URL for accessing the service" ) internal_url: Mapped[Optional[str]] = mapped_column( String(500), doc="Internal URL for accessing the service" ) port: Mapped[Optional[int]] = mapped_column( Integer, doc="Port number the service runs on" ) protocol: Mapped[Optional[str]] = mapped_column( String(50), doc="Protocol used (https, ssh, smb, etc.)" ) # Status status: Mapped[str] = mapped_column( String(50), default="running", server_default="running", nullable=False, doc="Status: running, stopped, error, maintenance" ) # Version version: Mapped[Optional[str]] = mapped_column( String(100), doc="Version of the service" ) # Notes notes: Mapped[Optional[str]] = mapped_column( Text, doc="Additional notes" ) # Relationships deployments: Mapped[list["Deployment"]] = relationship( "Deployment", back_populates="service", doc="Relationship to Deployment model" ) # Constraints and indexes __table_args__ = ( CheckConstraint( "status IN ('running', 'stopped', 'error', 'maintenance')", name="ck_services_status" ), Index("idx_services_infrastructure", "infrastructure_id"), Index("idx_services_name", "service_name"), Index("idx_services_type", "service_type"), ) def __repr__(self) -> str: """String representation of the service.""" return f""