Merge pull request #1428 from toshitanian/logs-exceptions
Add logs exceptions
This commit is contained in:
commit
4b21beb754
33
moto/logs/exceptions.py
Normal file
33
moto/logs/exceptions.py
Normal file
@ -0,0 +1,33 @@
|
||||
from __future__ import unicode_literals
|
||||
from moto.core.exceptions import JsonRESTError
|
||||
|
||||
|
||||
class LogsClientError(JsonRESTError):
|
||||
code = 400
|
||||
|
||||
|
||||
class ResourceNotFoundException(LogsClientError):
|
||||
def __init__(self):
|
||||
self.code = 400
|
||||
super(ResourceNotFoundException, self).__init__(
|
||||
"ResourceNotFoundException",
|
||||
"The specified resource does not exist"
|
||||
)
|
||||
|
||||
|
||||
class InvalidParameterException(LogsClientError):
|
||||
def __init__(self, msg=None):
|
||||
self.code = 400
|
||||
super(InvalidParameterException, self).__init__(
|
||||
"InvalidParameterException",
|
||||
msg or "A parameter is specified incorrectly."
|
||||
)
|
||||
|
||||
|
||||
class ResourceAlreadyExistsException(LogsClientError):
|
||||
def __init__(self):
|
||||
self.code = 400
|
||||
super(ResourceAlreadyExistsException, self).__init__(
|
||||
'ResourceAlreadyExistsException',
|
||||
'The specified resource already exists.'
|
||||
)
|
@ -1,6 +1,10 @@
|
||||
from moto.core import BaseBackend
|
||||
import boto.logs
|
||||
from moto.core.utils import unix_time_millis
|
||||
from .exceptions import (
|
||||
ResourceNotFoundException,
|
||||
ResourceAlreadyExistsException
|
||||
)
|
||||
|
||||
|
||||
class LogEvent:
|
||||
@ -49,23 +53,29 @@ class LogStream:
|
||||
self.__class__._log_ids += 1
|
||||
|
||||
def _update(self):
|
||||
self.firstEventTimestamp = min([x.timestamp for x in self.events])
|
||||
self.lastEventTimestamp = max([x.timestamp for x in self.events])
|
||||
# events can be empty when stream is described soon after creation
|
||||
self.firstEventTimestamp = min([x.timestamp for x in self.events]) if self.events else None
|
||||
self.lastEventTimestamp = max([x.timestamp for x in self.events]) if self.events else None
|
||||
|
||||
def to_describe_dict(self):
|
||||
# Compute start and end times
|
||||
self._update()
|
||||
|
||||
return {
|
||||
res = {
|
||||
"arn": self.arn,
|
||||
"creationTime": self.creationTime,
|
||||
"logStreamName": self.logStreamName,
|
||||
"storedBytes": self.storedBytes,
|
||||
}
|
||||
if self.events:
|
||||
rest = {
|
||||
"firstEventTimestamp": self.firstEventTimestamp,
|
||||
"lastEventTimestamp": self.lastEventTimestamp,
|
||||
"lastIngestionTime": self.lastIngestionTime,
|
||||
"logStreamName": self.logStreamName,
|
||||
"storedBytes": self.storedBytes,
|
||||
"uploadSequenceToken": str(self.uploadSequenceToken),
|
||||
}
|
||||
res.update(rest)
|
||||
return res
|
||||
|
||||
def put_log_events(self, log_group_name, log_stream_name, log_events, sequence_token):
|
||||
# TODO: ensure sequence_token
|
||||
@ -126,18 +136,22 @@ class LogGroup:
|
||||
self.streams = dict() # {name: LogStream}
|
||||
|
||||
def create_log_stream(self, log_stream_name):
|
||||
assert log_stream_name not in self.streams
|
||||
if log_stream_name in self.streams:
|
||||
raise ResourceAlreadyExistsException()
|
||||
self.streams[log_stream_name] = LogStream(self.region, self.name, log_stream_name)
|
||||
|
||||
def delete_log_stream(self, log_stream_name):
|
||||
assert log_stream_name in self.streams
|
||||
if log_stream_name not in self.streams:
|
||||
raise ResourceNotFoundException()
|
||||
del self.streams[log_stream_name]
|
||||
|
||||
def describe_log_streams(self, descending, limit, log_group_name, log_stream_name_prefix, next_token, order_by):
|
||||
# responses only logStreamName, creationTime, arn, storedBytes when no events are stored.
|
||||
|
||||
log_streams = [(name, stream.to_describe_dict()) for name, stream in self.streams.items() if name.startswith(log_stream_name_prefix)]
|
||||
|
||||
def sorter(item):
|
||||
return item[0] if order_by == 'logStreamName' else item[1]['lastEventTimestamp']
|
||||
return item[0] if order_by == 'logStreamName' else item[1].get('lastEventTimestamp', 0)
|
||||
|
||||
if next_token is None:
|
||||
next_token = 0
|
||||
@ -151,18 +165,18 @@ class LogGroup:
|
||||
return log_streams_page, new_token
|
||||
|
||||
def put_log_events(self, log_group_name, log_stream_name, log_events, sequence_token):
|
||||
assert log_stream_name in self.streams
|
||||
if log_stream_name not in self.streams:
|
||||
raise ResourceNotFoundException()
|
||||
stream = self.streams[log_stream_name]
|
||||
return stream.put_log_events(log_group_name, log_stream_name, log_events, sequence_token)
|
||||
|
||||
def get_log_events(self, log_group_name, log_stream_name, start_time, end_time, limit, next_token, start_from_head):
|
||||
assert log_stream_name in self.streams
|
||||
if log_stream_name not in self.streams:
|
||||
raise ResourceNotFoundException()
|
||||
stream = self.streams[log_stream_name]
|
||||
return stream.get_log_events(log_group_name, log_stream_name, start_time, end_time, limit, next_token, start_from_head)
|
||||
|
||||
def filter_log_events(self, log_group_name, log_stream_names, start_time, end_time, limit, next_token, filter_pattern, interleaved):
|
||||
assert not filter_pattern # TODO: impl
|
||||
|
||||
streams = [stream for name, stream in self.streams.items() if not log_stream_names or name in log_stream_names]
|
||||
|
||||
events = []
|
||||
@ -195,7 +209,8 @@ class LogsBackend(BaseBackend):
|
||||
self.__init__(region_name)
|
||||
|
||||
def create_log_group(self, log_group_name, tags):
|
||||
assert log_group_name not in self.groups
|
||||
if log_group_name in self.groups:
|
||||
raise ResourceAlreadyExistsException()
|
||||
self.groups[log_group_name] = LogGroup(self.region_name, log_group_name, tags)
|
||||
|
||||
def ensure_log_group(self, log_group_name, tags):
|
||||
@ -204,37 +219,44 @@ class LogsBackend(BaseBackend):
|
||||
self.groups[log_group_name] = LogGroup(self.region_name, log_group_name, tags)
|
||||
|
||||
def delete_log_group(self, log_group_name):
|
||||
assert log_group_name in self.groups
|
||||
if log_group_name not in self.groups:
|
||||
raise ResourceNotFoundException()
|
||||
del self.groups[log_group_name]
|
||||
|
||||
def create_log_stream(self, log_group_name, log_stream_name):
|
||||
assert log_group_name in self.groups
|
||||
if log_group_name not in self.groups:
|
||||
raise ResourceNotFoundException()
|
||||
log_group = self.groups[log_group_name]
|
||||
return log_group.create_log_stream(log_stream_name)
|
||||
|
||||
def delete_log_stream(self, log_group_name, log_stream_name):
|
||||
assert log_group_name in self.groups
|
||||
if log_group_name not in self.groups:
|
||||
raise ResourceNotFoundException()
|
||||
log_group = self.groups[log_group_name]
|
||||
return log_group.delete_log_stream(log_stream_name)
|
||||
|
||||
def describe_log_streams(self, descending, limit, log_group_name, log_stream_name_prefix, next_token, order_by):
|
||||
assert log_group_name in self.groups
|
||||
if log_group_name not in self.groups:
|
||||
raise ResourceNotFoundException()
|
||||
log_group = self.groups[log_group_name]
|
||||
return log_group.describe_log_streams(descending, limit, log_group_name, log_stream_name_prefix, next_token, order_by)
|
||||
|
||||
def put_log_events(self, log_group_name, log_stream_name, log_events, sequence_token):
|
||||
# TODO: add support for sequence_tokens
|
||||
assert log_group_name in self.groups
|
||||
if log_group_name not in self.groups:
|
||||
raise ResourceNotFoundException()
|
||||
log_group = self.groups[log_group_name]
|
||||
return log_group.put_log_events(log_group_name, log_stream_name, log_events, sequence_token)
|
||||
|
||||
def get_log_events(self, log_group_name, log_stream_name, start_time, end_time, limit, next_token, start_from_head):
|
||||
assert log_group_name in self.groups
|
||||
if log_group_name not in self.groups:
|
||||
raise ResourceNotFoundException()
|
||||
log_group = self.groups[log_group_name]
|
||||
return log_group.get_log_events(log_group_name, log_stream_name, start_time, end_time, limit, next_token, start_from_head)
|
||||
|
||||
def filter_log_events(self, log_group_name, log_stream_names, start_time, end_time, limit, next_token, filter_pattern, interleaved):
|
||||
assert log_group_name in self.groups
|
||||
if log_group_name not in self.groups:
|
||||
raise ResourceNotFoundException()
|
||||
log_group = self.groups[log_group_name]
|
||||
return log_group.filter_log_events(log_group_name, log_stream_names, start_time, end_time, limit, next_token, filter_pattern, interleaved)
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
import boto3
|
||||
import sure # noqa
|
||||
from botocore.exceptions import ClientError
|
||||
|
||||
from moto import mock_logs, settings
|
||||
from nose.tools import assert_raises
|
||||
|
||||
_logs_region = 'us-east-1' if settings.TEST_SERVER_MODE else 'us-west-2'
|
||||
|
||||
@ -12,3 +14,48 @@ def test_log_group_create():
|
||||
log_group_name = 'dummy'
|
||||
response = conn.create_log_group(logGroupName=log_group_name)
|
||||
response = conn.delete_log_group(logGroupName=log_group_name)
|
||||
|
||||
|
||||
@mock_logs
|
||||
def test_exceptions():
|
||||
conn = boto3.client('logs', 'us-west-2')
|
||||
log_group_name = 'dummy'
|
||||
log_stream_name = 'dummp-stream'
|
||||
conn.create_log_group(logGroupName=log_group_name)
|
||||
with assert_raises(ClientError):
|
||||
conn.create_log_group(logGroupName=log_group_name)
|
||||
|
||||
# descrine_log_groups is not implemented yet
|
||||
|
||||
conn.create_log_stream(
|
||||
logGroupName=log_group_name,
|
||||
logStreamName=log_stream_name
|
||||
)
|
||||
with assert_raises(ClientError):
|
||||
conn.create_log_stream(
|
||||
logGroupName=log_group_name,
|
||||
logStreamName=log_stream_name
|
||||
)
|
||||
|
||||
conn.put_log_events(
|
||||
logGroupName=log_group_name,
|
||||
logStreamName=log_stream_name,
|
||||
logEvents=[
|
||||
{
|
||||
'timestamp': 0,
|
||||
'message': 'line'
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
with assert_raises(ClientError):
|
||||
conn.put_log_events(
|
||||
logGroupName=log_group_name,
|
||||
logStreamName="invalid-stream",
|
||||
logEvents=[
|
||||
{
|
||||
'timestamp': 0,
|
||||
'message': 'line'
|
||||
},
|
||||
],
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user