diff --git a/packages/@aws-cdk/aws-lambda/lib/log-retention-provider/index.ts b/packages/@aws-cdk/aws-lambda/lib/log-retention-provider/index.ts index 4af3302d74374..56d71ea19cd68 100644 --- a/packages/@aws-cdk/aws-lambda/lib/log-retention-provider/index.ts +++ b/packages/@aws-cdk/aws-lambda/lib/log-retention-provider/index.ts @@ -49,9 +49,16 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent // group for this function should already exist at this stage because we // already logged the event but due to the async nature of Lambda logging // there could be a race condition. So we also try to create the log group - // of this function first. - await createLogGroupSafe(`/aws/lambda/${context.functionName}`); - await setRetentionPolicy(`/aws/lambda/${context.functionName}`, 1); + // of this function first. If multiple LogRetention constructs are present + // in the stack, they will try to act on this function's log group at the + // same time. This can sometime result in an OperationAbortedException. To + // avoid this and because this operation is not critical we catch all errors. + try { + await createLogGroupSafe(`/aws/lambda/${context.functionName}`); + await setRetentionPolicy(`/aws/lambda/${context.functionName}`, 1); + } catch (e) { + console.log(e); + } } } diff --git a/packages/@aws-cdk/aws-lambda/test/test.log-retention-provider.ts b/packages/@aws-cdk/aws-lambda/test/test.log-retention-provider.ts index 86ced0d4226b7..385f95f1dd613 100644 --- a/packages/@aws-cdk/aws-lambda/test/test.log-retention-provider.ts +++ b/packages/@aws-cdk/aws-lambda/test/test.log-retention-provider.ts @@ -1,3 +1,4 @@ +import AWSSDK = require('aws-sdk'); import AWS = require('aws-sdk-mock'); import nock = require('nock'); import { Test } from 'nodeunit'; @@ -227,4 +228,38 @@ export = { test.done(); }, + + async 'does not fail when operations on provider log group fail'(test: Test) { + const createLogGroupFake = (params: AWSSDK.CloudWatchLogs.CreateLogGroupRequest) => { + if (params.logGroupName === '/aws/lambda/provider') { + return Promise.reject(new Error('OperationAbortedException')); + } + return Promise.resolve({}); + }; + + const putRetentionPolicyFake = sinon.fake.resolves({}); + const deleteRetentionPolicyFake = sinon.fake.resolves({}); + + AWS.mock('CloudWatchLogs', 'createLogGroup', createLogGroupFake); + AWS.mock('CloudWatchLogs', 'putRetentionPolicy', putRetentionPolicyFake); + AWS.mock('CloudWatchLogs', 'deleteRetentionPolicy', deleteRetentionPolicyFake); + + const event = { + ...eventCommon, + RequestType: 'Create', + ResourceProperties: { + ServiceToken: 'token', + RetentionInDays: '30', + LogGroupName: 'group' + } + }; + + const request = createRequest('SUCCESS'); + + await provider.handler(event as AWSLambda.CloudFormationCustomResourceCreateEvent, context); + + test.equal(request.isDone(), true); + + test.done(); + } };