From c0b10d70f38e5150e68f242c72757f316d889f24 Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Thu, 30 May 2024 14:47:31 -0700 Subject: [PATCH 01/12] Create 'configureLambdaLogGroup' method in CustomResourceProviderBase to set LoggingConfig for the underlying lambda --- .../custom-resource-provider-base.ts | 20 ++++++++++++++---- .../custom-resource-provider.test.ts | 21 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/packages/aws-cdk-lib/core/lib/custom-resource-provider/custom-resource-provider-base.ts b/packages/aws-cdk-lib/core/lib/custom-resource-provider/custom-resource-provider-base.ts index 7bcc24269207f..d722a3948fcf4 100644 --- a/packages/aws-cdk-lib/core/lib/custom-resource-provider/custom-resource-provider-base.ts +++ b/packages/aws-cdk-lib/core/lib/custom-resource-provider/custom-resource-provider-base.ts @@ -51,6 +51,7 @@ export abstract class CustomResourceProviderBase extends Construct { private _codeHash?: string; private policyStatements?: any[]; private role?: CfnResource; + private handler: CfnResource; /** * The ARN of the provider's AWS Lambda function which should be used as the `serviceToken` when defining a custom @@ -129,7 +130,7 @@ export abstract class CustomResourceProviderBase extends Construct { const timeout = props.timeout ?? Duration.minutes(15); const memory = props.memorySize ?? Size.mebibytes(128); - const handler = new CfnResource(this, 'Handler', { + this.handler = new CfnResource(this, 'Handler', { type: 'AWS::Lambda::Function', properties: { Code: code, @@ -144,14 +145,25 @@ export abstract class CustomResourceProviderBase extends Construct { }); if (this.role) { - handler.addDependency(this.role); + this.handler.addDependency(this.role); } if (metadata) { - Object.entries(metadata).forEach(([k, v]) => handler.addMetadata(k, v)); + Object.entries(metadata).forEach(([k, v]) => this.handler.addMetadata(k, v)); } - this.serviceToken = Token.asString(handler.getAtt('Arn')); + this.serviceToken = Token.asString(this.handler.getAtt('Arn')); + } + + /** + * Set the log group used by the lambda function backing this custom resource. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-loggingconfig + */ + public configureLambdaLogGroup(logGroupName: string) { + this.handler.addPropertyOverride('LoggingConfig', { + LogGroup: logGroupName, + }); } /** diff --git a/packages/aws-cdk-lib/core/test/custom-resource-provider/custom-resource-provider.test.ts b/packages/aws-cdk-lib/core/test/custom-resource-provider/custom-resource-provider.test.ts index f326e4b34ae07..279fabe9e7032 100644 --- a/packages/aws-cdk-lib/core/test/custom-resource-provider/custom-resource-provider.test.ts +++ b/packages/aws-cdk-lib/core/test/custom-resource-provider/custom-resource-provider.test.ts @@ -394,6 +394,27 @@ describe('custom resource provider', () => { }]); }); + test('configureLambdaLogGroup() sets the Lambda LoggingConfig', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + const provider = CustomResourceProvider.getOrCreateProvider(stack, 'Custom:MyResourceType', { + codeDirectory: TEST_HANDLER, + runtime: STANDARD_PROVIDER, + policyStatements: [ + { statement1: 123 }, + { statement2: { foo: 111 } }, + ], + }); + provider.configureLambdaLogGroup('MyTestLogGroup'); + + // THEN + const template = toCloudFormation(stack); + const role = template.Resources.CustomMyResourceTypeCustomResourceProviderHandler29FBDD2A; + expect(role.Properties.LoggingConfig).toEqual({ LogGroup: 'MyTestLogGroup' }); + }); + test('memorySize, timeout and description', () => { // GIVEN const stack = new Stack(); From 3859bb1d873fec7849d71fab5c2f40df1ce42b56 Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Thu, 30 May 2024 15:02:41 -0700 Subject: [PATCH 02/12] Update provider code gen logic to create pure getProvider() method --- .../lib/custom-resources-framework/classes.ts | 32 ++++++++++++++++--- .../custom-resource-provider-core.ts | 11 ++++++- .../custom-resource-provider.ts | 11 ++++++- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/custom-resource-handlers/lib/custom-resources-framework/classes.ts b/packages/@aws-cdk/custom-resource-handlers/lib/custom-resources-framework/classes.ts index bee5e57cb3f35..74b28a169467a 100644 --- a/packages/@aws-cdk/custom-resource-handlers/lib/custom-resources-framework/classes.ts +++ b/packages/@aws-cdk/custom-resource-handlers/lib/custom-resources-framework/classes.ts @@ -274,6 +274,30 @@ export abstract class HandlerFrameworkClass extends ClassType { stmt.ret(expr.directCode('this.getOrCreateProvider(scope, uniqueid, props).serviceToken')), ); + const idStatement = stmt.constVar(expr.ident('id'), expr.directCode('`${uniqueid}CustomResourceProvider`')); + const stackFromScopeStatement = stmt.constVar(expr.ident('stack'), expr.directCode('Stack.of(scope)')); + const getProviderMethod = this.addMethod({ + name: 'getProvider', + static: true, + returnType: this.type, + docs: { + summary: 'Returns the stack-level singleton provider or undefined', + }, + }); + getProviderMethod.addParameter({ + name: 'scope', + type: CONSTRUCTS_MODULE.Construct, + }); + getProviderMethod.addParameter({ + name: 'uniqueid', + type: Type.STRING, + }); + getProviderMethod.addBody( + idStatement, + stackFromScopeStatement, + stmt.ret(expr.directCode(`stack.node.tryFindChild(id) as ${this.type}`)), + ); + const getOrCreateProviderMethod = this.addMethod({ name: 'getOrCreateProvider', static: true, @@ -282,7 +306,7 @@ export abstract class HandlerFrameworkClass extends ClassType { summary: 'Returns a stack-level singleton for the custom resource provider.', }, }); - const _scope = getOrCreateProviderMethod.addParameter({ + getOrCreateProviderMethod.addParameter({ name: 'scope', type: CONSTRUCTS_MODULE.Construct, }); @@ -296,9 +320,9 @@ export abstract class HandlerFrameworkClass extends ClassType { optional: true, }); getOrCreateProviderMethod.addBody( - stmt.constVar(expr.ident('id'), expr.directCode('`${uniqueid}CustomResourceProvider`')), - stmt.constVar(expr.ident('stack'), $T(CORE_MODULE.Stack).of(expr.directCode(_scope.spec.name))), - stmt.constVar(expr.ident('existing'), expr.directCode(`stack.node.tryFindChild(id) as ${this.type}`)), + idStatement, + stmt.constVar(expr.ident('existing'), expr.directCode('this.getProvider(scope, uniqueid)')), + stackFromScopeStatement, stmt.ret(expr.directCode(`existing ?? new ${this.name}(stack, id, props)`)), ); diff --git a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider-core.ts b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider-core.ts index 46b3b7bdf532c..3b6e1bc036975 100644 --- a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider-core.ts +++ b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider-core.ts @@ -12,13 +12,22 @@ export class TestProvider extends CustomResourceProviderBase { return this.getOrCreateProvider(scope, uniqueid, props).serviceToken; } + /** + * Returns the stack-level singleton provider or undefined + */ + public static getProvider(scope: Construct, uniqueid: string): TestProvider { + const id = `${uniqueid}CustomResourceProvider`; + const stack = Stack.of(scope); + return stack.node.tryFindChild(id) as TestProvider; + } + /** * Returns a stack-level singleton for the custom resource provider. */ public static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): TestProvider { const id = `${uniqueid}CustomResourceProvider`; + const existing = this.getProvider(scope, uniqueid); const stack = Stack.of(scope); - const existing = stack.node.tryFindChild(id) as TestProvider; return existing ?? new TestProvider(stack, id, props); } diff --git a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider.ts b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider.ts index 0ab4377ec0ebd..5d606d9709003 100644 --- a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider.ts +++ b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider.ts @@ -11,13 +11,22 @@ export class TestProvider extends CustomResourceProviderBase { return this.getOrCreateProvider(scope, uniqueid, props).serviceToken; } + /** + * Returns the stack-level singleton provider or undefined + */ + public static getProvider(scope: Construct, uniqueid: string): TestProvider { + const id = `${uniqueid}CustomResourceProvider`; + const stack = Stack.of(scope); + return stack.node.tryFindChild(id) as TestProvider; + } + /** * Returns a stack-level singleton for the custom resource provider. */ public static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): TestProvider { const id = `${uniqueid}CustomResourceProvider`; + const existing = this.getProvider(scope, uniqueid); const stack = Stack.of(scope); - const existing = stack.node.tryFindChild(id) as TestProvider; return existing ?? new TestProvider(stack, id, props); } From f5dcbe729e235403c4b40c18a133612e79c538c5 Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Thu, 30 May 2024 15:09:56 -0700 Subject: [PATCH 03/12] Create new static method setAutoDeleteObjectsLogGroup in Bucket construct --- packages/aws-cdk-lib/aws-s3/lib/bucket.ts | 24 +++++++ .../aws-cdk-lib/aws-s3/test/bucket.test.ts | 62 +++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts index 5497df55798f2..c874e47c82eab 100644 --- a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts +++ b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts @@ -10,6 +10,7 @@ import { parseBucketArn, parseBucketName } from './util'; import * as events from '../../aws-events'; import * as iam from '../../aws-iam'; import * as kms from '../../aws-kms'; +import * as logs from '../../aws-logs'; import { CustomResource, Duration, @@ -1466,6 +1467,9 @@ export interface BucketProps { * * Requires the `removalPolicy` to be set to `RemovalPolicy.DESTROY`. * + * A custom resource along with a provider lambda will be created for + * emptying the bucket. + * * **Warning** if you have deployed a bucket with `autoDeleteObjects: true`, * switching this to `false` in a CDK version *before* `1.126.0` will lead to * all objects in the bucket being deleted. Be sure to update your bucket resources @@ -1882,6 +1886,26 @@ export class Bucket extends BucketBase { } } + /** + * Set the log group on the singleton AutoDeleteObjects provider lambda. + * Note: Calling this multiple times will override the previously set log group + * + * In the case of no buckets with `autoDeleteObjects: true` exist in the stack, + * this will throw an exception as no AutoDeleteObjects provider lambda will exist + * in the stack. + * + * @param scope the stack with bucket(s) with `autoDeleteObjects: true`. + * @param logGroup the log group to use on the lambda. + */ + public static setAutoDeleteObjectsLogGroup(scope: Construct, logGroup: logs.ILogGroup): void { + const provider = AutoDeleteObjectsProvider.getProvider(scope, AUTO_DELETE_OBJECTS_RESOURCE_TYPE); + + if (provider === undefined) { + throw new Error('Requires at least one bucket with \'autoDeleteObjects: true\'. None is found.'); + } + provider.configureLambdaLogGroup(logGroup.logGroupName); + } + public readonly bucketArn: string; public readonly bucketName: string; public readonly bucketDomainName: string; diff --git a/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts b/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts index 4d97390952ee5..4fa9abdf1ffb8 100644 --- a/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts +++ b/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts @@ -3,6 +3,7 @@ import { testDeprecated } from '@aws-cdk/cdk-build-tools'; import { Annotations, Match, Template } from '../../assertions'; import * as iam from '../../aws-iam'; import * as kms from '../../aws-kms'; +import * as logs from '../../aws-logs'; import * as cdk from '../../core'; import * as s3 from '../lib'; @@ -3493,6 +3494,67 @@ describe('bucket', () => { })).toThrow(/Cannot use \'autoDeleteObjects\' property on a bucket without setting removal policy to \'DESTROY\'/); }); + test('setAutoDeleteObjectsLogGroup throws if no bucket has autoDeleteObjects: true in stack', () => { + const stack = new cdk.Stack(); + + new s3.Bucket(stack, 'MyBucket', { }); + + expect(() => s3.Bucket.setAutoDeleteObjectsLogGroup(stack, new logs.LogGroup(stack, 'MyLogGroup', {}))) + .toThrow(/Requires at least one bucket with 'autoDeleteObjects: true'. None is found./); + }); + + test('setAutoDeleteObjectsLogGroup to update AutoDeleteObjectsProvider LoggingConfig', () => { + const stack = new cdk.Stack(); + + new s3.Bucket(stack, 'MyBucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true, + }); + s3.Bucket.setAutoDeleteObjectsLogGroup(stack, new logs.LogGroup(stack, 'FirstLogGroup', { + logGroupName: 'MyFirstLogGroup', + })); + + Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', { + LogGroupName: 'MyFirstLogGroup', + }); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + LoggingConfig: { + LogGroup: { + 'Ref': 'FirstLogGroupFF5C2AA0', + }, + }, + }); + }); + + test('setAutoDeleteObjectsLogGroup multiple times should take the latest Log Group', () => { + const stack = new cdk.Stack(); + + new s3.Bucket(stack, 'MyBucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true, + }); + s3.Bucket.setAutoDeleteObjectsLogGroup(stack, new logs.LogGroup(stack, 'FirstLogGroup', { + logGroupName: 'MyFirstLogGroup', + })); + s3.Bucket.setAutoDeleteObjectsLogGroup(stack, new logs.LogGroup(stack, 'SecondLogGroup', { + logGroupName: 'MySecondLogGroup', + })); + + Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', { + LogGroupName: 'MyFirstLogGroup', + }); + Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', { + LogGroupName: 'MySecondLogGroup', + }); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + LoggingConfig: { + LogGroup: { + 'Ref': 'SecondLogGroup8CDA9B9E', + }, + }, + }); + }); + test('bucket with transfer acceleration turned on', () => { const stack = new cdk.Stack(); new s3.Bucket(stack, 'MyBucket', { From 3b2ef56c94ee913e751afafcd921a9eac57c4ebf Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Thu, 30 May 2024 15:13:44 -0700 Subject: [PATCH 04/12] Update integ.bucket-auto-delete-objects to cover the new setAutoDeleteObjectsLogGroup method --- ...3-bucket-auto-delete-objects.template.json | 14 +++++++++++ .../manifest.json | 6 +++++ .../tree.json | 25 +++++++++++++++++++ .../test/integ.bucket-auto-delete-objects.ts | 5 ++++ 4 files changed, 50 insertions(+) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.template.json index 3dade7cc0e247..9644a55534431 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.template.json @@ -144,6 +144,11 @@ " S3 bucket." ] ] + }, + "LoggingConfig": { + "LogGroup": { + "Ref": "MyLogGroup5C0DAD85" + } } }, "DependsOn": [ @@ -447,6 +452,15 @@ "DependsOn": [ "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" ] + }, + "MyLogGroup5C0DAD85": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "MyLogGroup", + "RetentionInDays": 731 + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" } }, "Mappings": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/manifest.json index fcdfba654b94f..74d87c6fdb89c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/manifest.json @@ -130,6 +130,12 @@ "data": "AWS679f53fac002430cb0da5b7982bd22872D164C4C" } ], + "/cdk-s3-bucket-auto-delete-objects/MyLogGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLogGroup5C0DAD85" + } + ], "/cdk-s3-bucket-auto-delete-objects/BootstrapVersion": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/tree.json index 4c90ee3e2e476..16d8b8c84c8c3 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/tree.json @@ -545,6 +545,31 @@ "version": "0.0.0" } }, + "MyLogGroup": { + "id": "MyLogGroup", + "path": "cdk-s3-bucket-auto-delete-objects/MyLogGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-s3-bucket-auto-delete-objects/MyLogGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Logs::LogGroup", + "aws:cdk:cloudformation:props": { + "logGroupName": "MyLogGroup", + "retentionInDays": 731 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_logs.CfnLogGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_logs.LogGroup", + "version": "0.0.0" + } + }, "BootstrapVersion": { "id": "BootstrapVersion", "path": "cdk-s3-bucket-auto-delete-objects/BootstrapVersion", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.ts index 9e2ef6ecbd938..d4992a3d2b12a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket-auto-delete-objects.ts @@ -3,6 +3,7 @@ import { App, CustomResource, CustomResourceProvider, RemovalPolicy, Stack, Stac import { IntegTest } from '@aws-cdk/integ-tests-alpha'; import { Construct } from 'constructs'; import * as s3 from 'aws-cdk-lib/aws-s3'; +import * as logs from 'aws-cdk-lib/aws-logs'; import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId } from 'aws-cdk-lib/custom-resources'; import { STANDARD_CUSTOM_RESOURCE_PROVIDER_RUNTIME } from '../../config'; @@ -55,6 +56,10 @@ class TestStack extends Stack { resources: [bucketThatWillBeRemoved.bucketArn], }), }); + + s3.Bucket.setAutoDeleteObjectsLogGroup(this, new logs.LogGroup(this, 'MyLogGroup', { + logGroupName: 'MyLogGroup', + })); } } From 91c4710771e2877fd92d44b6d043397d71954950 Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Fri, 31 May 2024 09:58:24 -0700 Subject: [PATCH 05/12] Update S3 README --- packages/aws-cdk-lib/aws-s3/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/aws-cdk-lib/aws-s3/README.md b/packages/aws-cdk-lib/aws-s3/README.md index 58b7084e620e2..eb652ae61920d 100644 --- a/packages/aws-cdk-lib/aws-s3/README.md +++ b/packages/aws-cdk-lib/aws-s3/README.md @@ -656,6 +656,23 @@ switching this to `false` in a CDK version _before_ `1.126.0` will lead to all objects in the bucket being deleted. Be sure to update your bucket resources by deploying with CDK version `1.126.0` or later **before** switching this value to `false`. +Enabling `autoDeleteObjects` creates a stack-wide singleton Lambda that is responsible for deleting objects. +To configure the lambda to use a different log group, use the `Bucket.setAutoDeleteObjectsLogGroup()` method: + +```ts +import * as logs from 'aws-cdk-lib/aws-logs'; + +const bucket = new s3.Bucket(this, 'MyTempFileBucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true, +}); + +s3.Bucket.setAutoDeleteObjectsLogGroup(this, new logs.LogGroup(this, 'MyLogGroup', { + logGroupName: 'MyLogGroup', + retention: logs.RetentionDays.FIVE_YEARS +})) +``` + ## Transfer Acceleration [Transfer Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/userguide/transfer-acceleration.html) can be configured to enable fast, easy, and secure transfers of files over long distances: From 21c771de1e5a788e328d858ad1d8dd343336da32 Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Mon, 10 Jun 2024 14:38:27 -0700 Subject: [PATCH 06/12] Update provider code gen logic to create useLogGroup() method --- .../lib/custom-resources-framework/classes.ts | 38 +++++++++++++++- .../custom-resource-provider-core.ts | 18 +++++++- .../custom-resource-provider.ts | 18 +++++++- packages/@aws-cdk/cx-api/FEATURE_FLAGS.md | 44 +++++++++++++++++-- 4 files changed, 108 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/custom-resource-handlers/lib/custom-resources-framework/classes.ts b/packages/@aws-cdk/custom-resource-handlers/lib/custom-resources-framework/classes.ts index 74b28a169467a..c6fc44e5200ef 100644 --- a/packages/@aws-cdk/custom-resource-handlers/lib/custom-resources-framework/classes.ts +++ b/packages/@aws-cdk/custom-resource-handlers/lib/custom-resources-framework/classes.ts @@ -276,6 +276,7 @@ export abstract class HandlerFrameworkClass extends ClassType { const idStatement = stmt.constVar(expr.ident('id'), expr.directCode('`${uniqueid}CustomResourceProvider`')); const stackFromScopeStatement = stmt.constVar(expr.ident('stack'), expr.directCode('Stack.of(scope)')); + const logContextKeyStatement = stmt.constVar(expr.ident('key'), expr.directCode('`${uniqueid}CustomResourceLogGroup`')); const getProviderMethod = this.addMethod({ name: 'getProvider', static: true, @@ -298,6 +299,34 @@ export abstract class HandlerFrameworkClass extends ClassType { stmt.ret(expr.directCode(`stack.node.tryFindChild(id) as ${this.type}`)), ); + const useLogGroupMethod = this.addMethod({ + name: 'useLogGroup', + static: true, + docs: { + summary: 'Set the log group to be used by the singleton provider', + }, + }); + useLogGroupMethod.addParameter({ + name: 'scope', + type: CONSTRUCTS_MODULE.Construct, + }); + useLogGroupMethod.addParameter({ + name: 'uniqueid', + type: Type.STRING, + }); + useLogGroupMethod.addParameter({ + name: 'logGroupName', + type: Type.STRING, + }); + useLogGroupMethod.addBody( + stackFromScopeStatement, + logContextKeyStatement, + expr.directCode('stack.node.addMetadata(key, logGroupName)'), + stmt.constVar(expr.ident('existing'), expr.directCode('this.getProvider(scope, uniqueid)')), + stmt.if_(expr.directCode('existing')) + .then(expr.directCode('existing.configureLambdaLogGroup(logGroupName)')), + ); + const getOrCreateProviderMethod = this.addMethod({ name: 'getOrCreateProvider', static: true, @@ -321,9 +350,14 @@ export abstract class HandlerFrameworkClass extends ClassType { }); getOrCreateProviderMethod.addBody( idStatement, - stmt.constVar(expr.ident('existing'), expr.directCode('this.getProvider(scope, uniqueid)')), stackFromScopeStatement, - stmt.ret(expr.directCode(`existing ?? new ${this.name}(stack, id, props)`)), + stmt.constVar(expr.ident('provider'), expr.directCode(`this.getProvider(scope, uniqueid) ?? new ${this.name}(stack, id, props)`)), + logContextKeyStatement, + stmt.constVar(expr.ident('logGroupMetadata'), + expr.directCode('stack.node.metadata.find(m => m.type === key)')), + stmt.if_(expr.directCode('logGroupMetadata?.data')) + .then(expr.directCode('provider.configureLambdaLogGroup(logGroupMetadata.data)')), + stmt.ret(expr.directCode('provider')), ); const superProps = new ObjectLiteral([ diff --git a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider-core.ts b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider-core.ts index 3b6e1bc036975..3c2f23a4a26e0 100644 --- a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider-core.ts +++ b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider-core.ts @@ -21,14 +21,28 @@ export class TestProvider extends CustomResourceProviderBase { return stack.node.tryFindChild(id) as TestProvider; } + /** + * Set the log group to be used by the singleton provider + */ + public static useLogGroup(scope: Construct, uniqueid: string, logGroupName: string): void { + const stack = Stack.of(scope); + const key = `${uniqueid}CustomResourceLogGroup`; + stack.node.addMetadata(key, logGroupName); + const existing = this.getProvider(scope, uniqueid); + if (existing) existing.configureLambdaLogGroup(logGroupName); + } + /** * Returns a stack-level singleton for the custom resource provider. */ public static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): TestProvider { const id = `${uniqueid}CustomResourceProvider`; - const existing = this.getProvider(scope, uniqueid); const stack = Stack.of(scope); - return existing ?? new TestProvider(stack, id, props); + const provider = this.getProvider(scope, uniqueid) ?? new TestProvider(stack, id, props); + const key = `${uniqueid}CustomResourceLogGroup`; + const logGroupMetadata = stack.node.metadata.find(m => m.type === key); + if (logGroupMetadata?.data) provider.configureLambdaLogGroup(logGroupMetadata.data); + return provider; } public constructor(scope: Construct, id: string, props?: CustomResourceProviderOptions) { diff --git a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider.ts b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider.ts index 5d606d9709003..673cd5cdbac53 100644 --- a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider.ts +++ b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/python-runtime/custom-resource-provider.ts @@ -20,14 +20,28 @@ export class TestProvider extends CustomResourceProviderBase { return stack.node.tryFindChild(id) as TestProvider; } + /** + * Set the log group to be used by the singleton provider + */ + public static useLogGroup(scope: Construct, uniqueid: string, logGroupName: string): void { + const stack = Stack.of(scope); + const key = `${uniqueid}CustomResourceLogGroup`; + stack.node.addMetadata(key, logGroupName); + const existing = this.getProvider(scope, uniqueid); + if (existing) existing.configureLambdaLogGroup(logGroupName); + } + /** * Returns a stack-level singleton for the custom resource provider. */ public static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): TestProvider { const id = `${uniqueid}CustomResourceProvider`; - const existing = this.getProvider(scope, uniqueid); const stack = Stack.of(scope); - return existing ?? new TestProvider(stack, id, props); + const provider = this.getProvider(scope, uniqueid) ?? new TestProvider(stack, id, props); + const key = `${uniqueid}CustomResourceLogGroup`; + const logGroupMetadata = stack.node.metadata.find(m => m.type === key); + if (logGroupMetadata?.data) provider.configureLambdaLogGroup(logGroupMetadata.data); + return provider; } public constructor(scope: Construct, id: string, props?: CustomResourceProviderOptions) { diff --git a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md index 3678e750e3617..590205503da37 100644 --- a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md +++ b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md @@ -68,7 +68,9 @@ Flags come in three types: | [@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2](#aws-cdkaws-codepipelinedefaultpipelinetypetov2) | Enables Pipeline to set the default pipeline type to V2. | 2.133.0 | (default) | | [@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope](#aws-cdkaws-kmsreducecrossaccountregionpolicyscope) | When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only. | 2.134.0 | (fix) | | [@aws-cdk/aws-eks:nodegroupNameAttribute](#aws-cdkaws-eksnodegroupnameattribute) | When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix. | 2.139.0 | (fix) | -| [@aws-cdk/aws-ec2:ebsDefaultGp3Volume](#aws-cdkaws-ec2ebsdefaultgp3volume) | When enabled, the default volume type of the EBS volume will be GP3 | V2NEXT | (default) | +| [@aws-cdk/aws-ec2:ebsDefaultGp3Volume](#aws-cdkaws-ec2ebsdefaultgp3volume) | When enabled, the default volume type of the EBS volume will be GP3 | 2.140.0 | (default) | +| [@aws-cdk/pipelines:reduceAssetRoleTrustScope](#aws-cdkpipelinesreduceassetroletrustscope) | Remove the root account principal from PipelineAssetsFileRole trust policy | 2.141.0 | (default) | +| [@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm](#aws-cdkaws-ecsremovedefaultdeploymentalarm) | When enabled, remove default deployment alarm settings | 2.143.0 | (default) | @@ -128,7 +130,8 @@ The following json shows the current recommended set of flags, as `cdk init` wou "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true, "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true, "@aws-cdk/aws-eks:nodegroupNameAttribute": true, - "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true } } ``` @@ -171,6 +174,7 @@ are migrating a v1 CDK project to v2, explicitly set any of these flags which do | [@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId](#aws-cdkaws-apigatewayusageplankeyorderinsensitiveid) | Allow adding/removing multiple UsagePlanKeys independently | (fix) | 1.98.0 | `false` | `true` | | [@aws-cdk/aws-lambda:recognizeVersionProps](#aws-cdkaws-lambdarecognizeversionprops) | Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. | (fix) | 1.106.0 | `false` | `true` | | [@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2\_2021](#aws-cdkaws-cloudfrontdefaultsecuritypolicytlsv12_2021) | Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default. | (fix) | 1.117.0 | `false` | `true` | +| [@aws-cdk/pipelines:reduceAssetRoleTrustScope](#aws-cdkpipelinesreduceassetroletrustscope) | Remove the root account principal from PipelineAssetsFileRole trust policy | (default) | | `false` | `true` | @@ -185,7 +189,8 @@ Here is an example of a `cdk.json` file that restores v1 behavior for these flag "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, "@aws-cdk/aws-lambda:recognizeVersionProps": false, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": false } } ``` @@ -1293,9 +1298,40 @@ When this featuer flag is enabled, the default volume type of the EBS volume wil | Since | Default | Recommended | | ----- | ----- | ----- | | (not in v1) | | | -| V2NEXT | `false` | `true` | +| 2.140.0 | `false` | `true` | **Compatibility with old behavior:** Pass `volumeType: EbsDeviceVolumeType.GENERAL_PURPOSE_SSD` to `Volume` construct to restore the previous behavior. +### @aws-cdk/pipelines:reduceAssetRoleTrustScope + +*Remove the root account principal from PipelineAssetsFileRole trust policy* (default) + +When this feature flag is enabled, the root account principal will not be added to the trust policy of asset role. +When this feature flag is disabled, it will keep the root account principal in the trust policy. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.141.0 | `true` | `true` | + +**Compatibility with old behavior:** Disable the feature flag to add the root account principal back + + +### @aws-cdk/aws-ecs:removeDefaultDeploymentAlarm + +*When enabled, remove default deployment alarm settings* (default) + +When this featuer flag is enabled, remove the default deployment alarm settings when creating a AWS ECS service. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.143.0 | `false` | `true` | + +**Compatibility with old behavior:** Set AWS::ECS::Service 'DeploymentAlarms' manually to restore the previous behavior. + + From fba53e8ebd67331dd8e5d13eada6ade7b6746521 Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Mon, 10 Jun 2024 14:43:40 -0700 Subject: [PATCH 07/12] allow setAutoDeleteObjectsLogGroup to be called before bucket creation --- packages/aws-cdk-lib/aws-s3/lib/bucket.ts | 7 +--- .../aws-cdk-lib/aws-s3/test/bucket.test.ts | 37 +++++++++++++------ 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts index c874e47c82eab..671773c5003cc 100644 --- a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts +++ b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts @@ -1898,12 +1898,7 @@ export class Bucket extends BucketBase { * @param logGroup the log group to use on the lambda. */ public static setAutoDeleteObjectsLogGroup(scope: Construct, logGroup: logs.ILogGroup): void { - const provider = AutoDeleteObjectsProvider.getProvider(scope, AUTO_DELETE_OBJECTS_RESOURCE_TYPE); - - if (provider === undefined) { - throw new Error('Requires at least one bucket with \'autoDeleteObjects: true\'. None is found.'); - } - provider.configureLambdaLogGroup(logGroup.logGroupName); + AutoDeleteObjectsProvider.useLogGroup(scope, AUTO_DELETE_OBJECTS_RESOURCE_TYPE, logGroup.logGroupName); } public readonly bucketArn: string; diff --git a/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts b/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts index 4fa9abdf1ffb8..d1a485a1534ef 100644 --- a/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts +++ b/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts @@ -3494,22 +3494,14 @@ describe('bucket', () => { })).toThrow(/Cannot use \'autoDeleteObjects\' property on a bucket without setting removal policy to \'DESTROY\'/); }); - test('setAutoDeleteObjectsLogGroup throws if no bucket has autoDeleteObjects: true in stack', () => { - const stack = new cdk.Stack(); - - new s3.Bucket(stack, 'MyBucket', { }); - - expect(() => s3.Bucket.setAutoDeleteObjectsLogGroup(stack, new logs.LogGroup(stack, 'MyLogGroup', {}))) - .toThrow(/Requires at least one bucket with 'autoDeleteObjects: true'. None is found./); - }); - - test('setAutoDeleteObjectsLogGroup to update AutoDeleteObjectsProvider LoggingConfig', () => { + test('setAutoDeleteObjectsLogGroup to update AutoDeleteObjectsProvider LoggingConfig after Bucket creation', () => { const stack = new cdk.Stack(); new s3.Bucket(stack, 'MyBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, autoDeleteObjects: true, }); + s3.Bucket.setAutoDeleteObjectsLogGroup(stack, new logs.LogGroup(stack, 'FirstLogGroup', { logGroupName: 'MyFirstLogGroup', })); @@ -3526,16 +3518,39 @@ describe('bucket', () => { }); }); - test('setAutoDeleteObjectsLogGroup multiple times should take the latest Log Group', () => { + test('setAutoDeleteObjectsLogGroup before Bucket creation', () => { const stack = new cdk.Stack(); + s3.Bucket.setAutoDeleteObjectsLogGroup(stack, new logs.LogGroup(stack, 'FirstLogGroup', { + logGroupName: 'MyFirstLogGroup', + })); new s3.Bucket(stack, 'MyBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, autoDeleteObjects: true, }); + + Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', { + LogGroupName: 'MyFirstLogGroup', + }); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + LoggingConfig: { + LogGroup: { + 'Ref': 'FirstLogGroupFF5C2AA0', + }, + }, + }); + }); + + test('setAutoDeleteObjectsLogGroup multiple times should take the latest Log Group', () => { + const stack = new cdk.Stack(); + s3.Bucket.setAutoDeleteObjectsLogGroup(stack, new logs.LogGroup(stack, 'FirstLogGroup', { logGroupName: 'MyFirstLogGroup', })); + new s3.Bucket(stack, 'MyBucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true, + }); s3.Bucket.setAutoDeleteObjectsLogGroup(stack, new logs.LogGroup(stack, 'SecondLogGroup', { logGroupName: 'MySecondLogGroup', })); From cebc4f3bc738a7e3d43bfdbdb1bb4ab2c0b5458d Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Mon, 10 Jun 2024 14:54:46 -0700 Subject: [PATCH 08/12] update setAutoDeleteObjectsLogGroup to take a Stack instead of a Construct scope --- packages/aws-cdk-lib/aws-s3/lib/bucket.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts index 671773c5003cc..429a5f7cb9505 100644 --- a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts +++ b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts @@ -1887,18 +1887,17 @@ export class Bucket extends BucketBase { } /** - * Set the log group on the singleton AutoDeleteObjects provider lambda. - * Note: Calling this multiple times will override the previously set log group + * Set the log group on the stack wide singleton AutoDeleteObjects provider lambda. * * In the case of no buckets with `autoDeleteObjects: true` exist in the stack, * this will throw an exception as no AutoDeleteObjects provider lambda will exist * in the stack. * - * @param scope the stack with bucket(s) with `autoDeleteObjects: true`. + * @param stack the stack with the singleton AutoDeleteObjects provider lambda. * @param logGroup the log group to use on the lambda. */ - public static setAutoDeleteObjectsLogGroup(scope: Construct, logGroup: logs.ILogGroup): void { - AutoDeleteObjectsProvider.useLogGroup(scope, AUTO_DELETE_OBJECTS_RESOURCE_TYPE, logGroup.logGroupName); + public static setAutoDeleteObjectsLogGroup(stack: Stack, logGroup: logs.ILogGroup): void { + AutoDeleteObjectsProvider.useLogGroup(stack, AUTO_DELETE_OBJECTS_RESOURCE_TYPE, logGroup.logGroupName); } public readonly bucketArn: string; From 90520ad92333b9a15d9b5d1f694340e0c37d934c Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Wed, 12 Jun 2024 10:08:18 -0700 Subject: [PATCH 09/12] resolve conflicts --- .../custom-resource-provider-core.ts | 27 +++++++++++++++++-- .../node-runtime/custom-resource-provider.ts | 27 +++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/node-runtime/custom-resource-provider-core.ts b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/node-runtime/custom-resource-provider-core.ts index 7d233b55451bd..3cc55b91da98d 100644 --- a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/node-runtime/custom-resource-provider-core.ts +++ b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/node-runtime/custom-resource-provider-core.ts @@ -12,14 +12,37 @@ export class TestProvider extends CustomResourceProviderBase { return this.getOrCreateProvider(scope, uniqueid, props).serviceToken; } + /** + * Returns the stack-level singleton provider or undefined + */ + public static getProvider(scope: Construct, uniqueid: string): TestProvider { + const id = `${uniqueid}CustomResourceProvider`; + const stack = Stack.of(scope); + return stack.node.tryFindChild(id) as TestProvider; + } + + /** + * Set the log group to be used by the singleton provider + */ + public static useLogGroup(scope: Construct, uniqueid: string, logGroupName: string): void { + const stack = Stack.of(scope); + const key = `${uniqueid}CustomResourceLogGroup`; + stack.node.addMetadata(key, logGroupName); + const existing = this.getProvider(scope, uniqueid); + if (existing) existing.configureLambdaLogGroup(logGroupName); + } + /** * Returns a stack-level singleton for the custom resource provider. */ public static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): TestProvider { const id = `${uniqueid}CustomResourceProvider`; const stack = Stack.of(scope); - const existing = stack.node.tryFindChild(id) as TestProvider; - return existing ?? new TestProvider(stack, id, props); + const provider = this.getProvider(scope, uniqueid) ?? new TestProvider(stack, id, props); + const key = `${uniqueid}CustomResourceLogGroup`; + const logGroupMetadata = stack.node.metadata.find(m => m.type === key); + if (logGroupMetadata?.data) provider.configureLambdaLogGroup(logGroupMetadata.data); + return provider; } public constructor(scope: Construct, id: string, props?: CustomResourceProviderOptions) { diff --git a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/node-runtime/custom-resource-provider.ts b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/node-runtime/custom-resource-provider.ts index 8c45d66c40e93..a3fe3b02e15a6 100644 --- a/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/node-runtime/custom-resource-provider.ts +++ b/packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/expected/node-runtime/custom-resource-provider.ts @@ -11,14 +11,37 @@ export class TestProvider extends CustomResourceProviderBase { return this.getOrCreateProvider(scope, uniqueid, props).serviceToken; } + /** + * Returns the stack-level singleton provider or undefined + */ + public static getProvider(scope: Construct, uniqueid: string): TestProvider { + const id = `${uniqueid}CustomResourceProvider`; + const stack = Stack.of(scope); + return stack.node.tryFindChild(id) as TestProvider; + } + + /** + * Set the log group to be used by the singleton provider + */ + public static useLogGroup(scope: Construct, uniqueid: string, logGroupName: string): void { + const stack = Stack.of(scope); + const key = `${uniqueid}CustomResourceLogGroup`; + stack.node.addMetadata(key, logGroupName); + const existing = this.getProvider(scope, uniqueid); + if (existing) existing.configureLambdaLogGroup(logGroupName); + } + /** * Returns a stack-level singleton for the custom resource provider. */ public static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): TestProvider { const id = `${uniqueid}CustomResourceProvider`; const stack = Stack.of(scope); - const existing = stack.node.tryFindChild(id) as TestProvider; - return existing ?? new TestProvider(stack, id, props); + const provider = this.getProvider(scope, uniqueid) ?? new TestProvider(stack, id, props); + const key = `${uniqueid}CustomResourceLogGroup`; + const logGroupMetadata = stack.node.metadata.find(m => m.type === key); + if (logGroupMetadata?.data) provider.configureLambdaLogGroup(logGroupMetadata.data); + return provider; } public constructor(scope: Construct, id: string, props?: CustomResourceProviderOptions) { From 3b7e4de0b6e2b10f8586e012270f25ac82af52fd Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Wed, 12 Jun 2024 10:51:12 -0700 Subject: [PATCH 10/12] update unit test with latest changes from main --- .../custom-resource-provider/custom-resource-provider.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/core/test/custom-resource-provider/custom-resource-provider.test.ts b/packages/aws-cdk-lib/core/test/custom-resource-provider/custom-resource-provider.test.ts index 279fabe9e7032..2bb620eef01cd 100644 --- a/packages/aws-cdk-lib/core/test/custom-resource-provider/custom-resource-provider.test.ts +++ b/packages/aws-cdk-lib/core/test/custom-resource-provider/custom-resource-provider.test.ts @@ -401,7 +401,7 @@ describe('custom resource provider', () => { // WHEN const provider = CustomResourceProvider.getOrCreateProvider(stack, 'Custom:MyResourceType', { codeDirectory: TEST_HANDLER, - runtime: STANDARD_PROVIDER, + runtime: DEFAULT_PROVIDER_RUNTIME, policyStatements: [ { statement1: 123 }, { statement2: { foo: 111 } }, From ca1acbe36a430c383f196e433caba5e38a95d910 Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Thu, 13 Jun 2024 15:26:57 -0700 Subject: [PATCH 11/12] revert unintended change in cx-api --- packages/@aws-cdk/cx-api/FEATURE_FLAGS.md | 44 +++-------------------- 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md index 590205503da37..3678e750e3617 100644 --- a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md +++ b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md @@ -68,9 +68,7 @@ Flags come in three types: | [@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2](#aws-cdkaws-codepipelinedefaultpipelinetypetov2) | Enables Pipeline to set the default pipeline type to V2. | 2.133.0 | (default) | | [@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope](#aws-cdkaws-kmsreducecrossaccountregionpolicyscope) | When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only. | 2.134.0 | (fix) | | [@aws-cdk/aws-eks:nodegroupNameAttribute](#aws-cdkaws-eksnodegroupnameattribute) | When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix. | 2.139.0 | (fix) | -| [@aws-cdk/aws-ec2:ebsDefaultGp3Volume](#aws-cdkaws-ec2ebsdefaultgp3volume) | When enabled, the default volume type of the EBS volume will be GP3 | 2.140.0 | (default) | -| [@aws-cdk/pipelines:reduceAssetRoleTrustScope](#aws-cdkpipelinesreduceassetroletrustscope) | Remove the root account principal from PipelineAssetsFileRole trust policy | 2.141.0 | (default) | -| [@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm](#aws-cdkaws-ecsremovedefaultdeploymentalarm) | When enabled, remove default deployment alarm settings | 2.143.0 | (default) | +| [@aws-cdk/aws-ec2:ebsDefaultGp3Volume](#aws-cdkaws-ec2ebsdefaultgp3volume) | When enabled, the default volume type of the EBS volume will be GP3 | V2NEXT | (default) | @@ -130,8 +128,7 @@ The following json shows the current recommended set of flags, as `cdk init` wou "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true, "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true, "@aws-cdk/aws-eks:nodegroupNameAttribute": true, - "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true, - "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true } } ``` @@ -174,7 +171,6 @@ are migrating a v1 CDK project to v2, explicitly set any of these flags which do | [@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId](#aws-cdkaws-apigatewayusageplankeyorderinsensitiveid) | Allow adding/removing multiple UsagePlanKeys independently | (fix) | 1.98.0 | `false` | `true` | | [@aws-cdk/aws-lambda:recognizeVersionProps](#aws-cdkaws-lambdarecognizeversionprops) | Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. | (fix) | 1.106.0 | `false` | `true` | | [@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2\_2021](#aws-cdkaws-cloudfrontdefaultsecuritypolicytlsv12_2021) | Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default. | (fix) | 1.117.0 | `false` | `true` | -| [@aws-cdk/pipelines:reduceAssetRoleTrustScope](#aws-cdkpipelinesreduceassetroletrustscope) | Remove the root account principal from PipelineAssetsFileRole trust policy | (default) | | `false` | `true` | @@ -189,8 +185,7 @@ Here is an example of a `cdk.json` file that restores v1 behavior for these flag "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, "@aws-cdk/aws-lambda:recognizeVersionProps": false, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false, - "@aws-cdk/pipelines:reduceAssetRoleTrustScope": false + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false } } ``` @@ -1298,40 +1293,9 @@ When this featuer flag is enabled, the default volume type of the EBS volume wil | Since | Default | Recommended | | ----- | ----- | ----- | | (not in v1) | | | -| 2.140.0 | `false` | `true` | +| V2NEXT | `false` | `true` | **Compatibility with old behavior:** Pass `volumeType: EbsDeviceVolumeType.GENERAL_PURPOSE_SSD` to `Volume` construct to restore the previous behavior. -### @aws-cdk/pipelines:reduceAssetRoleTrustScope - -*Remove the root account principal from PipelineAssetsFileRole trust policy* (default) - -When this feature flag is enabled, the root account principal will not be added to the trust policy of asset role. -When this feature flag is disabled, it will keep the root account principal in the trust policy. - - -| Since | Default | Recommended | -| ----- | ----- | ----- | -| (not in v1) | | | -| 2.141.0 | `true` | `true` | - -**Compatibility with old behavior:** Disable the feature flag to add the root account principal back - - -### @aws-cdk/aws-ecs:removeDefaultDeploymentAlarm - -*When enabled, remove default deployment alarm settings* (default) - -When this featuer flag is enabled, remove the default deployment alarm settings when creating a AWS ECS service. - - -| Since | Default | Recommended | -| ----- | ----- | ----- | -| (not in v1) | | | -| 2.143.0 | `false` | `true` | - -**Compatibility with old behavior:** Set AWS::ECS::Service 'DeploymentAlarms' manually to restore the previous behavior. - - From 5d12bf3de66cb7420683a33f809e7c50494889f8 Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Fri, 14 Jun 2024 13:57:43 -0700 Subject: [PATCH 12/12] update doc --- packages/aws-cdk-lib/aws-s3/lib/bucket.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts index 429a5f7cb9505..7212e854bbc15 100644 --- a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts +++ b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts @@ -1889,10 +1889,6 @@ export class Bucket extends BucketBase { /** * Set the log group on the stack wide singleton AutoDeleteObjects provider lambda. * - * In the case of no buckets with `autoDeleteObjects: true` exist in the stack, - * this will throw an exception as no AutoDeleteObjects provider lambda will exist - * in the stack. - * * @param stack the stack with the singleton AutoDeleteObjects provider lambda. * @param logGroup the log group to use on the lambda. */