awslabs.cloudwatch-mcp-server 0.0.8__tar.gz → 0.0.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/Dockerfile +2 -2
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/PKG-INFO +30 -1
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/README.md +29 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/cloudwatch_logs/tools.py +59 -10
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/pyproject.toml +1 -1
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_logs/test_logs_error_handling.py +72 -17
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_logs/test_logs_server.py +15 -11
- awslabs_cloudwatch_mcp_server-0.0.11/uv-requirements.txt +24 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/uv.lock +695 -695
- awslabs_cloudwatch_mcp_server-0.0.8/uv-requirements.txt +0 -26
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/.gitignore +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/.python-version +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/CHANGELOG.md +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/LICENSE +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/NOTICE +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/__init__.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/__init__.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/cloudwatch_alarms/models.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/cloudwatch_alarms/tools.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/cloudwatch_logs/models.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/cloudwatch_metrics/data/metric_metadata.json +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/cloudwatch_metrics/models.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/cloudwatch_metrics/tools.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/common.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/awslabs/cloudwatch_mcp_server/server.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/docker-healthcheck.sh +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_alarms/test_active_alarms.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_alarms/test_alarm_history.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_alarms/test_alarm_history_integration.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_alarms/test_alarms_error_handling.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_logs/test_logs_models.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_metrics/test_metrics_error_handling.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_metrics/test_metrics_models.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_metrics/test_metrics_server.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/cloudwatch_metrics/test_validation_error.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/test_common_and_server.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/test_init.py +0 -0
- {awslabs_cloudwatch_mcp_server-0.0.8 → awslabs_cloudwatch_mcp_server-0.0.11}/tests/test_main.py +0 -0
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
# dependabot should continue to update this to the latest hash.
|
|
16
|
-
FROM public.ecr.aws/docker/library/python:3.13
|
|
16
|
+
FROM public.ecr.aws/docker/library/python:3.13-alpine@sha256:070342a0cc1011532c0e69972cce2bbc6cc633eba294bae1d12abea8bd05303b AS uv
|
|
17
17
|
|
|
18
18
|
# Install the project into `/app`
|
|
19
19
|
WORKDIR /app
|
|
@@ -61,7 +61,7 @@ RUN --mount=type=cache,target=/root/.cache/uv \
|
|
|
61
61
|
# Make the directory just in case it doesn't exist
|
|
62
62
|
RUN mkdir -p /root/.local
|
|
63
63
|
|
|
64
|
-
FROM public.ecr.aws/docker/library/python:3.13
|
|
64
|
+
FROM public.ecr.aws/docker/library/python:3.13-alpine@sha256:070342a0cc1011532c0e69972cce2bbc6cc633eba294bae1d12abea8bd05303b
|
|
65
65
|
|
|
66
66
|
# Place executables in the environment at the front of the path and include other binaries
|
|
67
67
|
ENV PATH="/app/.venv/bin:$PATH" \
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: awslabs.cloudwatch-mcp-server
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.11
|
|
4
4
|
Summary: An AWS Labs Model Context Protocol (MCP) server for cloudwatch
|
|
5
5
|
Project-URL: homepage, https://awslabs.github.io/mcp/
|
|
6
6
|
Project-URL: docs, https://awslabs.github.io/mcp/servers/cloudwatch-mcp-server/
|
|
@@ -119,6 +119,35 @@ Alarm Recommendations - Suggests recommended alarm configurations for CloudWatch
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
```
|
|
122
|
+
### Windows Installation
|
|
123
|
+
|
|
124
|
+
For Windows users, the MCP server configuration format is slightly different:
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"mcpServers": {
|
|
129
|
+
"awslabs.cloudwatch-mcp-server": {
|
|
130
|
+
"disabled": false,
|
|
131
|
+
"timeout": 60,
|
|
132
|
+
"type": "stdio",
|
|
133
|
+
"command": "uv",
|
|
134
|
+
"args": [
|
|
135
|
+
"tool",
|
|
136
|
+
"run",
|
|
137
|
+
"--from",
|
|
138
|
+
"awslabs.cloudwatch-mcp-server@latest",
|
|
139
|
+
"awslabs.cloudwatch-mcp-server.exe"
|
|
140
|
+
],
|
|
141
|
+
"env": {
|
|
142
|
+
"FASTMCP_LOG_LEVEL": "ERROR",
|
|
143
|
+
"AWS_PROFILE": "your-aws-profile",
|
|
144
|
+
"AWS_REGION": "us-east-1"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
122
151
|
|
|
123
152
|
Please reference [AWS documentation](https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-files.html) to create and manage your credentials profile
|
|
124
153
|
|
|
@@ -90,6 +90,35 @@ Alarm Recommendations - Suggests recommended alarm configurations for CloudWatch
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
```
|
|
93
|
+
### Windows Installation
|
|
94
|
+
|
|
95
|
+
For Windows users, the MCP server configuration format is slightly different:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"mcpServers": {
|
|
100
|
+
"awslabs.cloudwatch-mcp-server": {
|
|
101
|
+
"disabled": false,
|
|
102
|
+
"timeout": 60,
|
|
103
|
+
"type": "stdio",
|
|
104
|
+
"command": "uv",
|
|
105
|
+
"args": [
|
|
106
|
+
"tool",
|
|
107
|
+
"run",
|
|
108
|
+
"--from",
|
|
109
|
+
"awslabs.cloudwatch-mcp-server@latest",
|
|
110
|
+
"awslabs.cloudwatch-mcp-server.exe"
|
|
111
|
+
],
|
|
112
|
+
"env": {
|
|
113
|
+
"FASTMCP_LOG_LEVEL": "ERROR",
|
|
114
|
+
"AWS_PROFILE": "your-aws-profile",
|
|
115
|
+
"AWS_REGION": "us-east-1"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
93
122
|
|
|
94
123
|
Please reference [AWS documentation](https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-files.html) to create and manage your credentials profile
|
|
95
124
|
|
|
@@ -168,12 +168,37 @@ class CloudWatchLogsTools:
|
|
|
168
168
|
"""
|
|
169
169
|
poll_start = timer()
|
|
170
170
|
while poll_start + max_timeout > timer():
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
try:
|
|
172
|
+
response = logs_client.get_query_results(queryId=query_id)
|
|
173
|
+
status = response['status']
|
|
174
|
+
|
|
175
|
+
logger.debug(f'Query {query_id} status: {status}')
|
|
176
|
+
|
|
177
|
+
if status in {'Complete', 'Failed', 'Cancelled'}:
|
|
178
|
+
logger.info(f'Query {query_id} finished with status {status}')
|
|
179
|
+
result = self._process_query_results(response, query_id)
|
|
180
|
+
|
|
181
|
+
# Handle case where query completed but returned no results
|
|
182
|
+
if status == 'Complete' and not result.get('results'):
|
|
183
|
+
logger.info(f'Query {query_id} completed but returned no results')
|
|
184
|
+
result['results'] = []
|
|
185
|
+
|
|
186
|
+
return result
|
|
187
|
+
|
|
188
|
+
# Handle unexpected status states
|
|
189
|
+
if status not in {'Scheduled', 'Running'}:
|
|
190
|
+
logger.warning(f'Query {query_id} has unexpected status: {status}')
|
|
191
|
+
return self._process_query_results(response, query_id)
|
|
173
192
|
|
|
174
|
-
|
|
175
|
-
logger.
|
|
176
|
-
|
|
193
|
+
except Exception as e:
|
|
194
|
+
logger.error(f'Error polling for query {query_id} completion: {str(e)}')
|
|
195
|
+
await ctx.error(f'Error during query polling: {str(e)}')
|
|
196
|
+
return {
|
|
197
|
+
'queryId': query_id,
|
|
198
|
+
'status': 'Error',
|
|
199
|
+
'message': f'Error occurred while polling: {str(e)}',
|
|
200
|
+
'results': [],
|
|
201
|
+
}
|
|
177
202
|
|
|
178
203
|
await asyncio.sleep(1)
|
|
179
204
|
|
|
@@ -184,6 +209,7 @@ class CloudWatchLogsTools:
|
|
|
184
209
|
'queryId': query_id,
|
|
185
210
|
'status': 'Polling Timeout',
|
|
186
211
|
'message': msg,
|
|
212
|
+
'results': [],
|
|
187
213
|
}
|
|
188
214
|
|
|
189
215
|
def register(self, mcp):
|
|
@@ -576,8 +602,16 @@ class CloudWatchLogsTools:
|
|
|
576
602
|
|
|
577
603
|
except Exception as e:
|
|
578
604
|
logger.error(f'Error in execute_log_insights_query_tool: {str(e)}')
|
|
579
|
-
|
|
580
|
-
|
|
605
|
+
error_msg = f'Error executing CloudWatch Logs Insights query: {str(e)}'
|
|
606
|
+
await ctx.error(error_msg)
|
|
607
|
+
|
|
608
|
+
# Instead of raising, return a consistent error result
|
|
609
|
+
return {
|
|
610
|
+
'queryId': '',
|
|
611
|
+
'status': 'Error',
|
|
612
|
+
'message': error_msg,
|
|
613
|
+
'results': [],
|
|
614
|
+
}
|
|
581
615
|
|
|
582
616
|
async def get_logs_insight_query_results(
|
|
583
617
|
self,
|
|
@@ -612,11 +646,26 @@ class CloudWatchLogsTools:
|
|
|
612
646
|
|
|
613
647
|
logger.info(f'Retrieved results for query ID {query_id}')
|
|
614
648
|
|
|
615
|
-
|
|
649
|
+
result = self._process_query_results(response, query_id)
|
|
650
|
+
|
|
651
|
+
# Ensure results is always an array, even if empty
|
|
652
|
+
if not result.get('results'):
|
|
653
|
+
result['results'] = []
|
|
654
|
+
|
|
655
|
+
return result
|
|
656
|
+
|
|
616
657
|
except Exception as e:
|
|
617
658
|
logger.error(f'Error in get_query_results_tool: {str(e)}')
|
|
618
|
-
|
|
619
|
-
|
|
659
|
+
error_msg = f'Error retrieving CloudWatch Logs Insights query results: {str(e)}'
|
|
660
|
+
await ctx.error(error_msg)
|
|
661
|
+
|
|
662
|
+
# Return consistent error structure instead of raising
|
|
663
|
+
return {
|
|
664
|
+
'queryId': query_id,
|
|
665
|
+
'status': 'Error',
|
|
666
|
+
'message': error_msg,
|
|
667
|
+
'results': [],
|
|
668
|
+
}
|
|
620
669
|
|
|
621
670
|
async def cancel_logs_insight_query(
|
|
622
671
|
self,
|
|
@@ -185,19 +185,22 @@ class TestErrorHandling:
|
|
|
185
185
|
|
|
186
186
|
tools = CloudWatchLogsTools()
|
|
187
187
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
)
|
|
188
|
+
result = await tools.execute_log_insights_query(
|
|
189
|
+
mock_context,
|
|
190
|
+
log_group_names=['test-group'],
|
|
191
|
+
log_group_identifiers=None,
|
|
192
|
+
start_time='2023-01-01T00:00:00+00:00',
|
|
193
|
+
end_time='2023-01-01T01:00:00+00:00',
|
|
194
|
+
query_string='fields @message',
|
|
195
|
+
limit=10,
|
|
196
|
+
max_timeout=30,
|
|
197
|
+
)
|
|
199
198
|
|
|
200
|
-
|
|
199
|
+
# Verify error response structure instead of exception
|
|
200
|
+
assert result['status'] == 'Error'
|
|
201
|
+
assert result['results'] == []
|
|
202
|
+
assert 'Query API Error' in result['message']
|
|
203
|
+
assert result['queryId'] == ''
|
|
201
204
|
mock_context.error.assert_called_once()
|
|
202
205
|
|
|
203
206
|
@pytest.mark.asyncio
|
|
@@ -212,10 +215,15 @@ class TestErrorHandling:
|
|
|
212
215
|
|
|
213
216
|
tools = CloudWatchLogsTools()
|
|
214
217
|
|
|
215
|
-
|
|
216
|
-
|
|
218
|
+
result = await tools.get_logs_insight_query_results(
|
|
219
|
+
mock_context, query_id='test-query-id'
|
|
220
|
+
)
|
|
217
221
|
|
|
218
|
-
|
|
222
|
+
# Verify error response structure instead of exception
|
|
223
|
+
assert result['status'] == 'Error'
|
|
224
|
+
assert result['results'] == []
|
|
225
|
+
assert 'Query Results API Error' in result['message']
|
|
226
|
+
assert result['queryId'] == 'test-query-id'
|
|
219
227
|
mock_context.error.assert_called_once()
|
|
220
228
|
|
|
221
229
|
@pytest.mark.asyncio
|
|
@@ -296,6 +304,54 @@ class TestErrorHandling:
|
|
|
296
304
|
assert result['queryId'] == 'test-query-id'
|
|
297
305
|
assert result['status'] == 'Cancelled'
|
|
298
306
|
|
|
307
|
+
@pytest.mark.asyncio
|
|
308
|
+
async def test_poll_for_query_completion_unexpected_status(self, mock_context):
|
|
309
|
+
"""Test polling with unexpected query status."""
|
|
310
|
+
with patch(
|
|
311
|
+
'awslabs.cloudwatch_mcp_server.cloudwatch_logs.tools.boto3.Session'
|
|
312
|
+
) as mock_session:
|
|
313
|
+
mock_client = Mock()
|
|
314
|
+
mock_client.get_query_results.return_value = {
|
|
315
|
+
'queryId': 'test-query-id',
|
|
316
|
+
'status': 'UnknownStatus', # Unexpected status
|
|
317
|
+
'results': [],
|
|
318
|
+
}
|
|
319
|
+
mock_session.return_value.client.return_value = mock_client
|
|
320
|
+
tools = CloudWatchLogsTools()
|
|
321
|
+
result = await tools._poll_for_query_completion(
|
|
322
|
+
mock_client, 'test-query-id', 30, mock_context
|
|
323
|
+
)
|
|
324
|
+
assert result['queryId'] == 'test-query-id'
|
|
325
|
+
assert result['status'] == 'UnknownStatus'
|
|
326
|
+
assert result['results'] == []
|
|
327
|
+
|
|
328
|
+
@pytest.mark.asyncio
|
|
329
|
+
async def test_poll_for_query_completion_polling_exception(self, mock_context):
|
|
330
|
+
"""Test polling with exception during get_query_results."""
|
|
331
|
+
with patch(
|
|
332
|
+
'awslabs.cloudwatch_mcp_server.cloudwatch_logs.tools.boto3.Session'
|
|
333
|
+
) as mock_session:
|
|
334
|
+
mock_client = Mock()
|
|
335
|
+
mock_client.get_query_results.side_effect = Exception('Network timeout during polling')
|
|
336
|
+
mock_session.return_value.client.return_value = mock_client
|
|
337
|
+
tools = CloudWatchLogsTools()
|
|
338
|
+
|
|
339
|
+
result = await tools._poll_for_query_completion(
|
|
340
|
+
mock_client, 'test-query-id', 30, mock_context
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
# Verify error response structure
|
|
344
|
+
assert result['queryId'] == 'test-query-id'
|
|
345
|
+
assert result['status'] == 'Error'
|
|
346
|
+
assert 'Network timeout during polling' in result['message']
|
|
347
|
+
assert result['results'] == []
|
|
348
|
+
|
|
349
|
+
# Verify context error was called
|
|
350
|
+
mock_context.error.assert_called_once()
|
|
351
|
+
error_call_args = mock_context.error.call_args[0][0]
|
|
352
|
+
assert 'Error during query polling' in error_call_args
|
|
353
|
+
assert 'Network timeout during polling' in error_call_args
|
|
354
|
+
|
|
299
355
|
|
|
300
356
|
class TestEdgeCases:
|
|
301
357
|
"""Test edge cases and boundary conditions."""
|
|
@@ -308,14 +364,13 @@ class TestEdgeCases:
|
|
|
308
364
|
# Response with minimal fields
|
|
309
365
|
raw_response = {
|
|
310
366
|
'status': 'Complete',
|
|
311
|
-
# Missing queryId,
|
|
367
|
+
# Missing queryId, results
|
|
312
368
|
}
|
|
313
369
|
|
|
314
370
|
processed = tools._process_query_results(raw_response, 'fallback-id')
|
|
315
371
|
|
|
316
372
|
assert processed['queryId'] == 'fallback-id'
|
|
317
373
|
assert processed['status'] == 'Complete'
|
|
318
|
-
assert processed['statistics'] == {}
|
|
319
374
|
assert processed['results'] == []
|
|
320
375
|
|
|
321
376
|
def test_aws_profile_initialization(self):
|
|
@@ -265,17 +265,21 @@ class TestExecuteLogInsightsQuery:
|
|
|
265
265
|
|
|
266
266
|
async def test_invalid_parameters(self, ctx, cloudwatch_tools):
|
|
267
267
|
"""Test invalid parameter handling."""
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
268
|
+
result = await cloudwatch_tools.execute_log_insights_query(
|
|
269
|
+
ctx,
|
|
270
|
+
log_group_names=['/aws/test/group1'],
|
|
271
|
+
log_group_identifiers=['/aws/test/group1'], # Both provided - should fail
|
|
272
|
+
start_time='2023-01-01T00:00:00+00:00',
|
|
273
|
+
end_time='2023-01-01T01:00:00+00:00',
|
|
274
|
+
query_string='fields @timestamp, @message | limit 10',
|
|
275
|
+
limit=10,
|
|
276
|
+
max_timeout=30,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
# Verify error response structure instead of exception
|
|
280
|
+
assert result['status'] == 'Error'
|
|
281
|
+
assert result['results'] == []
|
|
282
|
+
assert 'Error executing CloudWatch Logs Insights query' in result['message']
|
|
279
283
|
|
|
280
284
|
|
|
281
285
|
@pytest.mark.asyncio
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# This file was autogenerated by uv via the following command:
|
|
2
|
+
# echo "uv==0.8.10" > uv-requirements.in
|
|
3
|
+
# uv pip compile --generate-hashes --output-file=uv-requirements.txt --strip-extras --python=3.10 uv-requirements.in
|
|
4
|
+
uv==0.8.10 \
|
|
5
|
+
--hash=sha256:31e4fc37ee94b94c032384a0957ad32ba7dce4ce6c04b4880fd3e31e25e51a82 \
|
|
6
|
+
--hash=sha256:36a5ce708d52388c37043e7335f9eb3fea5a19a56166a2cc6adb365179a1cd77 \
|
|
7
|
+
--hash=sha256:38286d230daad82388469c8dc7a1d2f5dc279c11178319c886d1a88d7938e513 \
|
|
8
|
+
--hash=sha256:3e190cee3bb2b4f574a419eef87ae8e33f713e9cd6f856b83277ece70ad9ca9b \
|
|
9
|
+
--hash=sha256:3fdf89fc40af9902141c39ed943bcfca15664623363335eb032a44f22001e2b4 \
|
|
10
|
+
--hash=sha256:4cc190d403a89e46d13cec83b6f8e8d7d07aaf1e5a996eac9a3f0c2a8cd92537 \
|
|
11
|
+
--hash=sha256:57b71dc79eff25a5419d3fe4a563d3b9397f55d789f685ef27f43f033b31f482 \
|
|
12
|
+
--hash=sha256:86fe044c2be43977566a0d184a487edd7aace2febb757fd95927684b629ef50b \
|
|
13
|
+
--hash=sha256:88df34c32555064fae459cce665757619fd1af7deb2dc393352b15d909d2d131 \
|
|
14
|
+
--hash=sha256:9ad21eeaa4156a1bf5ed85903f80db06e2c02badd3a587ba98d3171517960555 \
|
|
15
|
+
--hash=sha256:a5495b5a6e3111c03cf5e4dbdd598bc8fd1da887e3920d58cd5a2d4c8bc9a473 \
|
|
16
|
+
--hash=sha256:ab072cd3bf2f9dc264659a1ff48ad91a910ac4830bcfe965e2d3f89c86646f46 \
|
|
17
|
+
--hash=sha256:af8a5526b0e331775a264fa0dbccfd53c183cb974f269a208af136d7561f9eb2 \
|
|
18
|
+
--hash=sha256:b00637c63d5dfc9f879281c5c91db2bb909ab1f9ab275dab015e7fb6cac6be5b \
|
|
19
|
+
--hash=sha256:b3ff3c451fcd23ea78356d8c18e802d0e423cbe655273601e3ec039a51b33286 \
|
|
20
|
+
--hash=sha256:c4a493cd4b15b3aef11523531aff96a77a586666a63e842fa437966b7b7ee62d \
|
|
21
|
+
--hash=sha256:defc50bb319be2d58be74a680710cd4b7697e88d5f79974eacd354df95f0b6b0 \
|
|
22
|
+
--hash=sha256:e0a02bcec766eb0862b7082ab746b204add7d9fcaa62322502d159b5a7ccc54a \
|
|
23
|
+
--hash=sha256:eb79a46d8099f563ef58237bf4e9009f876a40145e757ea883a92b24b724d01e
|
|
24
|
+
# via -r uv-requirements.in
|