New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AWS: Consolidates Lambda::Permission objects for cloudwatchLog events #5531

Merged
merged 14 commits into from Jan 21, 2019
Merged
Diff settings

Always

Just for now

Copy path View file
@@ -321,9 +321,9 @@ module.exports = {
return `${this.getNormalizedFunctionName(functionName)}LambdaPermissionAlexaSmartHome${ return `${this.getNormalizedFunctionName(functionName)}LambdaPermissionAlexaSmartHome${
alexaSmartHomeIndex}`; alexaSmartHomeIndex}`;
}, },
getLambdaCloudWatchLogPermissionLogicalId(functionName, logsIndex) { getLambdaCloudWatchLogPermissionLogicalId(functionName) {
return `${this.getNormalizedFunctionName(functionName) return `${this.getNormalizedFunctionName(functionName)
}LambdaPermissionLogsSubscriptionFilterCloudWatchLog${logsIndex}`; }LambdaPermissionLogsSubscriptionFilterCloudWatchLog`;
}, },
getLambdaCognitoUserPoolPermissionLogicalId(functionName, poolId, triggerSource) { getLambdaCognitoUserPoolPermissionLogicalId(functionName, poolId, triggerSource) {
return `${this return `${this
@@ -508,8 +508,8 @@ describe('#naming()', () => {
describe('#getLambdaCloudWatchLogPermissionLogicalId()', () => { describe('#getLambdaCloudWatchLogPermissionLogicalId()', () => {
it('should normalize the function name and add the standard suffix including event index', it('should normalize the function name and add the standard suffix including event index',
() => { () => {
expect(sdk.naming.getLambdaCloudWatchLogPermissionLogicalId('functionName', 0)) expect(sdk.naming.getLambdaCloudWatchLogPermissionLogicalId('functionName'))
.to.equal('FunctionNameLambdaPermissionLogsSubscriptionFilterCloudWatchLog0'); .to.equal('FunctionNameLambdaPermissionLogsSubscriptionFilterCloudWatchLog');
}); });
}); });


@@ -20,6 +20,8 @@ class AwsCompileCloudWatchLogEvents {
let cloudWatchLogNumberInFunction = 0; let cloudWatchLogNumberInFunction = 0;


if (functionObj.events) { if (functionObj.events) {
const logGroupNamesThisFunction = [];

functionObj.events.forEach(event => { functionObj.events.forEach(event => {
if (event.cloudwatchLog) { if (event.cloudwatchLog) {
cloudWatchLogNumberInFunction++; cloudWatchLogNumberInFunction++;
@@ -69,14 +71,14 @@ class AwsCompileCloudWatchLogEvents {
.Error(errorMessage); .Error(errorMessage);
} }
logGroupNames.push(LogGroupName); logGroupNames.push(LogGroupName);
logGroupNamesThisFunction.push(LogGroupName);


const lambdaLogicalId = this.provider.naming const lambdaLogicalId = this.provider.naming
.getLambdaLogicalId(functionName); .getLambdaLogicalId(functionName);
const cloudWatchLogLogicalId = this.provider.naming const cloudWatchLogLogicalId = this.provider.naming
.getCloudWatchLogLogicalId(functionName, cloudWatchLogNumberInFunction); .getCloudWatchLogLogicalId(functionName, cloudWatchLogNumberInFunction);
const lambdaPermissionLogicalId = this.provider.naming const lambdaPermissionLogicalId = this.provider.naming
.getLambdaCloudWatchLogPermissionLogicalId(functionName, .getLambdaCloudWatchLogPermissionLogicalId(functionName);
cloudWatchLogNumberInFunction);


// unescape quotes once when the first quote is detected escaped // unescape quotes once when the first quote is detected escaped
const idxFirstSlash = FilterPattern.indexOf('\\'); const idxFirstSlash = FilterPattern.indexOf('\\');
@@ -97,6 +99,8 @@ class AwsCompileCloudWatchLogEvents {
} }
`; `;


const commonSuffixOfLogGroupName = this.longestCommonSuffix(logGroupNamesThisFunction);

const permissionTemplate = ` const permissionTemplate = `
{ {
"Type": "AWS::Lambda::Permission", "Type": "AWS::Lambda::Permission",
@@ -121,7 +125,7 @@ class AwsCompileCloudWatchLogEvents {
":", ":",
{ "Ref": "AWS::AccountId" }, { "Ref": "AWS::AccountId" },
":log-group:", ":log-group:",
"${LogGroupName}", "${commonSuffixOfLogGroupName}",
":*" ":*"
] ] ] ]
} }
@@ -144,6 +148,19 @@ class AwsCompileCloudWatchLogEvents {
} }
}); });
} }

longestCommonSuffix(logGroupNames) {
const first = logGroupNames[0];
const longestCommon = logGroupNames.reduce((last, current) => {
for (let i = 0; i < last.length; i++) {
if (last[i] !== current[i]) {
return last.substring(0, i);
}
}
return last;
}, first);
return longestCommon + ((longestCommon === first) ? '' : '*');
}
} }


module.exports = AwsCompileCloudWatchLogEvents; module.exports = AwsCompileCloudWatchLogEvents;
@@ -108,11 +108,7 @@ describe('AwsCompileCloudWatchLogEvents', () => {
).to.equal(''); ).to.equal('');
expect(awsCompileCloudWatchLogEvents.serverless.service expect(awsCompileCloudWatchLogEvents.serverless.service
.provider.compiledCloudFormationTemplate.Resources .provider.compiledCloudFormationTemplate.Resources
.FirstLambdaPermissionLogsSubscriptionFilterCloudWatchLog1.Type .FirstLambdaPermissionLogsSubscriptionFilterCloudWatchLog.Type
).to.equal('AWS::Lambda::Permission');
expect(awsCompileCloudWatchLogEvents.serverless.service
.provider.compiledCloudFormationTemplate.Resources
.FirstLambdaPermissionLogsSubscriptionFilterCloudWatchLog2.Type
).to.equal('AWS::Lambda::Permission'); ).to.equal('AWS::Lambda::Permission');
}); });


@@ -278,14 +274,37 @@ describe('AwsCompileCloudWatchLogEvents', () => {
).to.equal(''); ).to.equal('');
expect(awsCompileCloudWatchLogEvents.serverless.service expect(awsCompileCloudWatchLogEvents.serverless.service
.provider.compiledCloudFormationTemplate.Resources .provider.compiledCloudFormationTemplate.Resources
.FirstLambdaPermissionLogsSubscriptionFilterCloudWatchLog1.Type .FirstLambdaPermissionLogsSubscriptionFilterCloudWatchLog.Type
).to.equal('AWS::Lambda::Permission');
expect(awsCompileCloudWatchLogEvents.serverless.service
.provider.compiledCloudFormationTemplate.Resources
.FirstLambdaPermissionLogsSubscriptionFilterCloudWatchLog2.Type
).to.equal('AWS::Lambda::Permission'); ).to.equal('AWS::Lambda::Permission');
}); });


it('should create a longest-common suffix of logGroup to minimize scope', () => {
expect(awsCompileCloudWatchLogEvents
.longestCommonSuffix(['/aws/lambda/hello1']))
.to.equal('/aws/lambda/hello1');
expect(awsCompileCloudWatchLogEvents
.longestCommonSuffix(['/aws/lambda/hello1', '/aws/lambda/hello2']))
.to.equal('/aws/lambda/hello*');
expect(awsCompileCloudWatchLogEvents
.longestCommonSuffix(['/aws/lambda/hello1', '/aws/lambda/hot']))
.to.equal('/aws/lambda/h*');
expect(awsCompileCloudWatchLogEvents
.longestCommonSuffix(['/aws/lambda/hello1', '/aws/lambda/tweet']))
.to.equal('/aws/lambda/*');
expect(awsCompileCloudWatchLogEvents
.longestCommonSuffix(['/aws/lambda/hello1', '/aws/lex/log1', '/aws/lightsail/log1']))
.to.equal('/aws/l*');
expect(awsCompileCloudWatchLogEvents
.longestCommonSuffix(['/aws/lambda/hello1', '/aws/batch/log1']))
.to.equal('/aws/*');
expect(awsCompileCloudWatchLogEvents
.longestCommonSuffix(['/aws/*', '/aws/lambda/hello']))
.to.equal('/aws/*');
expect(awsCompileCloudWatchLogEvents
.longestCommonSuffix(['/aws/lambda/*', '/aws/lambda/hello']))
.to.equal('/aws/lambda/*');
});

it('should throw an error if "logGroup" is duplicated in one CloudFormation stack', () => { it('should throw an error if "logGroup" is duplicated in one CloudFormation stack', () => {
awsCompileCloudWatchLogEvents.serverless.service.functions = { awsCompileCloudWatchLogEvents.serverless.service.functions = {
first: { first: {
ProTip! Use n and p to navigate between commits in a pull request.