Skip to content

Commit

Permalink
feat(Config Schema): Schema for AWS cloudwatch event (#8230)
Browse files Browse the repository at this point in the history
  • Loading branch information
thewizarodofoz committed Sep 15, 2020
1 parent 0c78259 commit 3730fd4
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 180 deletions.
106 changes: 49 additions & 57 deletions lib/plugins/aws/package/compile/events/cloudWatchEvent/index.js
Expand Up @@ -11,9 +11,37 @@ class AwsCompileCloudWatchEventEvents {
'package:compileEvents': this.compileCloudWatchEventEvents.bind(this),
};

// TODO: Complete schema, see https://github.com/serverless/serverless/issues/8026
this.serverless.configSchemaHandler.defineFunctionEvent('aws', 'cloudwatchEvent', {
type: 'object',
properties: {
event: { type: 'object' },
input: {
oneOf: [{ type: 'string', maxLength: 8192 }, { type: 'object' }],
},
inputPath: { type: 'string', minLength: 1, maxLength: 256 },
inputTransformer: {
type: 'object',
properties: {
inputPathsMap: {
type: 'object',
additionalProperties: { type: 'string', minLength: 1 },
},
inputTemplate: { type: 'string', minLength: 1, maxLength: 8192 },
},
required: ['inputTemplate'],
additionalProperties: false,
},
description: { type: 'string', maxLength: 512 },
name: { type: 'string', pattern: '[a-zA-Z0-9-_.]+', minLength: 1, maxLength: 64 },
enabled: { type: 'boolean' },
},
oneOf: [
{ required: ['input'] },
{ required: ['inputPath'] },
{ required: ['inputTransformer'] },
{ required: [] },
],
additionalProperties: false,
});
}

Expand All @@ -26,60 +54,30 @@ class AwsCompileCloudWatchEventEvents {
functionObj.events.forEach(event => {
if (event.cloudwatchEvent) {
cloudWatchEventNumberInFunction++;
let EventPattern;
let State;
let Input;
let InputPath;
let InputTransformer;
let Description;
let Name;

if (typeof event.cloudwatchEvent === 'object') {
if (!event.cloudwatchEvent.event) {
const errorMessage = [
`Missing "event" property for cloudwatch event in function ${functionName}`,
' Please check the docs for more info.',
].join('');
throw new this.serverless.classes.Error(errorMessage);
}

EventPattern = JSON.stringify(event.cloudwatchEvent.event);
State = 'ENABLED';
if (event.cloudwatchEvent.enabled === false) {
State = 'DISABLED';
}
Input = event.cloudwatchEvent.input;
InputPath = event.cloudwatchEvent.inputPath;
InputTransformer = event.cloudwatchEvent.inputTransformer;
Description = event.cloudwatchEvent.description;
Name = event.cloudwatchEvent.name;

const inputOptions = [Input, InputPath, InputTransformer].filter(i => i);
if (inputOptions.length > 1) {
const errorMessage = [
'You can only set one of input, inputPath, or inputTransformer ',
'properties at the same time for cloudwatch events. ',
'Please check the AWS docs for more info',
].join('');
throw new this.serverless.classes.Error(errorMessage);
}

if (Input && typeof Input === 'object') {
Input = JSON.stringify(Input);
}
if (Input && typeof Input === 'string') {
// escape quotes to favor JSON.parse
Input = Input.replace(/\"/g, '\\"'); // eslint-disable-line
}
if (InputTransformer) {
InputTransformer = this.formatInputTransformer(InputTransformer);
}
} else {
const errorMessage = [
`CloudWatch event of function "${functionName}" is not an object`,
' Please check the docs for more info.',
].join('');
throw new this.serverless.classes.Error(errorMessage);
const EventPattern = JSON.stringify(event.cloudwatchEvent.event);
State = 'ENABLED';
if (event.cloudwatchEvent.enabled === false) {
State = 'DISABLED';
}
const Name = event.cloudwatchEvent.name;
const InputPath = event.cloudwatchEvent.inputPath;
const Description = event.cloudwatchEvent.description;
Input = event.cloudwatchEvent.input;
InputTransformer = event.cloudwatchEvent.inputTransformer;

if (Input && typeof Input === 'object') {
Input = JSON.stringify(Input);
}
if (Input && typeof Input === 'string') {
// escape quotes to favor JSON.parse
Input = Input.replace(/\"/g, '\\"'); // eslint-disable-line
}
if (InputTransformer) {
InputTransformer = this.formatInputTransformer(InputTransformer);
}

const lambdaLogicalId = this.provider.naming.getLambdaLogicalId(functionName);
Expand Down Expand Up @@ -144,12 +142,6 @@ class AwsCompileCloudWatchEventEvents {
}

formatInputTransformer(inputTransformer) {
if (!inputTransformer.inputTemplate) {
throw new this.serverless.classes.Error(
'The inputTemplate key is required when specifying an ' +
'inputTransformer for a cloudwatchEvent event'
);
}
const cfmOutput = {
// InputTemplate is required
InputTemplate: inputTransformer.inputTemplate,
Expand Down
123 changes: 0 additions & 123 deletions lib/plugins/aws/package/compile/events/cloudWatchEvent/index.test.js
Expand Up @@ -23,48 +23,6 @@ describe('awsCompileCloudWatchEventEvents', () => {
});

describe('#compileCloudWatchEventEvents()', () => {
it('should throw an error if cloudwatch event type is not an object', () => {
awsCompileCloudWatchEventEvents.serverless.service.functions = {
first: {
events: [
{
cloudwatchEvent: 42,
},
],
},
};

expect(() => awsCompileCloudWatchEventEvents.compileCloudWatchEventEvents()).to.throw(Error);

awsCompileCloudWatchEventEvents.serverless.service.functions = {
first: {
events: [
{
cloudwatchEvent: '42',
},
],
},
};

expect(() => awsCompileCloudWatchEventEvents.compileCloudWatchEventEvents()).to.throw(Error);
});

it('should throw an error if the "event" property is not given', () => {
awsCompileCloudWatchEventEvents.serverless.service.functions = {
first: {
events: [
{
cloudwatchEvent: {
event: null,
},
},
],
},
};

expect(() => awsCompileCloudWatchEventEvents.compileCloudWatchEventEvents()).to.throw(Error);
});

it('should create corresponding resources when cloudwatch events are given', () => {
awsCompileCloudWatchEventEvents.serverless.service.functions = {
first: {
Expand Down Expand Up @@ -340,87 +298,6 @@ describe('awsCompileCloudWatchEventEvents', () => {
).to.equal('{"key":"value"}');
});

it('should throw an error when both Input and InputPath are set', () => {
awsCompileCloudWatchEventEvents.serverless.service.functions = {
first: {
events: [
{
cloudwatchEvent: {
event: {
'source': ['aws.ec2'],
'detail-type': ['EC2 Instance State-change Notification'],
'detail': { state: ['pending'] },
},
enabled: false,
input: {
key: 'value',
},
inputPath: '$.stageVariables',
},
},
],
},
};

expect(() => awsCompileCloudWatchEventEvents.compileCloudWatchEventEvents()).to.throw(Error);
});

it('should throw an error when both Input and InputTransformer are set', () => {
awsCompileCloudWatchEventEvents.serverless.service.functions = {
first: {
events: [
{
cloudwatchEvent: {
event: {
'source': ['aws.ec2'],
'detail-type': ['EC2 Instance State-change Notification'],
'detail': { state: ['pending'] },
},
enabled: false,
input: {
key: 'value',
},
inputTransformer: {
inputPathsMap: {
eventTime: '$.time',
},
inputTemplate: '{"time": <eventTime>, "key1": "value1"}',
},
},
},
],
},
};

expect(() => awsCompileCloudWatchEventEvents.compileCloudWatchEventEvents()).to.throw(Error);
});

it('should throw an error when inputTransformer does not have inputTemplate', () => {
awsCompileCloudWatchEventEvents.serverless.service.functions = {
first: {
events: [
{
cloudwatchEvent: {
event: {
'source': ['aws.ec2'],
'detail-type': ['EC2 Instance State-change Notification'],
'detail': { state: ['pending'] },
},
enabled: false,
inputTransformer: {
inputPathsMap: {
eventTime: '$.time',
},
},
},
},
],
},
};

expect(() => awsCompileCloudWatchEventEvents.compileCloudWatchEventEvents()).to.throw(Error);
});

it('should respect variables if multi-line variables is given', () => {
awsCompileCloudWatchEventEvents.serverless.service.functions = {
first: {
Expand Down

0 comments on commit 3730fd4

Please sign in to comment.