131 lines
3.9 KiB
Python
131 lines
3.9 KiB
Python
from types import SimpleNamespace
|
|
|
|
from unittest.mock import AsyncMock
|
|
|
|
import pytest
|
|
|
|
from src.models.approval import RiskLevel
|
|
from src.services.approval_execution import ApprovalExecutionService
|
|
|
|
|
|
class _FakeAutoRepairRepo:
|
|
def __init__(self) -> None:
|
|
self.created: list[dict] = []
|
|
|
|
async def list_by_incident(self, incident_id: str) -> list:
|
|
return []
|
|
|
|
async def create(self, **kwargs):
|
|
self.created.append(kwargs)
|
|
return SimpleNamespace(id="are-1", **kwargs)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_finalize_auto_approved_execution_persists_incident_link(monkeypatch):
|
|
repo = _FakeAutoRepairRepo()
|
|
timeline = SimpleNamespace(add_event=AsyncMock())
|
|
incident_service = SimpleNamespace(resolve_incident=AsyncMock())
|
|
write_km = AsyncMock()
|
|
run_verify = AsyncMock()
|
|
|
|
monkeypatch.setattr(
|
|
"src.repositories.audit_log_repository.get_auto_repair_execution_repository",
|
|
lambda: repo,
|
|
)
|
|
monkeypatch.setattr(
|
|
"src.services.approval_execution.get_timeline_service",
|
|
lambda: timeline,
|
|
)
|
|
monkeypatch.setattr(
|
|
"src.services.incident_service.get_incident_service",
|
|
lambda: incident_service,
|
|
)
|
|
monkeypatch.setattr(
|
|
"src.core.feature_flags.aiops_flags",
|
|
SimpleNamespace(is_sub_flag_enabled=lambda _: True),
|
|
)
|
|
monkeypatch.setattr(
|
|
ApprovalExecutionService,
|
|
"write_execution_result_to_km",
|
|
write_km,
|
|
)
|
|
monkeypatch.setattr(
|
|
ApprovalExecutionService,
|
|
"_run_post_execution_verify",
|
|
run_verify,
|
|
)
|
|
|
|
approval = SimpleNamespace(
|
|
id="11111111-1111-1111-1111-111111111111",
|
|
incident_id="INC-20260513-001",
|
|
action="kubectl rollout restart deployment/api -n awoooi-prod",
|
|
requested_by="auto_approve_rule_engine",
|
|
matched_playbook_id="pb-auto-001",
|
|
risk_level=RiskLevel.LOW,
|
|
)
|
|
|
|
await ApprovalExecutionService().finalize_auto_approved_execution(
|
|
approval,
|
|
success=True,
|
|
)
|
|
|
|
assert repo.created == [
|
|
{
|
|
"incident_id": "INC-20260513-001",
|
|
"playbook_id": "pb-auto-001",
|
|
"playbook_name": "approval_auto_execute:RESTART_DEPLOYMENT:api",
|
|
"success": True,
|
|
"executed_steps": ["kubectl rollout restart deployment/api -n awoooi-prod"],
|
|
"error_message": None,
|
|
"triggered_by": "auto_approve_rule_engine",
|
|
"risk_level": "low",
|
|
}
|
|
]
|
|
timeline.add_event.assert_awaited_once()
|
|
write_km.assert_awaited_once_with(approval, True, None)
|
|
run_verify.assert_awaited_once()
|
|
assert run_verify.await_args.kwargs["action_taken"].startswith(
|
|
"auto_repair_playbook:pb-auto-001:RESTART_DEPLOYMENT:api"
|
|
)
|
|
incident_service.resolve_incident.assert_awaited_once_with("INC-20260513-001")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_finalize_auto_approved_execution_skips_no_action(monkeypatch):
|
|
repo = _FakeAutoRepairRepo()
|
|
write_km = AsyncMock()
|
|
run_verify = AsyncMock()
|
|
|
|
monkeypatch.setattr(
|
|
"src.repositories.audit_log_repository.get_auto_repair_execution_repository",
|
|
lambda: repo,
|
|
)
|
|
monkeypatch.setattr(
|
|
ApprovalExecutionService,
|
|
"write_execution_result_to_km",
|
|
write_km,
|
|
)
|
|
monkeypatch.setattr(
|
|
ApprovalExecutionService,
|
|
"_run_post_execution_verify",
|
|
run_verify,
|
|
)
|
|
|
|
approval = SimpleNamespace(
|
|
id="22222222-2222-2222-2222-222222222222",
|
|
incident_id="INC-20260513-002",
|
|
action="NO_ACTION: observe only",
|
|
requested_by="auto_approve_rule_engine",
|
|
matched_playbook_id="pb-auto-002",
|
|
risk_level=RiskLevel.LOW,
|
|
)
|
|
|
|
await ApprovalExecutionService().finalize_auto_approved_execution(
|
|
approval,
|
|
success=True,
|
|
)
|
|
|
|
assert repo.created == []
|
|
write_km.assert_not_awaited()
|
|
run_verify.assert_not_awaited()
|