Add SQLite database integration with SQLAlchemy async, migration tooling, and comprehensive CRUD operations for hosts, tasks, schedules, and logs
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
"""Tests basiques pour valider la couche DB SQLAlchemy async."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
from app.models.database import async_session_maker, init_db, engine
|
||||
from app.crud.host import HostRepository
|
||||
from app.crud.bootstrap_status import BootstrapStatusRepository
|
||||
from app.crud.task import TaskRepository
|
||||
from app.crud.schedule import ScheduleRepository
|
||||
from app.crud.log import LogRepository
|
||||
|
||||
# Configure pytest-asyncio
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(scope="module")
|
||||
async def setup_db():
|
||||
await init_db()
|
||||
yield
|
||||
# Cleanup: drop all tables
|
||||
from app.models.database import Base
|
||||
async with engine.begin() as conn:
|
||||
await conn.run_sync(Base.metadata.drop_all)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_host(setup_db):
|
||||
async with async_session_maker() as session:
|
||||
repo = HostRepository(session)
|
||||
host = await repo.create(
|
||||
id="test-host-001",
|
||||
name="test.host.local",
|
||||
ip_address="192.168.1.100",
|
||||
ansible_group="env_test",
|
||||
status="online",
|
||||
reachable=True,
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
assert host.id == "test-host-001"
|
||||
assert host.name == "test.host.local"
|
||||
assert host.ip_address == "192.168.1.100"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_hosts(setup_db):
|
||||
async with async_session_maker() as session:
|
||||
repo = HostRepository(session)
|
||||
hosts = await repo.list(limit=10, offset=0)
|
||||
assert isinstance(hosts, list)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_task(setup_db):
|
||||
async with async_session_maker() as session:
|
||||
repo = TaskRepository(session)
|
||||
task = await repo.create(
|
||||
id="task-001",
|
||||
action="health-check",
|
||||
target="all",
|
||||
playbook="health-check.yml",
|
||||
status="pending",
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
assert task.id == "task-001"
|
||||
assert task.action == "health-check"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_log(setup_db):
|
||||
async with async_session_maker() as session:
|
||||
repo = LogRepository(session)
|
||||
log = await repo.create(
|
||||
level="INFO",
|
||||
message="Test log entry",
|
||||
source="test",
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
assert log.id is not None
|
||||
assert log.level == "INFO"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_soft_delete_host(setup_db):
|
||||
async with async_session_maker() as session:
|
||||
repo = HostRepository(session)
|
||||
# Create a host to delete
|
||||
host = await repo.create(
|
||||
id="host-to-delete",
|
||||
name="delete.me.local",
|
||||
ip_address="192.168.1.200",
|
||||
status="unknown",
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
# Soft delete
|
||||
deleted = await repo.soft_delete("host-to-delete")
|
||||
await session.commit()
|
||||
assert deleted is True
|
||||
|
||||
# Should not appear in normal list
|
||||
hosts = await repo.list()
|
||||
host_ids = [h.id for h in hosts]
|
||||
assert "host-to-delete" not in host_ids
|
||||
|
||||
# But should appear with include_deleted=True
|
||||
host_with_deleted = await repo.get("host-to-delete", include_deleted=True)
|
||||
assert host_with_deleted is not None
|
||||
assert host_with_deleted.deleted_at is not None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_schedule(setup_db):
|
||||
from app.crud.schedule import ScheduleRepository
|
||||
async with async_session_maker() as session:
|
||||
repo = ScheduleRepository(session)
|
||||
schedule = await repo.create(
|
||||
id="schedule-001",
|
||||
name="Daily Backup",
|
||||
playbook="backup.yml",
|
||||
target="all",
|
||||
schedule_type="recurring",
|
||||
recurrence_type="daily",
|
||||
recurrence_time="02:00",
|
||||
enabled=True,
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
assert schedule.id == "schedule-001"
|
||||
assert schedule.name == "Daily Backup"
|
||||
assert schedule.enabled is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_schedule_soft_delete(setup_db):
|
||||
from app.crud.schedule import ScheduleRepository
|
||||
async with async_session_maker() as session:
|
||||
repo = ScheduleRepository(session)
|
||||
# Create
|
||||
schedule = await repo.create(
|
||||
id="schedule-to-delete",
|
||||
name="To Delete",
|
||||
playbook="test.yml",
|
||||
target="all",
|
||||
schedule_type="once",
|
||||
enabled=True,
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
# Soft delete
|
||||
deleted = await repo.soft_delete("schedule-to-delete")
|
||||
await session.commit()
|
||||
assert deleted is True
|
||||
|
||||
# Should not appear in normal list
|
||||
schedules = await repo.list()
|
||||
schedule_ids = [s.id for s in schedules]
|
||||
assert "schedule-to-delete" not in schedule_ids
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_schedule_run(setup_db):
|
||||
from app.crud.schedule import ScheduleRepository
|
||||
from app.crud.schedule_run import ScheduleRunRepository
|
||||
from datetime import datetime, timezone
|
||||
|
||||
async with async_session_maker() as session:
|
||||
# Create schedule first
|
||||
sched_repo = ScheduleRepository(session)
|
||||
schedule = await sched_repo.create(
|
||||
id="schedule-for-run",
|
||||
name="Run Test",
|
||||
playbook="test.yml",
|
||||
target="all",
|
||||
schedule_type="once",
|
||||
enabled=True,
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
# Create run
|
||||
run_repo = ScheduleRunRepository(session)
|
||||
run = await run_repo.create(
|
||||
schedule_id="schedule-for-run",
|
||||
status="running",
|
||||
started_at=datetime.now(timezone.utc),
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
assert run.id is not None
|
||||
assert run.schedule_id == "schedule-for-run"
|
||||
assert run.status == "running"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Reference in New Issue
Block a user