from typing import Any from sqlalchemy.ext.asyncio import AsyncSession from starlette.background import BackgroundTask from starlette.exceptions import HTTPException from src.tofu.models import ( TofuInstance, TofuInstanceTask, TofuInstanceTaskType, TofuInstanceStatus, update_tofu_instance_status, ) from src.tofu.tasks import process_tasks async def create_tofu_instance( configuration: dict[str, Any], db: AsyncSession, *, commit: bool = False, create_task: bool = True ) -> tuple[int, BackgroundTask | None]: instance = TofuInstance(configuration=configuration) db.add(instance) await db.flush() if create_task: task = TofuInstanceTask(instance_id=instance.id, task=TofuInstanceTaskType.DEPLOY) db.add(task) if commit: await db.commit() return instance.id, BackgroundTask(process_tasks) if create_task else None async def create_empty_tofu_instance(db: AsyncSession) -> int: config = {} tofu_instance_id, _ = await create_tofu_instance(config, db, create_task=False) return tofu_instance_id async def update_tofu_instance( instance: TofuInstance, configuration: dict[str, Any], db: AsyncSession, *, commit: bool = False, allow_pending: bool = False ) -> BackgroundTask: allowed_status = [TofuInstanceStatus.ACTIVE, TofuInstanceStatus.DRIFTED] if allow_pending: allowed_status.append(TofuInstanceStatus.PENDING) if instance.status not in allowed_status: raise HTTPException( status_code=412, detail="Updates only allowed for active instances" ) instance.configuration = configuration task = TofuInstanceTask(instance_id=instance.id, task=TofuInstanceTaskType.DEPLOY) db.add(task) await db.flush() update_tofu_instance_status(db, instance, task.id, TofuInstanceStatus.PENDING) if commit: await db.commit() return BackgroundTask(process_tasks) async def destroy_tofu_instance( instance: TofuInstance, db: AsyncSession, *, commit: bool = False ) -> BackgroundTask: if instance.status not in [TofuInstanceStatus.ACTIVE, TofuInstanceStatus.DRIFTED]: raise HTTPException( status_code=412, detail="Instance cannot be destroyed currently as it is pending update", ) task = TofuInstanceTask(instance_id=instance.id, task=TofuInstanceTaskType.DESTROY) db.add(task) await db.flush() update_tofu_instance_status(db, instance, task.id, TofuInstanceStatus.PENDING_DESTROY) if commit: await db.commit() return BackgroundTask(process_tasks)