konokenj.cdk-api-mcp-server 0.29.0__py3-none-any.whl → 0.31.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. cdk_api_mcp_server/__about__.py +1 -1
  2. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-lambda-python-alpha/README.md +17 -4
  3. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api-dualstack.ts +4 -3
  4. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api.ts +4 -2
  5. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.stage.ts +20 -7
  6. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-authorizers/integ.iam.ts +38 -34
  7. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.sqs.ts +71 -58
  8. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-backup/README.md +2 -0
  9. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-backup/integ.backup.ts +12 -1
  10. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/README.md +32 -0
  11. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/integ.alarm-and-dashboard.ts +1 -0
  12. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/integ.math-alarm-and-dashboard.ts +4 -0
  13. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codedeploy/integ.deployment-config.ts +4 -15
  14. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codedeploy/integ.deployment-group.ts +218 -40
  15. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/integ.pipeline-elastic-beanstalk-deploy.ts +1 -1
  16. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ec2/README.md +13 -0
  17. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ec2/integ.client-vpn-endpoint-client-route-enforcement.ts +68 -0
  18. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/integ.helm-chart-logging.ts +55 -0
  19. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/README.md +15 -0
  20. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/integ.log-retention.ts +8 -2
  21. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/README.md +23 -13
  22. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.cluster-snapshot.ts +3 -71
  23. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.instance-engine-lifecycle-support.ts +53 -0
  24. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-notifications/integ.bucket-notifications.ts +42 -80
  25. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.call-aws-service-cross-region-lambda.ts +97 -0
  26. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.start-job-run.ts +51 -106
  27. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +156 -156
  28. {konokenj_cdk_api_mcp_server-0.29.0.dist-info → konokenj_cdk_api_mcp_server-0.31.0.dist-info}/METADATA +2 -2
  29. {konokenj_cdk_api_mcp_server-0.29.0.dist-info → konokenj_cdk_api_mcp_server-0.31.0.dist-info}/RECORD +32 -28
  30. {konokenj_cdk_api_mcp_server-0.29.0.dist-info → konokenj_cdk_api_mcp_server-0.31.0.dist-info}/WHEEL +0 -0
  31. {konokenj_cdk_api_mcp_server-0.29.0.dist-info → konokenj_cdk_api_mcp_server-0.31.0.dist-info}/entry_points.txt +0 -0
  32. {konokenj_cdk_api_mcp_server-0.29.0.dist-info → konokenj_cdk_api_mcp_server-0.31.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,62 +1,240 @@
1
- import * as path from 'path';
2
1
  import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
3
- import * as lambda from 'aws-cdk-lib/aws-lambda';
2
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
+ import * as ecs from 'aws-cdk-lib/aws-ecs';
4
+ import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
4
5
  import * as cdk from 'aws-cdk-lib';
6
+ import * as integ from '@aws-cdk/integ-tests-alpha';
5
7
  import * as codedeploy from 'aws-cdk-lib/aws-codedeploy';
6
- import { STANDARD_NODEJS_RUNTIME } from '../../../config';
7
8
 
8
- const app = new cdk.App({
9
- postCliContext: {
10
- '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
9
+ /**
10
+ * Follow these instructions to manually test running a CodeDeploy deployment with the resources provisioned in this stack:
11
+ *
12
+ * 1. Deploy the stack:
13
+ ```
14
+ $ cdk deploy --app 'node integ.deployment-group.js' aws-cdk-codedeploy-ecs-dg
15
+ ```
16
+ *
17
+ * 2. Create a file called `appspec.json` with the following contents, replacing the placeholders with output values from the deployed stack:
18
+ ```
19
+ {
20
+ "version": 0.0,
21
+ "Resources": [
22
+ {
23
+ "TargetService": {
24
+ "Type": "AWS::ECS::Service",
25
+ "Properties": {
26
+ "TaskDefinition": "<PLACEHOLDER - NEW TASK DEFINITION>",
27
+ "LoadBalancerInfo": {
28
+ "ContainerName": "Container",
29
+ "ContainerPort": 80
30
+ },
31
+ "PlatformVersion": "LATEST",
32
+ "NetworkConfiguration": {
33
+ "awsvpcConfiguration": {
34
+ "subnets": [
35
+ "<PLACEHOLDER - SUBNET 1 ID>",
36
+ "<PLACEHOLDER - SUBNET 2 ID>",
37
+ ],
38
+ "securityGroups": [
39
+ "<PLACEHOLDER - SECURITY GROUP ID>"
40
+ ],
41
+ "assignPublicIp": "DISABLED"
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ ]
48
+ }
49
+ ```
50
+ *
51
+ * 3. Start the deployment:
52
+ ```
53
+ $ appspec=$(jq -R -s '.' < appspec.json | sed 's/\\n//g')
54
+ $ aws deploy create-deployment \
55
+ --application-name <PLACEHOLDER - CODEDEPLOY APPLICATION NAME> \
56
+ --deployment-group-name <PLACEHOLDER - CODEDEPLOY DEPLOYMENT GROUP NAME> \
57
+ --description "AWS CDK integ test" \
58
+ --revision revisionType=AppSpecContent,appSpecContent={content="$appspec"}
59
+ ```
60
+ *
61
+ * 4. Wait for the deployment to complete successfully, providing the deployment ID from the previous step:
62
+ ```
63
+ $ aws deploy wait deployment-successful --deployment-id <PLACEHOLDER - DEPLOYMENT ID>
64
+ ```
65
+ *
66
+ * 5. Destroy the stack:
67
+ ```
68
+ $ cdk destroy --app 'node integ.deployment-group.js' aws-cdk-codedeploy-ecs-dg
69
+ ```
70
+ */
71
+
72
+ const app = new cdk.App();
73
+ const stack = new cdk.Stack(app, 'aws-cdk-codedeploy-ecs-dg');
74
+
75
+ // Network infrastructure
76
+ const vpc = new ec2.Vpc(stack, 'VPC', { maxAzs: 2, restrictDefaultSecurityGroup: false });
77
+
78
+ // ECS service
79
+ const cluster = new ecs.Cluster(stack, 'EcsCluster', {
80
+ vpc,
81
+ });
82
+ const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef');
83
+ taskDefinition.addContainer('Container', {
84
+ image: ecs.ContainerImage.fromRegistry('public.ecr.aws/ecs-sample-image/amazon-ecs-sample:latest'),
85
+ portMappings: [{ containerPort: 80 }],
86
+ });
87
+ const service = new ecs.FargateService(stack, 'FargateService', {
88
+ cluster,
89
+ taskDefinition,
90
+ deploymentController: {
91
+ type: ecs.DeploymentControllerType.CODE_DEPLOY,
11
92
  },
12
93
  });
13
- const stack = new cdk.Stack(app, 'aws-cdk-codedeploy-lambda');
14
94
 
15
- const handler = new lambda.Function(stack, 'Handler', {
16
- code: lambda.Code.fromAsset(path.join(__dirname, 'handler')),
17
- handler: 'index.handler',
18
- runtime: STANDARD_NODEJS_RUNTIME,
95
+ // A second task definition for testing a CodeDeploy deployment of the ECS service to a new task definition
96
+ const taskDefinition2 = new ecs.FargateTaskDefinition(stack, 'TaskDef2');
97
+ taskDefinition2.addContainer('Container', {
98
+ image: ecs.ContainerImage.fromRegistry('public.ecr.aws/ecs-sample-image/amazon-ecs-sample:latest'),
99
+ portMappings: [{ containerPort: 80 }],
19
100
  });
20
- const version = handler.currentVersion;
21
- const blueGreenAlias = new lambda.Alias(stack, 'Alias', {
22
- aliasName: 'alias',
23
- version,
101
+ service.node.addDependency(taskDefinition2);
102
+
103
+ // Load balancer
104
+ const loadBalancer = new elbv2.ApplicationLoadBalancer(stack, 'ServiceLB', {
105
+ vpc,
106
+ internetFacing: false,
24
107
  });
25
108
 
26
- const preHook = new lambda.Function(stack, 'PreHook', {
27
- code: lambda.Code.fromAsset(path.join(__dirname, 'preHook')),
28
- handler: 'index.handler',
29
- runtime: STANDARD_NODEJS_RUNTIME,
109
+ // Listeners
110
+ const prodListener = loadBalancer.addListener('ProdListener', {
111
+ port: 80, // port for production traffic
112
+ protocol: elbv2.ApplicationProtocol.HTTP,
30
113
  });
31
- const postHook = new lambda.Function(stack, 'PostHook', {
32
- code: lambda.Code.fromAsset(path.join(__dirname, 'postHook')),
33
- handler: 'index.handler',
34
- runtime: STANDARD_NODEJS_RUNTIME,
114
+ const testListener = loadBalancer.addListener('TestListener', {
115
+ port: 9002, // port for testing
116
+ protocol: elbv2.ApplicationProtocol.HTTP,
35
117
  });
36
118
 
37
- new codedeploy.LambdaDeploymentGroup(stack, 'BlueGreenDeployment', {
38
- alias: blueGreenAlias,
39
- deploymentConfig: codedeploy.LambdaDeploymentConfig.LINEAR_10PERCENT_EVERY_1MINUTE,
40
- alarms: [
41
- new cloudwatch.Alarm(stack, 'BlueGreenErrors', {
42
- comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
43
- threshold: 1,
44
- evaluationPeriods: 1,
45
- metric: blueGreenAlias.metricErrors(),
119
+ // Target groups
120
+ const blueTG = prodListener.addTargets('BlueTG', {
121
+ port: 80,
122
+ protocol: elbv2.ApplicationProtocol.HTTP,
123
+ targets: [
124
+ service.loadBalancerTarget({
125
+ containerName: 'Container',
126
+ containerPort: 80,
46
127
  }),
47
128
  ],
48
- preHook,
49
- postHook,
129
+ deregistrationDelay: cdk.Duration.seconds(30),
130
+ healthCheck: {
131
+ interval: cdk.Duration.seconds(5),
132
+ healthyHttpCodes: '200',
133
+ healthyThresholdCount: 2,
134
+ unhealthyThresholdCount: 3,
135
+ timeout: cdk.Duration.seconds(4),
136
+ },
50
137
  });
51
138
 
52
- const secondAlias = new lambda.Alias(stack, 'SecondAlias', {
53
- aliasName: 'secondAlias',
54
- version,
139
+ const greenTG = new elbv2.ApplicationTargetGroup(stack, 'GreenTG', {
140
+ vpc,
141
+ port: 80,
142
+ protocol: elbv2.ApplicationProtocol.HTTP,
143
+ targetType: elbv2.TargetType.IP,
144
+ deregistrationDelay: cdk.Duration.seconds(30),
145
+ healthCheck: {
146
+ interval: cdk.Duration.seconds(5),
147
+ healthyHttpCodes: '200',
148
+ healthyThresholdCount: 2,
149
+ unhealthyThresholdCount: 3,
150
+ timeout: cdk.Duration.seconds(4),
151
+ },
152
+ });
153
+
154
+ testListener.addTargetGroups('GreenTGTest', {
155
+ targetGroups: [greenTG],
55
156
  });
56
157
 
57
- new codedeploy.LambdaDeploymentGroup(stack, 'SecondDeployment', {
58
- alias: secondAlias,
59
- deploymentConfig: codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_5MINUTES,
158
+ prodListener.node.addDependency(greenTG);
159
+ testListener.node.addDependency(blueTG);
160
+ service.node.addDependency(testListener);
161
+ service.node.addDependency(greenTG);
162
+
163
+ // Alarms: monitor 500s and unhealthy hosts on target groups
164
+ const blueUnhealthyHosts = new cloudwatch.Alarm(stack, 'BlueUnhealthyHosts', {
165
+ alarmName: stack.stackName + '-Unhealthy-Hosts-Blue',
166
+ metric: blueTG.metricUnhealthyHostCount(),
167
+ threshold: 1,
168
+ evaluationPeriods: 2,
169
+ });
170
+
171
+ const blueApiFailure = new cloudwatch.Alarm(stack, 'Blue5xx', {
172
+ alarmName: stack.stackName + '-Http-500-Blue',
173
+ metric: blueTG.metricHttpCodeTarget(
174
+ elbv2.HttpCodeTarget.TARGET_5XX_COUNT,
175
+ { period: cdk.Duration.minutes(1) },
176
+ ),
177
+ threshold: 1,
178
+ evaluationPeriods: 1,
179
+ });
180
+
181
+ const greenUnhealthyHosts = new cloudwatch.Alarm(stack, 'GreenUnhealthyHosts', {
182
+ alarmName: stack.stackName + '-Unhealthy-Hosts-Green',
183
+ metric: greenTG.metricUnhealthyHostCount(),
184
+ threshold: 1,
185
+ evaluationPeriods: 2,
186
+ });
187
+
188
+ const greenApiFailure = new cloudwatch.Alarm(stack, 'Green5xx', {
189
+ alarmName: stack.stackName + '-Http-500-Green',
190
+ metric: greenTG.metricHttpCodeTarget(
191
+ elbv2.HttpCodeTarget.TARGET_5XX_COUNT,
192
+ { period: cdk.Duration.minutes(1) },
193
+ ),
194
+ threshold: 1,
195
+ evaluationPeriods: 1,
196
+ });
197
+
198
+ // Deployment group
199
+ const deploymentConfig = new codedeploy.EcsDeploymentConfig(stack, 'CanaryConfig', {
200
+ trafficRouting: codedeploy.TrafficRouting.timeBasedCanary({
201
+ interval: cdk.Duration.minutes(1),
202
+ percentage: 20,
203
+ }),
204
+ });
205
+
206
+ const dg = new codedeploy.EcsDeploymentGroup(stack, 'BlueGreenDG', {
207
+ alarms: [
208
+ blueUnhealthyHosts,
209
+ blueApiFailure,
210
+ greenUnhealthyHosts,
211
+ greenApiFailure,
212
+ ],
213
+ service,
214
+ blueGreenDeploymentConfig: {
215
+ blueTargetGroup: blueTG,
216
+ greenTargetGroup: greenTG,
217
+ listener: prodListener,
218
+ testListener,
219
+ terminationWaitTime: cdk.Duration.minutes(1),
220
+ },
221
+ deploymentConfig,
222
+ autoRollback: {
223
+ stoppedDeployment: true,
224
+ },
225
+ ignoreAlarmConfiguration: true,
226
+ });
227
+
228
+ // Outputs to use for manual testing
229
+ new cdk.CfnOutput(stack, 'NewTaskDefinition', { value: taskDefinition2.taskDefinitionArn });
230
+ new cdk.CfnOutput(stack, 'Subnet1Id', { value: vpc.privateSubnets[0].subnetId });
231
+ new cdk.CfnOutput(stack, 'Subnet2Id', { value: vpc.privateSubnets[1].subnetId });
232
+ new cdk.CfnOutput(stack, 'SecurityGroupId', { value: service.connections.securityGroups[0].securityGroupId });
233
+ new cdk.CfnOutput(stack, 'CodeDeployApplicationName', { value: dg.application.applicationName });
234
+ new cdk.CfnOutput(stack, 'CodeDeployDeploymentGroupName', { value: dg.deploymentGroupName });
235
+
236
+ new integ.IntegTest(app, 'EcsDeploymentGroupTest', {
237
+ testCases: [stack],
60
238
  });
61
239
 
62
240
  app.synth();
@@ -85,7 +85,7 @@ const beanstalkEnv = new elasticbeanstalk.CfnEnvironment(stack, 'beanstlk-env',
85
85
  applicationName: beanstalkApp.applicationName!,
86
86
  environmentName: 'codepipeline-test-env',
87
87
  // see https://docs.aws.amazon.com/elasticbeanstalk/latest/platforms/platforms-supported.html#platforms-supported.nodejs
88
- solutionStackName: '64bit Amazon Linux 2023 v6.4.3 running Node.js 20',
88
+ solutionStackName: '64bit Amazon Linux 2023 v6.5.2 running Node.js 20',
89
89
  optionSettings: [
90
90
  {
91
91
  namespace: 'aws:autoscaling:launchconfiguration',
@@ -1281,6 +1281,19 @@ endpoint.addRoute('Route', {
1281
1281
 
1282
1282
  Use the `connections` object of the endpoint to allow traffic to other security groups.
1283
1283
 
1284
+ To enable [client route enforcement](https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/cvpn-working-cre.html), configure the `clientRouteEnforcementOptions.enforced` prop to `true`:
1285
+
1286
+ ```ts fixture=client-vpn
1287
+ const endpoint = vpc.addClientVpnEndpoint('Endpoint', {
1288
+ cidr: '10.100.0.0/16',
1289
+ serverCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/server-certificate-id',
1290
+ clientCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/client-certificate-id',
1291
+ clientRouteEnforcementOptions: {
1292
+ enforced: true,
1293
+ },
1294
+ });
1295
+ ```
1296
+
1284
1297
  ## Instances
1285
1298
 
1286
1299
  You can use the `Instance` class to start up a single EC2 instance. For production setups, we recommend
@@ -0,0 +1,68 @@
1
+ import { App, RemovalPolicy, Stack, StackProps, UnscopedValidationError } from 'aws-cdk-lib';
2
+ import * as acm from 'aws-cdk-lib/aws-certificatemanager';
3
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
4
+ import * as logs from 'aws-cdk-lib/aws-logs';
5
+ import * as route53 from 'aws-cdk-lib/aws-route53';
6
+ import { IntegTest } from '@aws-cdk/integ-tests-alpha';
7
+ import { Construct } from 'constructs';
8
+
9
+ /**
10
+ * In order to test this you need to have a valid public hosted zone that you can use
11
+ * to validate the domain identity.
12
+ */
13
+ const hostedZoneId = process.env.CDK_INTEG_HOSTED_ZONE_ID ?? process.env.HOSTED_ZONE_ID;
14
+ if (!hostedZoneId) throw new UnscopedValidationError('For this test you must provide your own HostedZoneId as an env var "HOSTED_ZONE_ID". See framework-integ/README.md for details.');
15
+ const hostedZoneName = process.env.CDK_INTEG_HOSTED_ZONE_NAME ?? process.env.HOSTED_ZONE_NAME;
16
+ if (!hostedZoneName) throw new UnscopedValidationError('For this test you must provide your own HostedZoneName as an env var "HOSTED_ZONE_NAME". See framework-integ/README.md for details.');
17
+
18
+ interface TestStackProps extends StackProps {
19
+ hostedZoneId: string;
20
+ hostedZoneName: string;
21
+ }
22
+
23
+ class TestStack extends Stack {
24
+ constructor(scope: Construct, id: string, props: TestStackProps) {
25
+ super(scope, id, props);
26
+
27
+ const hostedZone = route53.PublicHostedZone.fromHostedZoneAttributes(this, 'HostedZone', {
28
+ hostedZoneId: props.hostedZoneId,
29
+ zoneName: props.hostedZoneName,
30
+ });
31
+
32
+ const serverCertificate = new acm.Certificate(this, 'Certificate', {
33
+ domainName: `server.${props.hostedZoneName}`,
34
+ validation: acm.CertificateValidation.fromDns(hostedZone),
35
+ });
36
+ const clientCertificate = new acm.Certificate(this, 'ClientCertificate', {
37
+ domainName: `client.${props.hostedZoneName}`,
38
+ validation: acm.CertificateValidation.fromDns(hostedZone),
39
+ });
40
+
41
+ const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 2, natGateways: 0 });
42
+
43
+ const logGroup = new logs.LogGroup(this, 'LogGroup', {
44
+ removalPolicy: RemovalPolicy.DESTROY,
45
+ });
46
+
47
+ vpc.addClientVpnEndpoint('Endpoint', {
48
+ cidr: '10.100.0.0/16',
49
+ serverCertificateArn: serverCertificate.certificateArn,
50
+ clientCertificateArn: clientCertificate.certificateArn,
51
+ logGroup,
52
+ clientRouteEnforcementOptions: {
53
+ enforced: true,
54
+ },
55
+ });
56
+ }
57
+ }
58
+
59
+ const app = new App();
60
+ new IntegTest(app, 'client-vpn-endpoint-integ', {
61
+ testCases: [
62
+ new TestStack(app, 'client-vpn-endpoint-stack', {
63
+ hostedZoneId,
64
+ hostedZoneName,
65
+ }),
66
+ ],
67
+ stackUpdateWorkflow: false,
68
+ });
@@ -0,0 +1,55 @@
1
+ /// !cdk-integ pragma:disable-update-workflow
2
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
+ import { App, Stack } from 'aws-cdk-lib';
4
+ import * as integ from '@aws-cdk/integ-tests-alpha';
5
+ import { getClusterVersionConfig } from './integ-tests-kubernetes-version';
6
+ import * as eks from 'aws-cdk-lib/aws-eks';
7
+
8
+ /**
9
+ * Integration test for improved Helm chart error logging
10
+ *
11
+ * This test creates a minimal EKS cluster and installs a Helm chart
12
+ * to verify the improved error logging functionality.
13
+ */
14
+ class HelmChartLoggingStack extends Stack {
15
+ constructor(scope: App, id: string) {
16
+ super(scope, id);
17
+
18
+ // Create a minimal VPC with just one NAT gateway
19
+ const vpc = new ec2.Vpc(this, 'Vpc', {
20
+ natGateways: 1,
21
+ restrictDefaultSecurityGroup: false,
22
+ });
23
+
24
+ // Create a minimal EKS cluster
25
+ const cluster = new eks.Cluster(this, 'Cluster', {
26
+ vpc,
27
+ defaultCapacity: 1,
28
+ ...getClusterVersionConfig(this),
29
+ });
30
+
31
+ // Install a simple Helm chart from a public repository
32
+ // Using the AWS Load Balancer Controller chart as it's commonly used
33
+ cluster.addHelmChart('aws-load-balancer-controller', {
34
+ chart: 'aws-load-balancer-controller',
35
+ repository: 'https://aws.github.io/eks-charts',
36
+ namespace: 'kube-system',
37
+ version: '1.6.0',
38
+ values: {
39
+ clusterName: cluster.clusterName,
40
+ },
41
+ });
42
+ }
43
+ }
44
+
45
+ const app = new App();
46
+
47
+ const stack = new HelmChartLoggingStack(app, 'aws-cdk-eks-helm-logging-test');
48
+
49
+ new integ.IntegTest(app, 'aws-cdk-eks-helm-logging', {
50
+ testCases: [stack],
51
+ // Test includes assets that are updated weekly. If not disabled, the upgrade PR will fail.
52
+ diffAssets: false,
53
+ });
54
+
55
+ app.synth();
@@ -281,6 +281,21 @@ const fn = new lambda.Function(this, 'MyFunctionWithFFTrue', {
281
281
  cdk.Tags.of(fn).add('env', 'dev'); // the tag is also added to the log group
282
282
  ```
283
283
 
284
+ ### Log removal policy
285
+
286
+ When using the deprecated `logRetention` property for creating a LogGroup, you can configure log removal policy:
287
+ ```ts
288
+ import * as logs from 'aws-cdk-lib/aws-logs';
289
+
290
+ const fn = new lambda.Function(this, 'MyFunctionWithFFTrue', {
291
+ runtime: lambda.Runtime.NODEJS_LATEST,
292
+ handler: 'handler.main',
293
+ code: lambda.Code.fromAsset('lambda'),
294
+ logRetention: logs.RetentionDays.INFINITE,
295
+ logRemovalPolicy: RemovalPolicy.RETAIN,
296
+ });
297
+ ```
298
+
284
299
  ## Resource-based Policies
285
300
 
286
301
  AWS Lambda supports resource-based policies for controlling access to Lambda
@@ -4,7 +4,11 @@ import * as lambda from 'aws-cdk-lib/aws-lambda';
4
4
  import { IntegTest } from '@aws-cdk/integ-tests-alpha';
5
5
  import { STANDARD_NODEJS_RUNTIME } from '../../config';
6
6
 
7
- const app = new cdk.App();
7
+ const app = new cdk.App({
8
+ postCliContext: {
9
+ '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
10
+ },
11
+ });
8
12
 
9
13
  const stack = new cdk.Stack(app, 'aws-cdk-lambda-log-retention');
10
14
 
@@ -13,6 +17,7 @@ new lambda.Function(stack, 'OneWeek', {
13
17
  handler: 'index.handler',
14
18
  runtime: STANDARD_NODEJS_RUNTIME,
15
19
  logRetention: logs.RetentionDays.ONE_WEEK,
20
+ logRemovalPolicy: cdk.RemovalPolicy.DESTROY,
16
21
  });
17
22
 
18
23
  new lambda.Function(stack, 'OneMonth', {
@@ -20,6 +25,7 @@ new lambda.Function(stack, 'OneMonth', {
20
25
  handler: 'index.handler',
21
26
  runtime: STANDARD_NODEJS_RUNTIME,
22
27
  logRetention: logs.RetentionDays.ONE_MONTH,
28
+ logRemovalPolicy: cdk.RemovalPolicy.DESTROY,
23
29
  });
24
30
 
25
31
  new lambda.Function(stack, 'OneYear', {
@@ -27,10 +33,10 @@ new lambda.Function(stack, 'OneYear', {
27
33
  handler: 'index.handler',
28
34
  runtime: STANDARD_NODEJS_RUNTIME,
29
35
  logRetention: logs.RetentionDays.ONE_YEAR,
36
+ logRemovalPolicy: cdk.RemovalPolicy.DESTROY,
30
37
  });
31
38
 
32
39
  new IntegTest(app, 'LambdaLogRetentionInteg', {
33
40
  testCases: [stack],
34
41
  diffAssets: true,
35
42
  });
36
- app.synth();
@@ -147,19 +147,6 @@ new rds.DatabaseCluster(this, 'DatabaseCluster', {
147
147
  });
148
148
  ```
149
149
 
150
- To configure [the life cycle type of the cluster](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/extended-support.html), use the `engineLifecycleSupport` property:
151
-
152
- ```ts
153
- declare const vpc: ec2.IVpc;
154
-
155
- new rds.DatabaseCluster(this, 'DatabaseCluster', {
156
- engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_07_0 }),
157
- writer: rds.ClusterInstance.serverlessV2('writerInstance'),
158
- vpc,
159
- engineLifecycleSupport: rds.EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT,
160
- });
161
- ```
162
-
163
150
  ### Updating the database instances in a cluster
164
151
 
165
152
  Database cluster instances may be updated in bulk or on a rolling basis.
@@ -1576,6 +1563,29 @@ new rds.DatabaseCluster(this, 'Cluster', {
1576
1563
  });
1577
1564
  ```
1578
1565
 
1566
+ ## Extended Support
1567
+
1568
+ With Amazon RDS Extended Support, you can continue running your database on a major engine version past the RDS end of
1569
+ standard support date for an additional cost. To configure the life cycle type, use the `engineLifecycleSupport` property:
1570
+
1571
+ ```ts
1572
+ declare const vpc: ec2.IVpc;
1573
+
1574
+ new rds.DatabaseCluster(this, 'DatabaseCluster', {
1575
+ engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_07_0 }),
1576
+ writer: rds.ClusterInstance.serverlessV2('writerInstance'),
1577
+ vpc,
1578
+ engineLifecycleSupport: rds.EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT,
1579
+ });
1580
+
1581
+ new rds.DatabaseInstance(this, 'DatabaseInstance', {
1582
+ engine: rds.DatabaseInstanceEngine.mysql({ version: rds.MysqlEngineVersion.VER_8_0_39 }),
1583
+ instanceType: ec2.InstanceType.of(ec2.InstanceClass.R7G, ec2.InstanceSize.LARGE),
1584
+ vpc,
1585
+ engineLifecycleSupport: rds.EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT_DISABLED,
1586
+ });
1587
+ ```
1588
+
1579
1589
  ## Importing existing DatabaseInstance
1580
1590
 
1581
1591
  ### Lookup DatabaseInstance by instanceIdentifier
@@ -1,14 +1,10 @@
1
- import * as path from 'path';
2
1
  import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
- import * as iam from 'aws-cdk-lib/aws-iam';
4
- import * as lambda from 'aws-cdk-lib/aws-lambda';
5
- import { App, ArnFormat, CustomResource, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
6
- import * as cr from 'aws-cdk-lib/custom-resources';
2
+ import { App, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
7
3
  import { Construct } from 'constructs';
8
4
  import * as rds from 'aws-cdk-lib/aws-rds';
9
5
  import { ClusterInstance } from 'aws-cdk-lib/aws-rds';
10
6
  import { IntegTest } from '@aws-cdk/integ-tests-alpha';
11
- import { STANDARD_NODEJS_RUNTIME } from '../../config';
7
+ import { ClusterSnapshoter } from './snapshoter';
12
8
 
13
9
  class TestStack extends Stack {
14
10
  constructor(scope: Construct, id: string, props?: StackProps) {
@@ -34,7 +30,7 @@ class TestStack extends Stack {
34
30
  removalPolicy: RemovalPolicy.DESTROY,
35
31
  });
36
32
 
37
- const snapshoter = new Snapshoter(this, 'Snapshoter', {
33
+ const snapshoter = new ClusterSnapshoter(this, 'Snapshoter', {
38
34
  cluster,
39
35
  snapshotIdentifier: 'cdk-integ-cluster-snapshot',
40
36
  });
@@ -58,69 +54,6 @@ class TestStack extends Stack {
58
54
  }
59
55
  }
60
56
 
61
- interface SnapshoterProps {
62
- readonly cluster: rds.IDatabaseCluster;
63
- readonly snapshotIdentifier: string;
64
- }
65
-
66
- class Snapshoter extends Construct {
67
- public readonly snapshotArn: string;
68
-
69
- constructor(scope: Construct, id: string, props: SnapshoterProps) {
70
- super(scope, id);
71
-
72
- const clusterArn = Stack.of(this).formatArn({
73
- service: 'rds',
74
- resource: 'cluster',
75
- resourceName: props.cluster.clusterIdentifier,
76
- arnFormat: ArnFormat.COLON_RESOURCE_NAME,
77
- });
78
-
79
- const snapshotArn = Stack.of(this).formatArn({
80
- service: 'rds',
81
- resource: 'cluster-snapshot',
82
- resourceName: props.snapshotIdentifier,
83
- arnFormat: ArnFormat.COLON_RESOURCE_NAME,
84
- });
85
-
86
- const code = lambda.Code.fromAsset(path.join(__dirname, 'snapshot-handler'), { exclude: ['*.ts'] });
87
- const onEventHandler = new lambda.Function(this, 'OnEventHandler', {
88
- code,
89
- runtime: STANDARD_NODEJS_RUNTIME,
90
- handler: 'index.onEventHandler',
91
- });
92
- onEventHandler.addToRolePolicy(new iam.PolicyStatement({
93
- actions: ['rds:CreateDBClusterSnapshot', 'rds:DeleteDBClusterSnapshot'],
94
- resources: [clusterArn, snapshotArn],
95
- }));
96
-
97
- const isCompleteHandler = new lambda.Function(this, 'IsCompleteHandler', {
98
- code,
99
- runtime: STANDARD_NODEJS_RUNTIME,
100
- handler: 'index.isCompleteHandler',
101
- });
102
- isCompleteHandler.addToRolePolicy(new iam.PolicyStatement({
103
- actions: ['rds:DescribeDBClusterSnapshots'],
104
- resources: [clusterArn, snapshotArn],
105
- }));
106
-
107
- const provider = new cr.Provider(this, 'SnapshotProvider', {
108
- onEventHandler,
109
- isCompleteHandler,
110
- });
111
-
112
- const customResource = new CustomResource(this, 'Snapshot', {
113
- resourceType: 'Custom::Snapshoter',
114
- serviceToken: provider.serviceToken,
115
- properties: {
116
- DBClusterIdentifier: props.cluster.clusterIdentifier,
117
- DBClusterSnapshotIdentifier: props.snapshotIdentifier,
118
- },
119
- });
120
- this.snapshotArn = customResource.getAttString('DBClusterSnapshotArn');
121
- }
122
- }
123
-
124
57
  const app = new App({
125
58
  postCliContext: {
126
59
  '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
@@ -133,4 +66,3 @@ new IntegTest(app, 'ClusterSnapshotInteg', {
133
66
  testCases: [stack],
134
67
  diffAssets: true,
135
68
  });
136
- app.synth();