"""Tests for the RDS investigation tools.""" from __future__ import annotations import logging from typing import Any from unittest.mock import patch from integrations.rds.tools.rds_describe_instance_tool import describe_rds_instance from integrations.rds.tools.rds_events_tool import describe_rds_events class _FakeAWSBackend: """Minimal AWSBackend stand-in that records calls for assertion.""" def __init__(self, db_response: dict[str, Any], events_response: dict[str, Any]) -> None: self.db_response = db_response self.events_response = events_response self.db_calls: list[dict[str, Any]] = [] self.events_calls: list[dict[str, Any]] = [] def describe_db_instances( self, db_instance_identifier: str, region: str = "", **_: Any, ) -> dict[str, Any]: self.db_calls.append({"db_instance_identifier": db_instance_identifier, "region": region}) return self.db_response def describe_db_events( self, db_instance_identifier: str, duration_minutes: int = 60, region: str = "", **_: Any, ) -> dict[str, Any]: self.events_calls.append( { "db_instance_identifier": db_instance_identifier, "duration_minutes": duration_minutes, "region": region, } ) return self.events_response @patch("integrations.rds.tools.rds_describe_instance_tool.execute_aws_sdk_call") def test_describe_rds_instance_success(mock_call) -> None: mock_call.return_value = { "success": True, "data": { "DBInstances": [ { "DBInstanceStatus": "available", "Engine": "postgres", "EngineVersion": "15.4", "DBInstanceClass": "db.t4g.micro", "MultiAZ": True, "PubliclyAccessible": False, "StorageType": "gp3", "AllocatedStorage": 20, "Endpoint": {"Address": "prod.abc.rds.aws", "Port": 5432}, "AvailabilityZone": "us-east-1a", "PreferredBackupWindow": "03:00-04:00", "BackupRetentionPeriod": 7, } ] }, } result = describe_rds_instance("prod-db", region="us-east-1") assert result["available"] is True assert result["status"] == "available" assert result["engine"] == "postgres" assert result["multi_az"] is True assert result["endpoint"]["port"] == 5432 @patch("integrations.rds.tools.rds_describe_instance_tool.execute_aws_sdk_call") def test_describe_rds_instance_not_found(mock_call) -> None: mock_call.return_value = {"success": True, "data": {"DBInstances": []}} result = describe_rds_instance("missing-db") assert result["available"] is False assert "No RDS instance" in result["error"] @patch("integrations.rds.tools.rds_describe_instance_tool.execute_aws_sdk_call") def test_describe_rds_instance_aws_failure(mock_call) -> None: mock_call.return_value = {"success": False, "error": "AccessDenied"} result = describe_rds_instance("prod-db") assert result["available"] is False assert result["error"] == "Failed to describe the RDS instance. Check server logs for details." @patch("integrations.rds.tools.rds_describe_instance_tool.execute_aws_sdk_call") def test_describe_rds_instance_multiple_instances_warns(mock_call, caplog) -> None: """When AWS returns >1 instance, use the first and emit a warning.""" mock_call.return_value = { "success": True, "data": { "DBInstances": [ { "DBInstanceStatus": "available", "Engine": "postgres", "EngineVersion": "15.4", "DBInstanceClass": "db.t4g.micro", "Endpoint": {"Address": "prod.abc.rds.aws", "Port": 5432}, }, { "DBInstanceStatus": "available", "Engine": "mysql", "EngineVersion": "8.0", "DBInstanceClass": "db.r6g.large", "Endpoint": {"Address": "replica.abc.rds.aws", "Port": 3306}, }, ] }, } with caplog.at_level(logging.WARNING): result = describe_rds_instance("prod-db") assert result["available"] is True assert result["engine"] == "postgres" # first instance used assert "returned 2 instances" in caplog.text @patch("integrations.rds.tools.rds_events_tool.execute_aws_sdk_call") def test_describe_rds_events_success(mock_call) -> None: mock_call.return_value = { "success": True, "data": { "Events": [ { "Date": "2026-05-05T12:00:00Z", "Message": "Multi-AZ instance failover started", "EventCategories": ["failover"], "SourceType": "db-instance", } ] }, } result = describe_rds_events("prod-db", duration_minutes=120) assert result["available"] is True assert result["total_events"] == 1 assert result["events"][0]["categories"] == ["failover"] @patch("integrations.rds.tools.rds_events_tool.execute_aws_sdk_call") def test_describe_rds_events_no_events(mock_call) -> None: mock_call.return_value = {"success": True, "data": {"Events": []}} result = describe_rds_events("prod-db") assert result["available"] is True assert result["total_events"] == 0 assert result["events"] == [] @patch("integrations.rds.tools.rds_events_tool.execute_aws_sdk_call") def test_describe_rds_events_failure(mock_call) -> None: mock_call.return_value = {"success": False, "error": "ThrottlingException"} result = describe_rds_events("prod-db") assert result["available"] is False assert result["error"] == "Failed to describe RDS events. Check server logs for details." # ───────────────────────────────────────────────────────────────────────────── # Synthetic-mode short-circuit: when an aws_backend handle is provided the # tool MUST route through it instead of boto3. This guards against the # regression where synthetic scenarios silently leaked describe_db_instances # calls to whatever real AWS account the developer was authenticated against. # ───────────────────────────────────────────────────────────────────────────── @patch("integrations.rds.tools.rds_describe_instance_tool.execute_aws_sdk_call") def test_describe_rds_instance_short_circuits_to_aws_backend(mock_call) -> None: backend = _FakeAWSBackend( db_response={ "source": "rds", "available": True, "db_instance_identifier": "synthetic-db", "engine": "mysql", "error": None, }, events_response={}, ) result = describe_rds_instance( "synthetic-db", region="us-east-1", aws_backend=backend, ) mock_call.assert_not_called() assert backend.db_calls == [{"db_instance_identifier": "synthetic-db", "region": "us-east-1"}] assert result["engine"] == "mysql" @patch("integrations.rds.tools.rds_events_tool.execute_aws_sdk_call") def test_describe_rds_events_short_circuits_to_aws_backend(mock_call) -> None: backend = _FakeAWSBackend( db_response={}, events_response={ "source": "rds", "available": True, "db_instance_identifier": "synthetic-db", "duration_minutes": 90, "total_events": 1, "events": [{"date": "2026-05-05T12:00:00Z", "message": "ok"}], "error": None, }, ) result = describe_rds_events( "synthetic-db", region="us-east-1", duration_minutes=90, aws_backend=backend, ) mock_call.assert_not_called() assert backend.events_calls == [ { "db_instance_identifier": "synthetic-db", "duration_minutes": 90, "region": "us-east-1", } ] assert result["total_events"] == 1