packages/mock-cloudwatchlogs/src/mock_cloudwatchlogs_mem.ts
import { getRandomSequenceToken } from '@seagull/libraries'
import { Mock } from '@seagull/mock'
import * as AWS from 'aws-sdk'
import * as AWSMock from 'aws-sdk-mock'
import {
DescribeLogStreamsRequest,
DescribeLogStreamsResponse,
} from 'aws-sdk/clients/cloudwatchlogs'
type PutLogRequest = AWS.CloudWatchLogs.PutLogEventsRequest
type PutLogResponse = AWS.CloudWatchLogs.PutLogEventsResponse
type GetLogRequest = AWS.CloudWatchLogs.GetLogEventsRequest
type GetLogResponse = AWS.CloudWatchLogs.GetLogEventsResponse
type LogEvents = AWS.CloudWatchLogs.InputLogEvents
type CreateLogStreamRequest = AWS.CloudWatchLogs.CreateLogStreamRequest
/**
* when activated, redirect all calls from the AWS SDK of S3 to the S3 shim
* implementation, which operates on a local folder instead.
*/
export class CWLMockMem implements Mock {
/**
* this is the place where calls to s3 buckets will be redirected to
*/
storage: {
[logGroupName: string]: { [logStreamName: string]: LogEvents }
} = {}
/**
* redirect S3 interactions to local folder
*/
activate = () => {
AWSMock.mock('CloudWatchLogs', 'putLogEvents', this.putLogEvents)
AWSMock.mock('CloudWatchLogs', 'getLogEvents', this.getLogEvents)
AWSMock.mock('CloudWatchLogs', 'createLogStream', this.createLogStream)
AWSMock.mock(
'CloudWatchLogs',
'describeLogStreams',
this.describeLogStreams
)
return this
}
/**
* restore original CloudWatchLogs behavior
*/
deactivate = () => {
AWSMock.restore('CloudWatchLogs')
return this
}
/**
* resets internal s3 state
*/
reset = () => {
this.storage = {}
}
putLogEvents = (Input: PutLogRequest, cb: any) => {
this.ensureLogGroup(Input.logGroupName)
const existingLogs =
this.storage[Input.logGroupName][Input.logStreamName] || []
this.storage[Input.logGroupName][Input.logStreamName] = existingLogs.concat(
Input.logEvents
)
const result = {
logStreamName: Input.logStreamName,
nextSequenceToken: getRandomSequenceToken(),
}
return this.result(cb, result)
}
getLogEvents = (Input: GetLogRequest, cb: any) => {
this.ensureLogGroup(Input.logGroupName)
const events = this.storage[Input.logGroupName][Input.logStreamName]
const result: GetLogResponse = { events: events || [] }
return this.result(cb, result)
}
createLogStream = (params: CreateLogStreamRequest, cb: any) => {
this.ensureLogGroup(params.logGroupName)
return this.result(cb, null)
}
describeLogStreams = (Input: DescribeLogStreamsRequest, cb: any) => {
this.ensureLogGroup(Input.logGroupName)
const group = this.storage[Input.logGroupName]
const result: DescribeLogStreamsResponse = {}
let streams = Object.keys(group).map(stream => {
return { logStreamName: stream }
})
if (Input.logStreamNamePrefix) {
streams = streams.filter(stream =>
stream.logStreamName.startsWith(Input.logStreamNamePrefix!)
)
}
result.logStreams = streams
return this.result(cb, result)
}
/**
* Decides if a mocked AWS Result object or void (while calling the callback) should be returned
*/
private result<Value>(cb: any, value: Value) {
return cb ? (void cb(null, value) as void) : this.requestObject(value)
}
/**
* Minimal mock for AWS Result
*/
private requestObject<T>(result: T) {
return {
promise: async () => result,
}
}
// little helper to ensure that the "bucket" key exists in [[storage]]
private ensureLogGroup = (name: string) => {
this.storage[name] = this.storage[name] || {}
}
}