diff --git a/moto/logs/models.py b/moto/logs/models.py index 807988ffe..9025e8d82 100644 --- a/moto/logs/models.py +++ b/moto/logs/models.py @@ -8,6 +8,15 @@ from .exceptions import ( InvalidParameterException, LimitExceededException, ) +import uuid + + +class LogQuery(BaseModel): + def __init__(self, id, start_time, end_time, query): + self.id = id + self.start_time = start_time + self.end_time = end_time + self.query = query class LogEvent(BaseModel): @@ -500,6 +509,7 @@ class LogsBackend(BaseBackend): def __init__(self, region_name): self.region_name = region_name self.groups = dict() # { logGroupName: LogGroup} + self.queries = dict() def reset(self): region_name = self.region_name @@ -725,6 +735,16 @@ class LogsBackend(BaseBackend): log_group.delete_subscription_filter(filter_name) + def start_query(self, log_group_names, start_time, end_time, query_string): + + for log_group_name in log_group_names: + if log_group_name not in self.groups: + raise ResourceNotFoundException() + + query_id = uuid.uuid1() + self.queries[query_id] = LogQuery(query_id, start_time, end_time, query_string) + return query_id + logs_backends = {} for region in Session().get_available_regions("logs"): diff --git a/moto/logs/responses.py b/moto/logs/responses.py index 715c4b5c1..d2cab68c6 100644 --- a/moto/logs/responses.py +++ b/moto/logs/responses.py @@ -1,6 +1,7 @@ from moto.core.responses import BaseResponse from .models import logs_backends import json +from .exceptions import InvalidParameterException # See http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/Welcome.html @@ -211,3 +212,22 @@ class LogsResponse(BaseResponse): self.logs_backend.delete_subscription_filter(log_group_name, filter_name) return "" + + def start_query(self): + log_group_name = self._get_param("logGroupName") + log_group_names = self._get_param("logGroupNames") + start_time = self._get_param("startTime") + end_time = self._get_param("endTime") + query_string = self._get_param("queryString") + + if log_group_name and log_group_names: + raise InvalidParameterException() + + if log_group_name: + log_group_names = [log_group_name] + + query_id = self.logs_backend.start_query( + log_group_names, start_time, end_time, query_string + ) + + return json.dumps({"queryId": "{0}".format(query_id)}) diff --git a/tests/test_logs/test_logs.py b/tests/test_logs/test_logs.py index 8fce654ab..79dcb2d3e 100644 --- a/tests/test_logs/test_logs.py +++ b/tests/test_logs/test_logs.py @@ -611,3 +611,35 @@ def test_describe_log_streams_paging(): ) resp["logStreams"].should.have.length_of(0) resp.should_not.have.key("nextToken") + + +@mock_logs +def test_start_query(): + client = boto3.client("logs", "us-east-1") + + log_group_name = "/aws/codebuild/lowercase-dev" + client.create_log_group(logGroupName=log_group_name) + + response = client.start_query( + logGroupName=log_group_name, + startTime=int(time.time()), + endTime=int(time.time()) + 300, + queryString="test", + ) + + assert "queryId" in response + + with pytest.raises(ClientError) as e: + client.start_query( + logGroupName="/aws/codebuild/lowercase-dev-invalid", + startTime=int(time.time()), + endTime=int(time.time()) + 300, + queryString="test", + ) + + # then + ex = e.value + ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") + ex.response["Error"]["Message"].should.equal( + "The specified log group does not exist" + )