75 lines
1.8 KiB
Python
75 lines
1.8 KiB
Python
"""Agent model for SysAdmin automation workers."""
|
|
|
|
import uuid
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
from typing import TYPE_CHECKING
|
|
|
|
from sqlalchemy import DateTime, ForeignKey, String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.models.base import Base, TimestampMixin, UUIDMixin
|
|
|
|
if TYPE_CHECKING:
|
|
from app.models.task import Task
|
|
from app.models.tenant import Tenant
|
|
|
|
|
|
class AgentStatus(str, Enum):
|
|
"""Agent status values."""
|
|
|
|
ONLINE = "online"
|
|
OFFLINE = "offline"
|
|
|
|
|
|
class Agent(UUIDMixin, TimestampMixin, Base):
|
|
"""
|
|
Agent model representing a SysAdmin automation worker.
|
|
|
|
Agents register with the orchestrator and receive tasks to execute.
|
|
"""
|
|
|
|
__tablename__ = "agents"
|
|
|
|
tenant_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
ForeignKey("tenants.id", ondelete="CASCADE"),
|
|
nullable=True,
|
|
index=True,
|
|
)
|
|
name: Mapped[str] = mapped_column(
|
|
String(255),
|
|
nullable=False,
|
|
)
|
|
version: Mapped[str] = mapped_column(
|
|
String(50),
|
|
nullable=False,
|
|
default="",
|
|
)
|
|
status: Mapped[str] = mapped_column(
|
|
String(20),
|
|
nullable=False,
|
|
default=AgentStatus.OFFLINE.value,
|
|
index=True,
|
|
)
|
|
last_heartbeat: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True),
|
|
nullable=True,
|
|
)
|
|
token: Mapped[str] = mapped_column(
|
|
Text,
|
|
nullable=False,
|
|
default="",
|
|
)
|
|
|
|
# Relationships
|
|
tenant: Mapped["Tenant | None"] = relationship(
|
|
back_populates="agents",
|
|
)
|
|
tasks: Mapped[list["Task"]] = relationship(
|
|
back_populates="agent",
|
|
lazy="selectin",
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Agent(id={self.id}, name={self.name}, status={self.status})>"
|