Philipp Muens 028c5d714a Formatting
2019-11-05 10:23:35 +01:00

667 lines
19 KiB
JavaScript

'use strict';
const chai = require('chai');
const sandbox = require('sinon');
const AwsProvider = require('../../../../provider/awsProvider');
const AwsCompileCloudFrontEvents = require('./index');
const Serverless = require('../../../../../../Serverless');
chai.use(require('sinon-chai'));
const { expect } = chai;
describe('AwsCompileCloudFrontEvents', () => {
let serverless;
let awsCompileCloudFrontEvents;
let options;
beforeEach(() => {
options = {
stage: 'dev',
region: 'us-east-1',
};
serverless = new Serverless();
serverless.processedInput = {
commands: [],
};
serverless.service.environment = {
vars: {},
stages: {
dev: {
vars: {},
regions: {
'us-east-1': {
vars: {},
},
},
},
},
};
serverless.service.resources = {};
serverless.service.provider.compiledCloudFormationTemplate = {
Resources: {
IamRoleLambdaExecution: {
Properties: {
AssumeRolePolicyDocument: {
Statement: [
{
Effect: 'Allow',
Principal: {
Service: ['lambda.amazonaws.com'],
},
Action: ['sts:AssumeRole'],
},
],
},
Policies: [
{
PolicyDocument: {
Statement: [],
},
},
],
},
},
FirstLambdaVersion: {
Type: 'AWS::Lambda::Version',
DeletionPolicy: 'Retain',
Properties: {
FunctionName: {
Ref: 'FirstLambdaFunction',
},
},
},
},
};
serverless.setProvider('aws', new AwsProvider(serverless, options));
serverless.cli = { log: sandbox.spy() };
awsCompileCloudFrontEvents = new AwsCompileCloudFrontEvents(serverless, options);
});
describe('#constructor()', () => {
it('should set the provider variable to an instance of AwsProvider', () =>
expect(awsCompileCloudFrontEvents.provider).to.be.instanceof(AwsProvider));
it('should use "before:remove:remove" hook to log a message before removing the service', () => {
serverless.processedInput.commands = ['remove'];
serverless.service.functions = {
first: {
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
const awsCompileCloudFrontEventsRemoval = new AwsCompileCloudFrontEvents(serverless, options);
awsCompileCloudFrontEventsRemoval.hooks['before:remove:remove']();
expect(awsCompileCloudFrontEventsRemoval.serverless.cli.log).to.have.been.calledOnce;
expect(awsCompileCloudFrontEventsRemoval.serverless.cli.log.args[0][0]).to.include(
'remove your Lambda@Edge functions'
);
});
});
describe('#logRemoveReminder()', () => {
it('should not log an info message if the users wants to remove the stack without a cloudFront event', () => {
serverless.processedInput.commands = ['remove'];
const awsCompileCloudFrontEventsRemoval = new AwsCompileCloudFrontEvents(serverless, options);
expect(awsCompileCloudFrontEventsRemoval.serverless.cli.log).not.to.have.been.calledOnce;
});
it('should not throw if function has no events', () => {
serverless.processedInput.commands = ['remove'];
serverless.service.functions = {
first: {},
};
expect(() => new AwsCompileCloudFrontEvents(serverless, options)).not.throw(Error);
});
});
describe('#validate()', () => {
it('should throw if memorySize is greater than 128 for viewer-request or viewer-response functions', () => {
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
memorySize: 129,
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
expect(() => {
awsCompileCloudFrontEvents.validate();
}).to.throw(Error, 'greater than 128');
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
memorySize: 129,
events: [
{
cloudFront: {
eventType: 'viewer-response',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
expect(() => {
awsCompileCloudFrontEvents.validate();
}).to.throw(Error, 'greater than 128');
});
it('should throw if timeout is greater than 5 for viewer-request or viewer response functions', () => {
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
timeout: 6,
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
expect(() => {
awsCompileCloudFrontEvents.validate();
}).to.throw(Error, 'greater than 5');
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
timeout: 6,
events: [
{
cloudFront: {
eventType: 'viewer-response',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
expect(() => {
awsCompileCloudFrontEvents.validate();
}).to.throw(Error, 'greater than 5');
});
it('should throw if memorySize is greater than 3008 for origin-request or origin-response functions', () => {
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
memorySize: 3009,
events: [
{
cloudFront: {
eventType: 'origin-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
expect(() => {
awsCompileCloudFrontEvents.validate();
}).to.throw(Error, 'greater than 3008');
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
memorySize: 3009,
events: [
{
cloudFront: {
eventType: 'origin-response',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
expect(() => {
awsCompileCloudFrontEvents.validate();
}).to.throw(Error, 'greater than 3008');
});
it('should throw if timeout is greater than 30 for origin-request or origin response functions', () => {
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
timeout: 31,
events: [
{
cloudFront: {
eventType: 'origin-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
expect(() => {
awsCompileCloudFrontEvents.validate();
}).to.throw(Error, 'greater than 30');
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
timeout: 31,
events: [
{
cloudFront: {
eventType: 'origin-response',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
expect(() => {
awsCompileCloudFrontEvents.validate();
}).to.throw(Error, 'greater than 30');
});
});
describe('#prepareFunctions()', () => {
it('should enable function versioning and set the necessary default configs for functions', () => {
awsCompileCloudFrontEvents.serverless.service.provider.versionFunctions = false;
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
awsCompileCloudFrontEvents.prepareFunctions();
expect(awsCompileCloudFrontEvents.serverless.service.functions).to.eql({
first: {
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
memorySize: 128,
timeout: 5,
versionFunction: true,
},
});
});
it('should retain the memorySize and timeout properties if given', () => {
awsCompileCloudFrontEvents.serverless.service.provider.versionFunctions = false;
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
memorySize: 64,
timeout: 1,
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
awsCompileCloudFrontEvents.prepareFunctions();
expect(awsCompileCloudFrontEvents.serverless.service.functions).to.eql({
first: {
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
memorySize: 64,
timeout: 1,
versionFunction: true,
},
});
});
});
describe('#compileCloudFrontEvents()', () => {
it('should throw an error if cloudFront event type is not an object', () => {
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
events: [
{
cloudFront: 42,
},
],
},
};
expect(() => awsCompileCloudFrontEvents.compileCloudFrontEvents()).to.throw(Error);
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
events: [
{
cloudFront: 'some',
},
],
},
};
expect(() => awsCompileCloudFrontEvents.compileCloudFrontEvents()).to.throw(Error);
});
it('should throw an error if the region is not us-east-1', () => {
options.region = 'eu-central-1';
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
name: 'first',
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources = {
FirstLambdaFunction: {
Type: 'AWS::Lambda::Function',
Properties: {
FunctionName: 'first',
},
},
FirstLambdaVersion: {
Type: 'AWS::Lambda::Version',
Properties: {
FunctionName: { Ref: 'FirstLambdaFunction' },
},
},
IamRoleLambdaExecution: {
Type: 'AWS::IAM::Role',
Properties: {
AssumeRolePolicyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Service: ['lambda.amazonaws.com'],
},
Action: ['sts:AssumeRole'],
},
],
},
Policies: [
{
PolicyName: {
'Fn::Join': ['-', ['dev', 'first', 'lambda']],
},
PolicyDocument: {
Version: '2012-10-17',
Statement: [],
},
},
],
Path: '/',
RoleName: {
'Fn::Join': [
'-',
[
'first',
'dev',
{
Ref: 'AWS::Region',
},
'lambdaRole',
],
],
},
},
},
};
expect(() => awsCompileCloudFrontEvents.compileCloudFrontEvents()).to.throw(
/to the us-east-1 region/
);
});
it('should create corresponding resources when cloudFront events are given', () => {
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
name: 'first',
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
};
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources = {
FirstLambdaFunction: {
Type: 'AWS::Lambda::Function',
Properties: {
FunctionName: 'first',
},
},
FirstLambdaVersion: {
Type: 'AWS::Lambda::Version',
Properties: {
FunctionName: { Ref: 'FirstLambdaFunction' },
},
},
IamRoleLambdaExecution: {
Type: 'AWS::IAM::Role',
Properties: {
AssumeRolePolicyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Service: ['lambda.amazonaws.com'],
},
Action: ['sts:AssumeRole'],
},
],
},
Policies: [
{
PolicyName: {
'Fn::Join': ['-', ['dev', 'first', 'lambda']],
},
PolicyDocument: {
Version: '2012-10-17',
Statement: [],
},
},
],
Path: '/',
RoleName: {
'Fn::Join': [
'-',
[
'first',
'dev',
{
Ref: 'AWS::Region',
},
'lambdaRole',
],
],
},
},
},
};
awsCompileCloudFrontEvents.compileCloudFrontEvents();
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.FirstLambdaFunction.DeletionPolicy
).to.equal('Retain');
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.IamRoleLambdaExecution.Properties.AssumeRolePolicyDocument.Statement[0]
).to.eql({
Effect: 'Allow',
Principal: {
Service: ['lambda.amazonaws.com', 'edgelambda.amazonaws.com'],
},
Action: ['sts:AssumeRole'],
});
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.IamRoleLambdaExecution.Properties.Policies[0].PolicyDocument.Statement[0]
).to.eql({
Effect: 'Allow',
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
Resource: ['arn:aws:logs:*:*:*'],
});
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.CloudFrontDistribution.Type
).to.equal('AWS::CloudFront::Distribution');
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.CloudFrontDistribution.Properties.DistributionConfig.Enabled
).to.equal(true);
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.CloudFrontDistribution.Properties.DistributionConfig.DefaultCacheBehavior
.ViewerProtocolPolicy
).to.equal('allow-all');
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.CloudFrontDistribution.Properties.DistributionConfig.DefaultCacheBehavior
.TargetOriginId
).to.equal('First/files');
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.CloudFrontDistribution.Properties.DistributionConfig.DefaultCacheBehavior
.ForwardedValues
).to.eql({ QueryString: false });
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.CloudFrontDistribution.Properties.DistributionConfig.DefaultCacheBehavior
.LambdaFunctionAssociations[0]
).to.eql({
EventType: 'viewer-request',
LambdaFunctionARN: {
Ref: 'FirstLambdaVersion',
},
});
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.CloudFrontDistribution.Properties.DistributionConfig.Origins[0]
).to.eql({
Id: 'First/files',
DomainName: 'bucketname.s3.amazonaws.com',
OriginPath: '/files',
S3OriginConfig: {},
});
});
it('should create different origins for different domains with the same path', () => {
awsCompileCloudFrontEvents.serverless.service.functions = {
first: {
name: 'first',
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://bucketname.s3.amazonaws.com/files',
},
},
],
},
second: {
name: 'second',
events: [
{
cloudFront: {
eventType: 'viewer-request',
origin: 's3://anotherbucket.s3.amazonaws.com/files',
},
},
],
},
};
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources = {
FirstLambdaFunction: {
Type: 'AWS::Lambda::Function',
Properties: {
FunctionName: 'first',
},
},
SecondLambdaFunction: {
Type: 'AWS::Lambda::Function',
Properties: {
FunctionName: 'second',
},
},
};
awsCompileCloudFrontEvents.compileCloudFrontEvents();
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.CloudFrontDistribution.Properties.DistributionConfig.Origins[0]
).to.eql({
Id: 'First/files',
DomainName: 'bucketname.s3.amazonaws.com',
OriginPath: '/files',
S3OriginConfig: {},
});
expect(
awsCompileCloudFrontEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.CloudFrontDistribution.Properties.DistributionConfig.Origins[1]
).to.eql({
Id: 'Second/files',
DomainName: 'anotherbucket.s3.amazonaws.com',
OriginPath: '/files',
S3OriginConfig: {},
});
});
});
});