From 53fcc4ef85eb08c33db48088993223a3d7d5c017 Mon Sep 17 00:00:00 2001 From: Jaap van Blaaderen Date: Thu, 28 May 2020 16:22:02 +0200 Subject: [PATCH 1/8] fix(lambda): increase retry count for creating cloudwatch log groups This prevents throttling issues on stacks with a lot of Lambdas. fixes #8257 --- .../lib/log-retention-provider/index.ts | 7 +++++-- .../test/integ.log-retention.expected.json | 18 +++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) 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 38ac1fb709d8b..5e4b3e38a34d8 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 @@ -3,6 +3,9 @@ // eslint-disable-next-line import/no-extraneous-dependencies import * as AWS from 'aws-sdk'; +// Ensure we do not run into throttling issues when deploying stack(s) with a lot of Lambdas. +const retryOptions = { maxRetries: 6, retryDelayOptions: { base: 300 }}; + /** * Creates a log group and doesn't throw if it exists. * @@ -10,7 +13,7 @@ import * as AWS from 'aws-sdk'; */ async function createLogGroupSafe(logGroupName: string) { try { // Try to create the log group - const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28' }); + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...retryOptions}); await cloudwatchlogs.createLogGroup({ logGroupName }).promise(); } catch (e) { if (e.code !== 'ResourceAlreadyExistsException') { @@ -26,7 +29,7 @@ async function createLogGroupSafe(logGroupName: string) { * @param retentionInDays the number of days to retain the log events in the specified log group. */ async function setRetentionPolicy(logGroupName: string, retentionInDays?: number) { - const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28' }); + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...retryOptions}); if (!retentionInDays) { await cloudwatchlogs.deleteRetentionPolicy({ logGroupName }).promise(); } else { diff --git a/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json b/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json index 4ca25f4d0ba99..ff3bb7285e69f 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json @@ -133,7 +133,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3Bucket7046E6CE" + "Ref": "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3BucketD782C750" }, "S3Key": { "Fn::Join": [ @@ -146,7 +146,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3VersionKey3194A583" + "Ref": "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3VersionKeyB87E9196" } ] } @@ -159,7 +159,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3VersionKey3194A583" + "Ref": "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3VersionKeyB87E9196" } ] } @@ -331,17 +331,17 @@ } }, "Parameters": { - "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3Bucket7046E6CE": { + "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3BucketD782C750": { "Type": "String", - "Description": "S3 bucket for asset \"82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4e\"" + "Description": "S3 bucket for asset \"c11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6be\"" }, - "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3VersionKey3194A583": { + "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3VersionKeyB87E9196": { "Type": "String", - "Description": "S3 key for asset version \"82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4e\"" + "Description": "S3 key for asset version \"c11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6be\"" }, - "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eArtifactHashB967D42A": { + "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beArtifactHashBA1C5764": { "Type": "String", - "Description": "Artifact hash for asset \"82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4e\"" + "Description": "Artifact hash for asset \"c11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6be\"" } } } \ No newline at end of file From 044a81c2a78e3decc180bfdb376e5e44533c7fa2 Mon Sep 17 00:00:00 2001 From: Jaap van Blaaderen Date: Mon, 8 Jun 2020 13:00:08 +0200 Subject: [PATCH 2/8] fix(lambda): Make retry options configurable for CloudWatchLogs group management fixes #8257 --- packages/@aws-cdk/aws-lambda/lib/function.ts | 13 ++++++- .../lib/log-retention-provider/index.ts | 38 +++++++++++++------ .../@aws-cdk/aws-lambda/lib/log-retention.ts | 26 +++++++++++++ .../test/integ.log-retention.expected.json | 18 ++++----- .../test/test.log-retention-provider.ts | 37 ++++++++++++++++++ 5 files changed, 111 insertions(+), 21 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index ea2d2bf1f18ef..c5539fd3c4f37 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -12,7 +12,7 @@ import { calculateFunctionHash, trimFromStart } from './function-hash'; import { Version, VersionOptions } from './lambda-version'; import { CfnFunction } from './lambda.generated'; import { ILayerVersion } from './layers'; -import { LogRetention } from './log-retention'; +import { LogRetention, LogRetentionRetryOptions } from './log-retention'; import { Runtime } from './runtime'; /** @@ -232,6 +232,16 @@ export interface FunctionOptions extends EventInvokeConfigOptions { */ readonly logRetentionRole?: iam.IRole; + /** + * Retry options for creating CloudWatch log groups. Deploying many Lambdas + * with log retention resources may result in rate limit issues when creating + * CloudWatch Log groups. The retry options allow you to customize the retry + * options in order to successfully create these. + * + * @default - Default retry options of the AWS SDK. + */ + readonly logRetentionRetryOptions?: LogRetentionRetryOptions; + /** * Options for the `lambda.Version` resource automatically created by the * `fn.currentVersion` method. @@ -544,6 +554,7 @@ export class Function extends FunctionBase { logGroupName: `/aws/lambda/${this.functionName}`, retention: props.logRetention, role: props.logRetentionRole, + logRetentionRetryOptions: props.logRetentionRetryOptions, }); this._logGroup = logs.LogGroup.fromLogGroupArn(this, 'LogGroup', logretention.logGroupArn); } 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 5e4b3e38a34d8..668913e76d9fd 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 @@ -2,18 +2,16 @@ // eslint-disable-next-line import/no-extraneous-dependencies import * as AWS from 'aws-sdk'; - -// Ensure we do not run into throttling issues when deploying stack(s) with a lot of Lambdas. -const retryOptions = { maxRetries: 6, retryDelayOptions: { base: 300 }}; +import { LogRetentionRetryOptions } from '../log-retention'; /** * Creates a log group and doesn't throw if it exists. * * @param logGroupName the name of the log group to create */ -async function createLogGroupSafe(logGroupName: string) { +async function createLogGroupSafe(logGroupName: string, retryOptions?: LogRetentionRetryOptions) { try { // Try to create the log group - const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...retryOptions}); + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...retryOptions }); await cloudwatchlogs.createLogGroup({ logGroupName }).promise(); } catch (e) { if (e.code !== 'ResourceAlreadyExistsException') { @@ -28,8 +26,8 @@ async function createLogGroupSafe(logGroupName: string) { * @param logGroupName the name of the log group to create * @param retentionInDays the number of days to retain the log events in the specified log group. */ -async function setRetentionPolicy(logGroupName: string, retentionInDays?: number) { - const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...retryOptions}); +async function setRetentionPolicy(logGroupName: string, retryOptions?: LogRetentionRetryOptions, retentionInDays?: number) { + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...retryOptions }); if (!retentionInDays) { await cloudwatchlogs.deleteRetentionPolicy({ logGroupName }).promise(); } else { @@ -44,10 +42,13 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent // The target log group const logGroupName = event.ResourceProperties.LogGroupName; + // Parse retry options for creating the target log group + const retryOptions = parseRetryOptions(event.ResourceProperties.LogRetentionRetryOptions); + if (event.RequestType === 'Create' || event.RequestType === 'Update') { // Act on the target log group - await createLogGroupSafe(logGroupName); - await setRetentionPolicy(logGroupName, parseInt(event.ResourceProperties.RetentionInDays, 10)); + await createLogGroupSafe(logGroupName, retryOptions); + await setRetentionPolicy(logGroupName, retryOptions, parseInt(event.ResourceProperties.RetentionInDays, 10)); if (event.RequestType === 'Create') { // Set a retention policy of 1 day on the logs of this function. The log @@ -59,8 +60,8 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent // 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); + await createLogGroupSafe(`/aws/lambda/${context.functionName}`, retryOptions); + await setRetentionPolicy(`/aws/lambda/${context.functionName}`, retryOptions, 1); } catch (e) { console.log(e); } @@ -111,4 +112,19 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent } }); } + + function parseRetryOptions(rawOptions: any) { + const retryOptions: { maxRetries?: number, retryOptions?: { base?: number } } = {}; + if (rawOptions) { + if (rawOptions.maxRetries) { + retryOptions.maxRetries = parseInt(rawOptions.maxRetries, 10); + } + if (rawOptions.base) { + retryOptions.retryOptions = { + base: parseInt(rawOptions.base, 10), + }; + } + } + return retryOptions; + } } diff --git a/packages/@aws-cdk/aws-lambda/lib/log-retention.ts b/packages/@aws-cdk/aws-lambda/lib/log-retention.ts index 74feeb5e62794..9918bf8aa3df6 100644 --- a/packages/@aws-cdk/aws-lambda/lib/log-retention.ts +++ b/packages/@aws-cdk/aws-lambda/lib/log-retention.ts @@ -26,6 +26,31 @@ export interface LogRetentionProps { * @default - A new role is created */ readonly role?: iam.IRole; + + /** + * Retry options for managing CloudWatch log groups. + * + * @default - AWS SDK default retry options + */ + readonly logRetentionRetryOptions?: LogRetentionRetryOptions; +} + +/** + * Retry options for managing CloudWatch log groups + */ +export interface LogRetentionRetryOptions { + /** + * The maximum amount of retries. + * + * @default - AWS SDK default + */ + readonly maxRetries?: number; + /** + * The base number of milliseconds to use in the exponential backoff for operation retries. + * + * @default - AWS SDK default + */ + readonly base?: number; } /** @@ -69,6 +94,7 @@ export class LogRetention extends cdk.Construct { properties: { ServiceToken: provider.functionArn, LogGroupName: props.logGroupName, + LogRetentionRetryOptions: props.logRetentionRetryOptions, RetentionInDays: props.retention === logs.RetentionDays.INFINITE ? undefined : props.retention, }, }); diff --git a/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json b/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json index ff3bb7285e69f..d33ff3f57d2eb 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json @@ -133,7 +133,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3BucketD782C750" + "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3BucketA7A09DD7" }, "S3Key": { "Fn::Join": [ @@ -146,7 +146,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3VersionKeyB87E9196" + "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3" } ] } @@ -159,7 +159,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3VersionKeyB87E9196" + "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3" } ] } @@ -331,17 +331,17 @@ } }, "Parameters": { - "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3BucketD782C750": { + "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3BucketA7A09DD7": { "Type": "String", - "Description": "S3 bucket for asset \"c11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6be\"" + "Description": "S3 bucket for asset \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" }, - "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beS3VersionKeyB87E9196": { + "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3": { "Type": "String", - "Description": "S3 key for asset version \"c11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6be\"" + "Description": "S3 key for asset version \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" }, - "AssetParametersc11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6beArtifactHashBA1C5764": { + "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fArtifactHashE75963CF": { "Type": "String", - "Description": "Artifact hash for asset \"c11219c29950dc50a505625251bd4e6b553c3d85f04bcba46572f2e25e8fe6be\"" + "Description": "Artifact hash for asset \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" } } } \ No newline at end of file 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 bfc37c0d1b6f2..02c8cbfa08c3a 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 @@ -296,4 +296,41 @@ export = { test.done(); }, + + async 'custom log retention retry options'(test: Test) { + AWS.mock('CloudWatchLogs', 'createLogGroup', sinon.fake.resolves({})); + AWS.mock('CloudWatchLogs', 'putRetentionPolicy', sinon.fake.resolves({})); + AWS.mock('CloudWatchLogs', 'deleteRetentionPolicy', sinon.fake.resolves({})); + + const event = { + ...eventCommon, + RequestType: 'Create', + ResourceProperties: { + ServiceToken: 'token', + RetentionInDays: '30', + LogGroupName: 'group', + LogRetentionRetryOptions: { + maxRetries: '5', + base: '300', + }, + }, + }; + + const request = createRequest('SUCCESS'); + + await provider.handler(event as AWSLambda.CloudFormationCustomResourceCreateEvent, context); + + sinon.assert.calledWith(AWSSDK.CloudWatchLogs as any, { + apiVersion: '2014-03-28', + maxRetries: 5, + retryOptions: { + base: 300, + }, + }); + + test.equal(request.isDone(), true); + + test.done(); + }, + }; From 1f86f2f5ddb1cdf21143c105b4a13bf61fe8a313 Mon Sep 17 00:00:00 2001 From: Jaap van Blaaderen Date: Mon, 8 Jun 2020 23:48:08 +0200 Subject: [PATCH 3/8] fix(lambda): Fix integration test fixes #8257 --- .../test/integ.instance.lit.expected.json | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json index d5c7708151b53..2d9a9f963c9ee 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json +++ b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json @@ -967,7 +967,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3Bucket7046E6CE" + "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3BucketA7A09DD7" }, "S3Key": { "Fn::Join": [ @@ -980,7 +980,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3VersionKey3194A583" + "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3" } ] } @@ -993,7 +993,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3VersionKey3194A583" + "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3" } ] } @@ -1108,17 +1108,17 @@ } }, "Parameters": { - "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3Bucket7046E6CE": { + "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3BucketA7A09DD7": { "Type": "String", - "Description": "S3 bucket for asset \"82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4e\"" + "Description": "S3 bucket for asset \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" }, - "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eS3VersionKey3194A583": { + "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3": { "Type": "String", - "Description": "S3 key for asset version \"82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4e\"" + "Description": "S3 key for asset version \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" }, - "AssetParameters82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4eArtifactHashB967D42A": { + "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fArtifactHashE75963CF": { "Type": "String", - "Description": "Artifact hash for asset \"82c54bfa7c42ba410d6d18dad983ba51c93a5ea940818c5c20230f8b59c19d4e\"" + "Description": "Artifact hash for asset \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" } } -} +} \ No newline at end of file From 7ca18c76e1ee93d0ac20133b99f5849dabe7a01f Mon Sep 17 00:00:00 2001 From: Jaap van Blaaderen Date: Thu, 11 Jun 2020 09:37:27 +0200 Subject: [PATCH 4/8] fix(lambda): Code cleanup - fix review comments fixes #8257 --- packages/@aws-cdk/aws-lambda/lib/function.ts | 8 +++----- .../lib/log-retention-provider/index.ts | 17 +++++++++-------- .../@aws-cdk/aws-lambda/lib/log-retention.ts | 18 +++++++++++------- .../test/integ.log-retention.expected.json | 18 +++++++++--------- .../test/test.log-retention-provider.ts | 2 +- .../test/integ.instance.lit.expected.json | 18 +++++++++--------- 6 files changed, 42 insertions(+), 39 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index c5539fd3c4f37..d99d1b1ce8377 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -233,12 +233,10 @@ export interface FunctionOptions extends EventInvokeConfigOptions { readonly logRetentionRole?: iam.IRole; /** - * Retry options for creating CloudWatch log groups. Deploying many Lambdas - * with log retention resources may result in rate limit issues when creating - * CloudWatch Log groups. The retry options allow you to customize the retry - * options in order to successfully create these. + * When log retention is specified, a custom resource attempts to create the CloudWatch log group. + * These options control the retry policy when interacting with CloudWatch APIs. * - * @default - Default retry options of the AWS SDK. + * @default - Default AWS SDK retry options. */ readonly logRetentionRetryOptions?: LogRetentionRetryOptions; 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 668913e76d9fd..45268e1b3be85 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 @@ -2,16 +2,16 @@ // eslint-disable-next-line import/no-extraneous-dependencies import * as AWS from 'aws-sdk'; -import { LogRetentionRetryOptions } from '../log-retention'; /** * Creates a log group and doesn't throw if it exists. * - * @param logGroupName the name of the log group to create + * @param logGroupName the name of the log group to create. + * @param options CloudWatch API SDK options. */ -async function createLogGroupSafe(logGroupName: string, retryOptions?: LogRetentionRetryOptions) { +async function createLogGroupSafe(logGroupName: string, options?: any) { try { // Try to create the log group - const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...retryOptions }); + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...options }); await cloudwatchlogs.createLogGroup({ logGroupName }).promise(); } catch (e) { if (e.code !== 'ResourceAlreadyExistsException') { @@ -24,10 +24,11 @@ async function createLogGroupSafe(logGroupName: string, retryOptions?: LogRetent * Puts or deletes a retention policy on a log group. * * @param logGroupName the name of the log group to create + * @param options CloudWatch API SDK options. * @param retentionInDays the number of days to retain the log events in the specified log group. */ -async function setRetentionPolicy(logGroupName: string, retryOptions?: LogRetentionRetryOptions, retentionInDays?: number) { - const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...retryOptions }); +async function setRetentionPolicy(logGroupName: string, options?: any, retentionInDays?: number) { + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...options }); if (!retentionInDays) { await cloudwatchlogs.deleteRetentionPolicy({ logGroupName }).promise(); } else { @@ -42,8 +43,8 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent // The target log group const logGroupName = event.ResourceProperties.LogGroupName; - // Parse retry options for creating the target log group - const retryOptions = parseRetryOptions(event.ResourceProperties.LogRetentionRetryOptions); + // Parse to AWS SDK retry options + const retryOptions = parseRetryOptions(event.ResourceProperties.SdkRetry); if (event.RequestType === 'Create' || event.RequestType === 'Update') { // Act on the target log group diff --git a/packages/@aws-cdk/aws-lambda/lib/log-retention.ts b/packages/@aws-cdk/aws-lambda/lib/log-retention.ts index 9918bf8aa3df6..785b164c49b64 100644 --- a/packages/@aws-cdk/aws-lambda/lib/log-retention.ts +++ b/packages/@aws-cdk/aws-lambda/lib/log-retention.ts @@ -28,7 +28,7 @@ export interface LogRetentionProps { readonly role?: iam.IRole; /** - * Retry options for managing CloudWatch log groups. + * Retry options for all AWS API calls. * * @default - AWS SDK default retry options */ @@ -36,21 +36,21 @@ export interface LogRetentionProps { } /** - * Retry options for managing CloudWatch log groups + * Retry options for all AWS API calls. */ export interface LogRetentionRetryOptions { /** * The maximum amount of retries. * - * @default - AWS SDK default + * @default - 3 (AWS SDK default) */ readonly maxRetries?: number; /** - * The base number of milliseconds to use in the exponential backoff for operation retries. + * The base duration to use in the exponential backoff for operation retries. * - * @default - AWS SDK default + * @default - 100 milliseconds (AWS SDK default) */ - readonly base?: number; + readonly base?: cdk.Duration; } /** @@ -89,12 +89,16 @@ export class LogRetention extends cdk.Construct { // Need to use a CfnResource here to prevent lerna dependency cycles // @aws-cdk/aws-cloudformation -> @aws-cdk/aws-lambda -> @aws-cdk/aws-cloudformation + const retryOptions = props.logRetentionRetryOptions; const resource = new cdk.CfnResource(this, 'Resource', { type: 'Custom::LogRetention', properties: { ServiceToken: provider.functionArn, LogGroupName: props.logGroupName, - LogRetentionRetryOptions: props.logRetentionRetryOptions, + SdkRetry: retryOptions ? { + maxRetries: retryOptions.maxRetries, + base: retryOptions.base?.toMilliseconds(), + } : undefined, RetentionInDays: props.retention === logs.RetentionDays.INFINITE ? undefined : props.retention, }, }); diff --git a/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json b/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json index d33ff3f57d2eb..e14dfc8a04b39 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json @@ -133,7 +133,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3BucketA7A09DD7" + "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3Bucket7D13D80A" }, "S3Key": { "Fn::Join": [ @@ -146,7 +146,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3" + "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55" } ] } @@ -159,7 +159,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3" + "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55" } ] } @@ -331,17 +331,17 @@ } }, "Parameters": { - "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3BucketA7A09DD7": { + "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3Bucket7D13D80A": { "Type": "String", - "Description": "S3 bucket for asset \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" + "Description": "S3 bucket for asset \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" }, - "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3": { + "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55": { "Type": "String", - "Description": "S3 key for asset version \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" + "Description": "S3 key for asset version \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" }, - "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fArtifactHashE75963CF": { + "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67ArtifactHash13DA6A3B": { "Type": "String", - "Description": "Artifact hash for asset \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" + "Description": "Artifact hash for asset \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" } } } \ No newline at end of file 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 02c8cbfa08c3a..007f2836bf44b 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 @@ -309,7 +309,7 @@ export = { ServiceToken: 'token', RetentionInDays: '30', LogGroupName: 'group', - LogRetentionRetryOptions: { + SdkRetry: { maxRetries: '5', base: '300', }, diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json index 2d9a9f963c9ee..e5d140fa3f058 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json +++ b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json @@ -967,7 +967,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3BucketA7A09DD7" + "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3Bucket7D13D80A" }, "S3Key": { "Fn::Join": [ @@ -980,7 +980,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3" + "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55" } ] } @@ -993,7 +993,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3" + "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55" } ] } @@ -1108,17 +1108,17 @@ } }, "Parameters": { - "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3BucketA7A09DD7": { + "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3Bucket7D13D80A": { "Type": "String", - "Description": "S3 bucket for asset \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" + "Description": "S3 bucket for asset \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" }, - "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fS3VersionKey579A73D3": { + "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55": { "Type": "String", - "Description": "S3 key for asset version \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" + "Description": "S3 key for asset version \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" }, - "AssetParameterse375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028fArtifactHashE75963CF": { + "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67ArtifactHash13DA6A3B": { "Type": "String", - "Description": "Artifact hash for asset \"e375da66e6ab168bb13b858a043e9e8c8c20334b443d746983fa4ad0dcc7028f\"" + "Description": "Artifact hash for asset \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" } } } \ No newline at end of file From c4823d5ddffb4707f04879f9d3b845e09c4d4a06 Mon Sep 17 00:00:00 2001 From: Jaap van Blaaderen Date: Thu, 11 Jun 2020 10:49:04 +0200 Subject: [PATCH 5/8] fix(lambda):Update readme fixes #8257 --- packages/@aws-cdk/aws-lambda/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index 01b211d16e142..fb7283b2643d8 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -266,6 +266,9 @@ The `logRetention` property can be used to set a different expiration period. It is possible to obtain the function's log group as a `logs.ILogGroup` by calling the `logGroup` property of the `Function` construct. +By default, CDK uses the AWS SDK retry options when creating a log group. The `logRetentionRetryOptions` property +allows you to customize the maximum number of retries and base backoff duration. + *Note* that, if either `logRetention` is set or `logGroup` property is called, a [CloudFormation custom resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html) is added to the stack that pre-creates the log group as part of the stack deployment, if it already doesn't exist, and sets the From 1c6f5d795d3a91a005bf2d8f8b790b7e3af5469d Mon Sep 17 00:00:00 2001 From: Jaap van Blaaderen Date: Fri, 12 Jun 2020 11:54:40 +0200 Subject: [PATCH 6/8] Update packages/@aws-cdk/aws-lambda/lib/log-retention.ts Tweak comment #8258 Co-authored-by: Niranjan Jayakar --- packages/@aws-cdk/aws-lambda/lib/log-retention.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/log-retention.ts b/packages/@aws-cdk/aws-lambda/lib/log-retention.ts index 785b164c49b64..8e7d640948083 100644 --- a/packages/@aws-cdk/aws-lambda/lib/log-retention.ts +++ b/packages/@aws-cdk/aws-lambda/lib/log-retention.ts @@ -42,7 +42,7 @@ export interface LogRetentionRetryOptions { /** * The maximum amount of retries. * - * @default - 3 (AWS SDK default) + * @default 3 (AWS SDK default) */ readonly maxRetries?: number; /** From 6708723128d15d980e716084f75abbdb0c6799ad Mon Sep 17 00:00:00 2001 From: Jaap van Blaaderen Date: Fri, 12 Jun 2020 11:55:16 +0200 Subject: [PATCH 7/8] Tweak comment #8258 Co-authored-by: Niranjan Jayakar --- packages/@aws-cdk/aws-lambda/lib/log-retention.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/log-retention.ts b/packages/@aws-cdk/aws-lambda/lib/log-retention.ts index 8e7d640948083..6c5fec2da7cd9 100644 --- a/packages/@aws-cdk/aws-lambda/lib/log-retention.ts +++ b/packages/@aws-cdk/aws-lambda/lib/log-retention.ts @@ -48,7 +48,7 @@ export interface LogRetentionRetryOptions { /** * The base duration to use in the exponential backoff for operation retries. * - * @default - 100 milliseconds (AWS SDK default) + * @default Duration.millis(100) (AWS SDK default) */ readonly base?: cdk.Duration; } From 6f4057c526538d24724724a2d2ecb25b80c38126 Mon Sep 17 00:00:00 2001 From: Jaap van Blaaderen Date: Fri, 12 Jun 2020 17:06:54 +0200 Subject: [PATCH 8/8] fix(lambda): Fix review comments fixes #8257 --- .../lib/log-retention-provider/index.ts | 15 +++++++++++---- .../test/integ.log-retention.expected.json | 18 +++++++++--------- .../test/integ.instance.lit.expected.json | 18 +++++++++--------- 3 files changed, 29 insertions(+), 22 deletions(-) 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 45268e1b3be85..16d44a5fd83de 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 @@ -2,6 +2,13 @@ // eslint-disable-next-line import/no-extraneous-dependencies import * as AWS from 'aws-sdk'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { RetryDelayOptions } from 'aws-sdk/lib/config'; + +interface SdkRetryOptions { + maxRetries?: number; + retryOptions?: RetryDelayOptions; +} /** * Creates a log group and doesn't throw if it exists. @@ -9,7 +16,7 @@ import * as AWS from 'aws-sdk'; * @param logGroupName the name of the log group to create. * @param options CloudWatch API SDK options. */ -async function createLogGroupSafe(logGroupName: string, options?: any) { +async function createLogGroupSafe(logGroupName: string, options?: SdkRetryOptions) { try { // Try to create the log group const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...options }); await cloudwatchlogs.createLogGroup({ logGroupName }).promise(); @@ -27,7 +34,7 @@ async function createLogGroupSafe(logGroupName: string, options?: any) { * @param options CloudWatch API SDK options. * @param retentionInDays the number of days to retain the log events in the specified log group. */ -async function setRetentionPolicy(logGroupName: string, options?: any, retentionInDays?: number) { +async function setRetentionPolicy(logGroupName: string, options?: SdkRetryOptions, retentionInDays?: number) { const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', ...options }); if (!retentionInDays) { await cloudwatchlogs.deleteRetentionPolicy({ logGroupName }).promise(); @@ -114,8 +121,8 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent }); } - function parseRetryOptions(rawOptions: any) { - const retryOptions: { maxRetries?: number, retryOptions?: { base?: number } } = {}; + function parseRetryOptions(rawOptions: any): SdkRetryOptions { + const retryOptions: SdkRetryOptions = {}; if (rawOptions) { if (rawOptions.maxRetries) { retryOptions.maxRetries = parseInt(rawOptions.maxRetries, 10); diff --git a/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json b/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json index e14dfc8a04b39..3e45c9ce6d65d 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.log-retention.expected.json @@ -133,7 +133,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3Bucket7D13D80A" + "Ref": "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3Bucket21D86049" }, "S3Key": { "Fn::Join": [ @@ -146,7 +146,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55" + "Ref": "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3VersionKey1F67C4C1" } ] } @@ -159,7 +159,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55" + "Ref": "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3VersionKey1F67C4C1" } ] } @@ -331,17 +331,17 @@ } }, "Parameters": { - "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3Bucket7D13D80A": { + "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3Bucket21D86049": { "Type": "String", - "Description": "S3 bucket for asset \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" + "Description": "S3 bucket for asset \"3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3\"" }, - "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55": { + "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3VersionKey1F67C4C1": { "Type": "String", - "Description": "S3 key for asset version \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" + "Description": "S3 key for asset version \"3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3\"" }, - "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67ArtifactHash13DA6A3B": { + "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3ArtifactHash31AA1F7C": { "Type": "String", - "Description": "Artifact hash for asset \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" + "Description": "Artifact hash for asset \"3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3\"" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json index e5d140fa3f058..01687488c079e 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json +++ b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.expected.json @@ -967,7 +967,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3Bucket7D13D80A" + "Ref": "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3Bucket21D86049" }, "S3Key": { "Fn::Join": [ @@ -980,7 +980,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55" + "Ref": "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3VersionKey1F67C4C1" } ] } @@ -993,7 +993,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55" + "Ref": "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3VersionKey1F67C4C1" } ] } @@ -1108,17 +1108,17 @@ } }, "Parameters": { - "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3Bucket7D13D80A": { + "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3Bucket21D86049": { "Type": "String", - "Description": "S3 bucket for asset \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" + "Description": "S3 bucket for asset \"3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3\"" }, - "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67S3VersionKey8FAF5E55": { + "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3S3VersionKey1F67C4C1": { "Type": "String", - "Description": "S3 key for asset version \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" + "Description": "S3 key for asset version \"3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3\"" }, - "AssetParameters5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67ArtifactHash13DA6A3B": { + "AssetParameters3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3ArtifactHash31AA1F7C": { "Type": "String", - "Description": "Artifact hash for asset \"5e2b20ad370d3155f4160b75bbf219a9280a3ea5ff390409ce201444026b0f67\"" + "Description": "Artifact hash for asset \"3974ceb096f16a0d6c372c0c821ca2ab0333112497b2d3bc462ccaf2fc6037c3\"" } } } \ No newline at end of file