205 lines
6.7 KiB
Python
205 lines
6.7 KiB
Python
"""Tests for Nextcloud playbook routes."""
|
|
|
|
import uuid
|
|
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.models.agent import Agent
|
|
from app.models.task import Task
|
|
from app.models.tenant import Tenant
|
|
from app.playbooks.nextcloud import NEXTCLOUD_STACK_DIR
|
|
from app.routes.playbooks import (
|
|
NextcloudSetDomainRequest,
|
|
nextcloud_set_domain,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
class TestNextcloudSetDomainEndpoint:
|
|
"""Tests for the nextcloud_set_domain endpoint."""
|
|
|
|
async def test_happy_path_creates_task(
|
|
self, db: AsyncSession, test_tenant: Tenant, test_agent_for_tenant: Agent
|
|
):
|
|
"""POST /tenants/{id}/nextcloud/set-domain returns 201 with COMPOSITE task."""
|
|
request = NextcloudSetDomainRequest(
|
|
public_url="https://cloud.example.com",
|
|
pull=False,
|
|
)
|
|
|
|
task = await nextcloud_set_domain(
|
|
tenant_id=test_tenant.id, request=request, db=db
|
|
)
|
|
|
|
assert task.id is not None
|
|
assert task.tenant_id == test_tenant.id
|
|
assert task.agent_id == test_agent_for_tenant.id
|
|
assert task.type == "COMPOSITE"
|
|
assert task.status == "pending"
|
|
|
|
async def test_task_has_both_steps(
|
|
self, db: AsyncSession, test_tenant: Tenant, test_agent_for_tenant: Agent
|
|
):
|
|
"""Verify response task payload contains both steps in correct order."""
|
|
request = NextcloudSetDomainRequest(
|
|
public_url="https://cloud.example.com",
|
|
pull=True,
|
|
)
|
|
|
|
task = await nextcloud_set_domain(
|
|
tenant_id=test_tenant.id, request=request, db=db
|
|
)
|
|
|
|
assert "steps" in task.payload
|
|
assert len(task.payload["steps"]) == 2
|
|
|
|
# First step: NEXTCLOUD_SET_DOMAIN
|
|
step0 = task.payload["steps"][0]
|
|
assert step0["type"] == "NEXTCLOUD_SET_DOMAIN"
|
|
assert step0["payload"]["public_url"] == "https://cloud.example.com"
|
|
|
|
# Second step: DOCKER_RELOAD
|
|
step1 = task.payload["steps"][1]
|
|
assert step1["type"] == "DOCKER_RELOAD"
|
|
assert step1["payload"]["compose_dir"] == NEXTCLOUD_STACK_DIR
|
|
assert step1["payload"]["pull"] is True
|
|
|
|
async def test_pull_flag_default_false(
|
|
self, db: AsyncSession, test_tenant: Tenant, test_agent_for_tenant: Agent
|
|
):
|
|
"""Verify pull defaults to False when not specified."""
|
|
request = NextcloudSetDomainRequest(
|
|
public_url="https://cloud.example.com",
|
|
)
|
|
|
|
task = await nextcloud_set_domain(
|
|
tenant_id=test_tenant.id, request=request, db=db
|
|
)
|
|
|
|
step = task.payload["steps"][1]
|
|
assert step["payload"]["pull"] is False
|
|
|
|
async def test_tenant_not_found_returns_404(self, db: AsyncSession):
|
|
"""Non-existent tenant_id returns 404."""
|
|
fake_tenant_id = uuid.uuid4()
|
|
request = NextcloudSetDomainRequest(
|
|
public_url="https://cloud.example.com",
|
|
pull=False,
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
await nextcloud_set_domain(
|
|
tenant_id=fake_tenant_id, request=request, db=db
|
|
)
|
|
|
|
assert exc_info.value.status_code == 404
|
|
assert f"Tenant {fake_tenant_id} not found" in str(exc_info.value.detail)
|
|
|
|
async def test_no_online_agent_returns_404(
|
|
self, db: AsyncSession, test_tenant: Tenant
|
|
):
|
|
"""Tenant with no online agent returns 404."""
|
|
request = NextcloudSetDomainRequest(
|
|
public_url="https://cloud.example.com",
|
|
pull=False,
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
await nextcloud_set_domain(
|
|
tenant_id=test_tenant.id, request=request, db=db
|
|
)
|
|
|
|
assert exc_info.value.status_code == 404
|
|
assert "No online agent found" in str(exc_info.value.detail)
|
|
|
|
async def test_offline_agent_not_resolved(
|
|
self, db: AsyncSession, test_tenant: Tenant
|
|
):
|
|
"""Offline agent should not be auto-resolved."""
|
|
# Create an offline agent for the tenant
|
|
offline_agent = Agent(
|
|
id=uuid.uuid4(),
|
|
tenant_id=test_tenant.id,
|
|
name="offline-agent",
|
|
version="1.0.0",
|
|
status="offline",
|
|
token="offline-token",
|
|
)
|
|
db.add(offline_agent)
|
|
await db.commit()
|
|
|
|
request = NextcloudSetDomainRequest(
|
|
public_url="https://cloud.example.com",
|
|
pull=False,
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
await nextcloud_set_domain(
|
|
tenant_id=test_tenant.id, request=request, db=db
|
|
)
|
|
|
|
assert exc_info.value.status_code == 404
|
|
assert "No online agent found" in str(exc_info.value.detail)
|
|
|
|
async def test_task_persisted_to_database(
|
|
self, db: AsyncSession, test_tenant: Tenant, test_agent_for_tenant: Agent
|
|
):
|
|
"""Verify the task is actually persisted and can be retrieved."""
|
|
request = NextcloudSetDomainRequest(
|
|
public_url="https://cloud.example.com",
|
|
pull=False,
|
|
)
|
|
|
|
task = await nextcloud_set_domain(
|
|
tenant_id=test_tenant.id, request=request, db=db
|
|
)
|
|
|
|
# Query the task back from the database
|
|
result = await db.execute(select(Task).where(Task.id == task.id))
|
|
retrieved_task = result.scalar_one_or_none()
|
|
|
|
assert retrieved_task is not None
|
|
assert retrieved_task.type == "COMPOSITE"
|
|
assert retrieved_task.tenant_id == test_tenant.id
|
|
assert retrieved_task.agent_id == test_agent_for_tenant.id
|
|
|
|
async def test_auto_resolves_first_online_agent(
|
|
self, db: AsyncSession, test_tenant: Tenant
|
|
):
|
|
"""Verify that the first online agent is auto-resolved."""
|
|
# Create two agents for the tenant - one offline, one online
|
|
offline_agent = Agent(
|
|
id=uuid.uuid4(),
|
|
tenant_id=test_tenant.id,
|
|
name="offline-agent",
|
|
version="1.0.0",
|
|
status="offline",
|
|
token="offline-token",
|
|
)
|
|
online_agent = Agent(
|
|
id=uuid.uuid4(),
|
|
tenant_id=test_tenant.id,
|
|
name="online-agent",
|
|
version="1.0.0",
|
|
status="online",
|
|
token="online-token",
|
|
)
|
|
db.add(offline_agent)
|
|
db.add(online_agent)
|
|
await db.commit()
|
|
|
|
request = NextcloudSetDomainRequest(
|
|
public_url="https://cloud.example.com",
|
|
pull=False,
|
|
)
|
|
|
|
task = await nextcloud_set_domain(
|
|
tenant_id=test_tenant.id, request=request, db=db
|
|
)
|
|
|
|
# Should have resolved to the online agent
|
|
assert task.agent_id == online_agent.id
|