"""Docker Image model for Homelab Automation.""" from __future__ import annotations from datetime import datetime from typing import Optional from sqlalchemy import BigInteger, DateTime, ForeignKey, Integer, String, JSON, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql import func from .database import Base class DockerImage(Base): """Model representing a Docker image on a host.""" __tablename__ = "docker_images" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) host_id: Mapped[str] = mapped_column(String, ForeignKey("hosts.id", ondelete="CASCADE"), nullable=False) image_id: Mapped[str] = mapped_column(String(64), nullable=False) repo_tags: Mapped[Optional[list]] = mapped_column(JSON, nullable=True) # ["nginx:latest", "nginx:1.25"] size: Mapped[Optional[int]] = mapped_column(BigInteger, nullable=True) created: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) last_update_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now(), onupdate=func.now() ) # Relationship to host host: Mapped["Host"] = relationship("Host", back_populates="docker_images") __table_args__ = ( UniqueConstraint('host_id', 'image_id', name='uq_docker_images_host_image'), {"sqlite_autoincrement": True}, ) def __repr__(self) -> str: # pragma: no cover tags = self.repo_tags[0] if self.repo_tags else self.image_id[:12] return f"" def to_dict(self) -> dict: """Convert to dictionary for API responses.""" return { "id": self.id, "host_id": self.host_id, "image_id": self.image_id, "repo_tags": self.repo_tags, "size": self.size, "created": self.created.isoformat() if self.created else None, "last_update_at": self.last_update_at.isoformat() if self.last_update_at else None, }