refactor origin and behavior indexing

This commit is contained in:
Eetu Tuomala 2018-03-01 07:58:11 +02:00 committed by Philipp Muens
parent 01136970d4
commit d3f54ea62f
2 changed files with 55 additions and 38 deletions

View File

@ -518,4 +518,11 @@ module.exports = {
getLambdaAtEdgeInvokePermissionLogicalId(functionName) {
return `${this.getLambdaLogicalId(functionName)}InvokePermission`;
},
getCloudFrontOriginId(functionName, path) {
let originId = this.getNormalizedFunctionName(functionName);
if (typeof path !== 'undefined') {
originId = `${originId}${path}`;
}
return originId;
},
};

View File

@ -5,7 +5,7 @@ const { URL } = require('url');
const chalk = require('chalk');
// helper function for joining origins and behaviors
const extendDeep = (object, source) => {
const extendDeep = (object, source) =>
_.assignWith(object, source, (a, b) => {
if (_.isArray(a)) {
return _.uniq(a.concat(b));
@ -15,7 +15,7 @@ const extendDeep = (object, source) => {
}
return a;
});
};
class AwsCompileCloudFrontEvents {
constructor(serverless) {
this.serverless = serverless;
@ -44,12 +44,14 @@ class AwsCompileCloudFrontEvents {
this.provider.naming.getCloudFrontDistributionDomainNameLogicalId();
const lambdaAtEdgeFunctions = [];
const origins = [];
const behaviors = [];
const { Resources, Outputs } = this.serverless.service.provider.compiledCloudFormationTemplate;
function createOrigin(functionName, origin, naming) {
const originObj = {
Id: naming.getNormalizedFunctionName(functionName),
};
const originObj = {};
if (typeof origin === 'string') {
const originUrl = new URL(origin);
_.merge(originObj, {
@ -73,6 +75,9 @@ class AwsCompileCloudFrontEvents {
_.merge(originObj, origin);
}
_.merge(originObj, {
Id: naming.getCloudFrontOriginId(functionName, originObj.OriginPath),
});
return originObj;
}
@ -95,9 +100,21 @@ class AwsCompileCloudFrontEvents {
? event.cloudFront.pathPattern
: undefined;
const behavior = {
let origin =
createOrigin(functionName, event.cloudFront.origin, this.provider.naming);
const existingOrigin =
_.find(origins, o => o.OriginPath === origin.OriginPath);
if (typeof existingOrigin === 'undefined') {
origins.push(origin);
} else {
origin = extendDeep(existingOrigin, origin);
}
let behavior = {
ViewerProtocolPolicy: 'allow-all',
TargetOriginId: this.provider.naming.getNormalizedFunctionName(functionName),
TargetOriginId: origin.Id,
ForwardedValues: {
QueryString: false,
},
@ -109,21 +126,36 @@ class AwsCompileCloudFrontEvents {
}],
};
if (typeof pathPattern !== undefined) {
if (typeof pathPattern !== 'undefined') {
_.merge(behavior, { PathPattern: pathPattern });
}
const origin =
createOrigin(functionName, event.cloudFront.origin, this.provider.naming);
const existingBehaviour =
_.find(behaviors, o =>
o.PathPattern === behavior.PathPattern
&& o.TargetOriginId === behavior.TargetOriginId);
lambdaAtEdgeFunctions.push(_.merge({
cloudFront: { origin, behavior } },
if (typeof existingBehaviour === 'undefined') {
behaviors.push(behavior);
} else {
behavior = extendDeep(existingBehaviour, behavior);
}
lambdaAtEdgeFunctions.push(_.merge({},
functionObj, { functionName, lambdaVersionLogicalId }));
}
});
}
});
// sort that first is without PathPattern if available
behaviors.sort((a, b) => {
if (b.PathPattern) {
return -1;
}
return 0;
});
if (lambdaAtEdgeFunctions.length > 0) {
if (this.provider.getRegion() !== 'us-east-1') {
throw new
@ -205,17 +237,7 @@ class AwsCompileCloudFrontEvents {
}
const CacheBehaviors =
lambdaAtEdgeFunctions
.filter(({ cloudFront }) => !!cloudFront.behavior.PathPattern)
.map(({ cloudFront }) => cloudFront.behavior)
.reduce((result, behaviour) => {
const existingBehaviour = _.find(result, { PathPattern: behaviour.PathPattern });
if (typeof existingBehaviour !== 'undefined') {
extendDeep(existingBehaviour, behaviour);
return result;
}
return result.concat(behaviour);
}, []);
behaviors.slice(1);
const CloudFrontDistribution = {
Type: 'AWS::CloudFront::Distribution',
@ -223,25 +245,13 @@ class AwsCompileCloudFrontEvents {
DistributionConfig: {
Comment: `${this.serverless.service.service} ${this.serverless.service.provider.stage}`,
Enabled: true,
DefaultCacheBehavior:
lambdaAtEdgeFunctions
.filter(({ cloudFront }) => !cloudFront.behavior.PathPattern)
.map(({ cloudFront }) => cloudFront.behavior)[0],
Origins: lambdaAtEdgeFunctions
.map(({ cloudFront }) => cloudFront.origin)
.reduce((result, origin) => {
const existingOrigin = _.find(result, { OriginPath: origin.OriginPath });
if (typeof existingOrigin !== 'undefined') {
extendDeep(existingOrigin, origin);
return result;
}
return result.concat(origin);
}, []),
DefaultCacheBehavior: behaviors[0],
Origins: origins,
},
},
};
if (typeof CacheBehaviors !== 'undefined') {
if (CacheBehaviors.length > 0) {
_.merge(CloudFrontDistribution.Properties.DistributionConfig, { CacheBehaviors });
}