konokenj.cdk-api-mcp-server 0.43.0__py3-none-any.whl → 0.45.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.

Potentially problematic release.


This version of konokenj.cdk-api-mcp-server might be problematic. Click here for more details.

Files changed (40) hide show
  1. cdk_api_mcp_server/__about__.py +1 -1
  2. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-iot-alpha/README.md +1 -1
  3. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/README.md +8 -0
  4. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api.ts +4 -0
  5. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-batch/README.md +34 -0
  6. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-batch/integ.ecs-exec-batch-job.ts +148 -0
  7. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront-origins/README.md +36 -0
  8. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront-origins/integ.origin-response-completion-timeout.ts +50 -0
  9. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/README.md +1 -0
  10. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/integ.project-docker-server.ts +44 -0
  11. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/integ.pipeline-elastic-beanstalk-deploy.ts +22 -16
  12. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecr-assets/README.md +4 -0
  13. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/README.md +2 -0
  14. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/README.md +21 -0
  15. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/integ.alb-target-group-attributes.ts +45 -0
  16. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/integ.nlb-target-group-attributes.ts +45 -0
  17. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events/README.md +18 -1
  18. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events/integ.eventbus.ts +13 -3
  19. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-nodejs/README.md +3 -3
  20. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-nodejs/integ.dependencies-bun-lock.ts +50 -0
  21. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/README.md +20 -0
  22. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.proxy-endpoint.ts +36 -0
  23. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53/README.md +24 -0
  24. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53/integ.route53.ts +51 -1
  25. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53-targets/integ.cloudfront-alias-target.ts +16 -1
  26. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3/integ.bucket.notifications-scoped-permissions.ts +71 -0
  27. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.distributed-map-parallel.ts +82 -0
  28. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.distributed-map-redrive.ts +130 -0
  29. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.map-with-catch.ts +1 -0
  30. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/README.md +53 -0
  31. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.emr-create-cluster-with-ebs.ts +126 -0
  32. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/README.md +27 -0
  33. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/integ.canary-browser-type.ts +35 -0
  34. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cloudformation-include/integ.novalue-nonstring.ts +25 -0
  35. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +2 -2
  36. {konokenj_cdk_api_mcp_server-0.43.0.dist-info → konokenj_cdk_api_mcp_server-0.45.0.dist-info}/METADATA +2 -2
  37. {konokenj_cdk_api_mcp_server-0.43.0.dist-info → konokenj_cdk_api_mcp_server-0.45.0.dist-info}/RECORD +40 -27
  38. {konokenj_cdk_api_mcp_server-0.43.0.dist-info → konokenj_cdk_api_mcp_server-0.45.0.dist-info}/WHEEL +0 -0
  39. {konokenj_cdk_api_mcp_server-0.43.0.dist-info → konokenj_cdk_api_mcp_server-0.45.0.dist-info}/entry_points.txt +0 -0
  40. {konokenj_cdk_api_mcp_server-0.43.0.dist-info → konokenj_cdk_api_mcp_server-0.45.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -108,8 +108,8 @@ With the `@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion` disabled, the runt
108
108
 
109
109
  ## Lock file
110
110
 
111
- The `NodejsFunction` requires a dependencies lock file (`yarn.lock`, `pnpm-lock.yaml`, `bun.lockb` or
112
- `package-lock.json`). When bundling in a Docker container, the path containing this lock file is
111
+ The `NodejsFunction` requires a dependencies lock file (`yarn.lock`, `pnpm-lock.yaml`, `bun.lockb`,
112
+ `bun.lock` or `package-lock.json`). When bundling in a Docker container, the path containing this lock file is
113
113
  used as the source (`/asset-input`) for the volume mounted in the container.
114
114
 
115
115
  By default, the construct will try to automatically determine your project lock file.
@@ -201,7 +201,7 @@ new nodejs.NodejsFunction(this, 'my-handler', {
201
201
 
202
202
  The modules listed in `nodeModules` must be present in the `package.json`'s dependencies or
203
203
  installed. The same version will be used for installation. The lock file (`yarn.lock`,
204
- `pnpm-lock.yaml`, `bun.lockb` or `package-lock.json`) will be used along with the right installer (`yarn`,
204
+ `pnpm-lock.yaml`, `bun.lockb`, `bun.lock` or `package-lock.json`) will be used along with the right installer (`yarn`,
205
205
  `pnpm`, `bun` or `npm`).
206
206
 
207
207
  When working with `nodeModules` using native dependencies, you might want to force bundling in a
@@ -0,0 +1,50 @@
1
+ import * as path from 'path';
2
+ import { Runtime } from 'aws-cdk-lib/aws-lambda';
3
+ import * as cdk from 'aws-cdk-lib';
4
+ import { ExpectedResult, IntegTest } from '@aws-cdk/integ-tests-alpha';
5
+ import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';
6
+
7
+ const app = new cdk.App({
8
+ postCliContext: {
9
+ '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
10
+ },
11
+ });
12
+
13
+ const stack = new cdk.Stack(app, 'TestStack');
14
+
15
+ const handler = new lambda.NodejsFunction(stack, 'Function', {
16
+ entry: path.join(__dirname, 'integ-handlers/bun_lock/dependencies-bun.ts'),
17
+ runtime: Runtime.NODEJS_22_X,
18
+ bundling: {
19
+ minify: true,
20
+ // Will be installed, not bundled
21
+ // (axios is a package with sub-dependencies,
22
+ // will be used to ensure bun bundling works as expected)
23
+ nodeModules: ['axios'],
24
+ forceDockerBundling: true,
25
+ },
26
+
27
+ // To (re-)generate this lockfile:
28
+ // 1. Ensure your local version of bun matches the version in packages/aws-cdk-lib/aws-lambda-nodejs/lib/Dockerfile
29
+ // 2. `cd` to `packages/@aws-cdk-testing/framework-integ/test/aws-lambda-nodejs/test/integ-handlers/bun`
30
+ // 3. Rename the `_package.json` file to `package.json`
31
+ // 4. Run `bun install`
32
+ depsLockFilePath: path.join(__dirname, 'integ-handlers/bun_lock/bun.lock'),
33
+ });
34
+
35
+ const integ = new IntegTest(app, 'BunTest', {
36
+ testCases: [stack],
37
+ stackUpdateWorkflow: false, // this will tell the runner to not check in assets.
38
+ });
39
+
40
+ const response = integ.assertions.invokeFunction({
41
+ functionName: handler.functionName,
42
+ });
43
+ response.expect(
44
+ ExpectedResult.objectLike({
45
+ // expect invoking without error
46
+ StatusCode: 200,
47
+ ExecutedVersion: '$LATEST',
48
+ Payload: 'null',
49
+ }),
50
+ );
@@ -1166,6 +1166,26 @@ const proxy = dbInstance.addProxy('proxy', {
1166
1166
  });
1167
1167
  ```
1168
1168
 
1169
+ ### Proxy Endpoint
1170
+ The following example add additional endpoint to RDS Proxy.
1171
+
1172
+ ```ts
1173
+ declare const vpc: ec2.Vpc;
1174
+ declare const secrets: secretsmanager.Secret[];
1175
+ declare const dbInstance: rds.DatabaseInstance;
1176
+
1177
+ const proxy = dbInstance.addProxy('Proxy', {
1178
+ secrets,
1179
+ vpc,
1180
+ });
1181
+
1182
+ // Add a reader endpoint
1183
+ proxy.addEndpoint('ProxyEndpoint', {
1184
+ vpc,
1185
+ targetRole: rds.ProxyEndpointTargetRole.READ_ONLY,
1186
+ });
1187
+ ```
1188
+
1169
1189
  ## Exporting Logs
1170
1190
 
1171
1191
  You can publish database logs to Amazon CloudWatch Logs. With CloudWatch Logs, you can perform real-time analysis of the log data,
@@ -0,0 +1,36 @@
1
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
2
+ import { App, RemovalPolicy, Stack } from 'aws-cdk-lib';
3
+ import * as integ from '@aws-cdk/integ-tests-alpha';
4
+ import * as rds from 'aws-cdk-lib/aws-rds';
5
+
6
+ const app = new App();
7
+ const stack = new Stack(app, 'cdk-rds-proxy-endpoint');
8
+
9
+ const vpc = new ec2.Vpc(stack, 'vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false });
10
+
11
+ const dbInstance = new rds.DatabaseInstance(stack, 'dbInstance', {
12
+ engine: rds.DatabaseInstanceEngine.postgres({
13
+ version: rds.PostgresEngineVersion.VER_17_5,
14
+ }),
15
+ instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM),
16
+ vpc,
17
+ removalPolicy: RemovalPolicy.DESTROY,
18
+ });
19
+
20
+ const dbProxy = new rds.DatabaseProxy(stack, 'dbProxy', {
21
+ secrets: [dbInstance.secret!],
22
+ proxyTarget: rds.ProxyTarget.fromInstance(dbInstance),
23
+ vpc,
24
+ });
25
+
26
+ const securityGroup = ec2.SecurityGroup.fromSecurityGroupId(stack, 'SecurityGroup', vpc.vpcDefaultSecurityGroup);
27
+
28
+ dbProxy.addEndpoint('dbProxyEndpoint', {
29
+ vpc,
30
+ targetRole: rds.ProxyEndpointTargetRole.READ_ONLY,
31
+ securityGroups: [securityGroup],
32
+ });
33
+
34
+ new integ.IntegTest(app, 'cdk-rds-proxy-endpoint-integ', {
35
+ testCases: [stack],
36
+ });
@@ -134,6 +134,30 @@ new route53.AaaaRecord(this, 'Alias', {
134
134
  });
135
135
  ```
136
136
 
137
+ To add an HTTPS record:
138
+
139
+ ``` ts
140
+ import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
141
+
142
+ declare const myZone: route53.HostedZone;
143
+ declare const distribution: cloudfront.CloudFrontWebDistribution;
144
+ // Alias to CloudFront target
145
+ new route53.HttpsRecord(this, 'HttpsRecord-CloudFrontAlias', {
146
+ zone: myZone,
147
+ target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
148
+ });
149
+ // ServiceMode (priority >= 1)
150
+ new route53.HttpsRecord(this, 'HttpsRecord-ServiceMode', {
151
+ zone: myZone,
152
+ values: [route53.HttpsRecordValue.service({ alpn: [route53.Alpn.H3, route53.Alpn.H2] })],
153
+ });
154
+ // AliasMode (priority = 0)
155
+ new route53.HttpsRecord(this, 'HttpsRecord-AliasMode', {
156
+ zone: myZone,
157
+ values: [route53.HttpsRecordValue.alias('service.example.com')],
158
+ });
159
+ ```
160
+
137
161
  [Geolocation routing](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-geo.html) can be enabled for continent, country or subdivision:
138
162
 
139
163
  ```ts
@@ -1,6 +1,6 @@
1
1
  import * as ec2 from 'aws-cdk-lib/aws-ec2';
2
2
  import * as cdk from 'aws-cdk-lib';
3
- import { ARecord, CaaAmazonRecord, CnameRecord, Continent, GeoLocation, PrivateHostedZone, PublicHostedZone, RecordTarget, TxtRecord } from 'aws-cdk-lib/aws-route53';
3
+ import { Alpn, ARecord, CaaAmazonRecord, CnameRecord, Continent, GeoLocation, HttpsRecord, HttpsRecordValue, PrivateHostedZone, PublicHostedZone, RecordTarget, SvcbRecord, SvcbRecordValue, TxtRecord } from 'aws-cdk-lib/aws-route53';
4
4
 
5
5
  const app = new cdk.App();
6
6
 
@@ -92,6 +92,56 @@ new TxtRecord(stack, 'TXT', {
92
92
  ],
93
93
  });
94
94
 
95
+ new SvcbRecord(stack, 'SVCB-AliasMode', {
96
+ zone: publicZone,
97
+ recordName: '_8080._svcb-alias',
98
+ values: [SvcbRecordValue.alias('service.example.com')],
99
+ });
100
+ new SvcbRecord(stack, 'SVCB-ServiceMode', {
101
+ zone: publicZone,
102
+ recordName: '_8080._svcb-service',
103
+ values: [SvcbRecordValue.service({ alpn: [Alpn.H3, Alpn.H2] })],
104
+ });
105
+ new SvcbRecord(stack, 'SVCB-ServiceMode-FullParams', {
106
+ zone: publicZone,
107
+ recordName: '_8080._svcb-service-fullparams',
108
+ values: [SvcbRecordValue.service({
109
+ priority: 2,
110
+ targetName: 'service.example.com',
111
+ mandatory: ['alpn'],
112
+ alpn: [Alpn.H3, Alpn.H2, Alpn.HTTP1_1, Alpn.of('h3-29')],
113
+ noDefaultAlpn: true,
114
+ port: 8443,
115
+ ipv4hint: ['127.0.0.1'],
116
+ ipv6hint: ['::1'],
117
+ })],
118
+ });
119
+
120
+ new HttpsRecord(stack, 'HTTPS-AliasMode', {
121
+ zone: publicZone,
122
+ recordName: 'https-alias',
123
+ values: [HttpsRecordValue.alias('service.example.com')],
124
+ });
125
+ new HttpsRecord(stack, 'HTTPS-ServiceMode', {
126
+ zone: publicZone,
127
+ recordName: 'https-service',
128
+ values: [HttpsRecordValue.service({ alpn: [Alpn.H3, Alpn.H2] })],
129
+ });
130
+ new HttpsRecord(stack, 'HTTPS-ServiceMode-FullParams', {
131
+ zone: publicZone,
132
+ recordName: 'https-service-fullparams',
133
+ values: [HttpsRecordValue.service({
134
+ priority: 2,
135
+ targetName: 'service.example.com',
136
+ mandatory: ['alpn'],
137
+ alpn: [Alpn.H3, Alpn.H2, Alpn.HTTP1_1, Alpn.of('h3-29')],
138
+ noDefaultAlpn: true,
139
+ port: 8443,
140
+ ipv4hint: ['127.0.0.1'],
141
+ ipv6hint: ['::1'],
142
+ })],
143
+ });
144
+
95
145
  new cdk.CfnOutput(stack, 'PrivateZoneId', { value: privateZone.hostedZoneId });
96
146
  new cdk.CfnOutput(stack, 'PublicZoneId', { value: publicZone.hostedZoneId });
97
147
 
@@ -3,6 +3,7 @@ import * as route53 from 'aws-cdk-lib/aws-route53';
3
3
  import * as s3 from 'aws-cdk-lib/aws-s3';
4
4
  import * as cdk from 'aws-cdk-lib';
5
5
  import * as targets from 'aws-cdk-lib/aws-route53-targets';
6
+ import { IntegTest } from '@aws-cdk/integ-tests-alpha';
6
7
 
7
8
  const app = new cdk.App();
8
9
 
@@ -31,4 +32,18 @@ new route53.ARecord(zone, 'Alias', {
31
32
  target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
32
33
  });
33
34
 
34
- app.synth();
35
+ new route53.AaaaRecord(zone, 'AaaaAlias', {
36
+ zone,
37
+ recordName: '_foo',
38
+ target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
39
+ });
40
+
41
+ new route53.HttpsRecord(zone, 'HttpsAlias', {
42
+ zone,
43
+ recordName: '_foo',
44
+ target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
45
+ });
46
+
47
+ new IntegTest(app, 'aws-cdk-route53-cloudfront-alias-integ-test', {
48
+ testCases: [stack],
49
+ });
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ import * as cdk from 'aws-cdk-lib';
3
+ import * as integ from '@aws-cdk/integ-tests-alpha';
4
+ import * as s3 from 'aws-cdk-lib/aws-s3';
5
+ import * as sns from 'aws-cdk-lib/aws-sns';
6
+ import * as sqs from 'aws-cdk-lib/aws-sqs';
7
+ import * as s3n from 'aws-cdk-lib/aws-s3-notifications';
8
+ import { Match, Template } from 'aws-cdk-lib/assertions';
9
+
10
+ const app = new cdk.App();
11
+
12
+ const stack = new cdk.Stack(app, 'aws-cdk-s3-notifications-scoped-permissions');
13
+
14
+ // Create multiple buckets to test consolidated policy with scoped permissions
15
+ const bucket1 = new s3.Bucket(stack, 'Bucket1', {
16
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
17
+ });
18
+
19
+ const bucket2 = new s3.Bucket(stack, 'Bucket2', {
20
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
21
+ });
22
+
23
+ const topic = new sns.Topic(stack, 'Topic');
24
+ const queue = new sqs.Queue(stack, 'Queue', {
25
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
26
+ });
27
+
28
+ // Add notifications to multiple buckets with different event types - this should create scoped IAM permissions
29
+ bucket1.addEventNotification(s3.EventType.OBJECT_CREATED_PUT, new s3n.SnsDestination(topic));
30
+ bucket1.addEventNotification(s3.EventType.OBJECT_CREATED_POST, new s3n.SqsDestination(queue));
31
+ bucket2.addEventNotification(s3.EventType.OBJECT_REMOVED_DELETE, new s3n.SnsDestination(topic));
32
+ bucket2.addEventNotification(s3.EventType.OBJECT_REMOVED_DELETE_MARKER_CREATED, new s3n.SnsDestination(topic));
33
+
34
+ // Create integration test with snapshot comparison enabled
35
+ new integ.IntegTest(app, 'ScopedPermissionsTest', {
36
+ testCases: [stack],
37
+ diffAssets: true,
38
+ });
39
+
40
+ // Add assertions to verify IAM policies are scoped to specific bucket ARNs
41
+ const template = Template.fromStack(stack);
42
+
43
+ // Verify that IAM policies do not contain wildcard permissions
44
+ template.hasResourceProperties('AWS::IAM::Policy', {
45
+ PolicyDocument: {
46
+ Statement: Match.arrayWith([
47
+ Match.objectLike({
48
+ Effect: 'Allow',
49
+ Action: 's3:PutBucketNotification',
50
+ Resource: Match.not('*'), // Ensure no wildcard permissions
51
+ }),
52
+ ]),
53
+ },
54
+ });
55
+
56
+ // Verify that the IAM policy contains specific bucket ARNs
57
+ template.hasResourceProperties('AWS::IAM::Policy', {
58
+ PolicyDocument: {
59
+ Statement: Match.arrayWith([
60
+ Match.objectLike({
61
+ Effect: 'Allow',
62
+ Action: 's3:PutBucketNotification',
63
+ Resource: Match.arrayWith([
64
+ Match.objectLike({
65
+ 'Fn::GetAtt': Match.arrayWith([Match.stringLikeRegexp('Bucket[12]'), 'Arn']),
66
+ }),
67
+ ]),
68
+ }),
69
+ ]),
70
+ },
71
+ });
@@ -0,0 +1,82 @@
1
+ import * as s3 from 'aws-cdk-lib/aws-s3';
2
+ import * as cdk from 'aws-cdk-lib/core';
3
+ import * as integ from '@aws-cdk/integ-tests-alpha';
4
+ import * as sfn from 'aws-cdk-lib/aws-stepfunctions';
5
+
6
+ const CSV_KEY = 'my-key.csv';
7
+
8
+ class DistributedMapParallelStack extends cdk.Stack {
9
+ readonly bucket: s3.Bucket;
10
+ readonly stateMachine: sfn.StateMachine;
11
+
12
+ constructor(scope: cdk.App, id: string) {
13
+ super(scope, id);
14
+
15
+ this.bucket = new s3.Bucket(this, 'Bucket', {
16
+ autoDeleteObjects: true,
17
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
18
+ });
19
+
20
+ const parallel = new sfn.Parallel(this, 'Parallel');
21
+
22
+ const distributedMap = new sfn.DistributedMap(this, 'DistributedMap', {
23
+ itemReader: new sfn.S3CsvItemReader({
24
+ bucket: this.bucket,
25
+ key: CSV_KEY,
26
+ csvHeaders: sfn.CsvHeaders.useFirstRow(),
27
+ }),
28
+ }).itemProcessor(new sfn.Pass(this, 'Pass'));
29
+
30
+ this.stateMachine = new sfn.StateMachine(this, 'StateMachine', {
31
+ definitionBody: sfn.ChainDefinitionBody.fromChainable(parallel.branch(distributedMap)),
32
+ });
33
+ }
34
+ }
35
+
36
+ function setupAssertions(testCaseStack: DistributedMapParallelStack, assertions: integ.IDeployAssert) {
37
+ const waitForStateMachineActive = assertions
38
+ .awsApiCall('StepFunctions', 'describeStateMachine', {
39
+ stateMachineArn: testCaseStack.stateMachine.stateMachineArn,
40
+ })
41
+ .expect(integ.ExpectedResult.objectLike({ status: 'ACTIVE' }))
42
+ .waitForAssertions({
43
+ interval: cdk.Duration.seconds(10),
44
+ totalTimeout: cdk.Duration.minutes(5),
45
+ });
46
+
47
+ // Upload the input to the DistributedMap
48
+ const uploadInput = assertions.awsApiCall('S3', 'putObject', {
49
+ Bucket: testCaseStack.bucket.bucketName,
50
+ Key: CSV_KEY,
51
+ Body: 'a,b,c\n1,2,3\n4,5,6',
52
+ });
53
+
54
+ // Start an execution
55
+ const startExecution = assertions.awsApiCall('StepFunctions', 'startExecution', {
56
+ stateMachineArn: testCaseStack.stateMachine.stateMachineArn,
57
+ });
58
+
59
+ const executionArn = startExecution.getAttString('executionArn');
60
+
61
+ const expectSucceededExecution = assertions
62
+ .awsApiCall('StepFunctions', 'describeExecution', { executionArn: executionArn })
63
+ .expect(integ.ExpectedResult.objectLike({ status: 'SUCCEEDED' }))
64
+ .waitForAssertions({
65
+ interval: cdk.Duration.seconds(10),
66
+ totalTimeout: cdk.Duration.minutes(1),
67
+ });
68
+
69
+ waitForStateMachineActive
70
+ .next(uploadInput)
71
+ .next(startExecution)
72
+ .next(expectSucceededExecution);
73
+ }
74
+
75
+ const app = new cdk.App();
76
+ const parallelStack = new DistributedMapParallelStack(app, 'DistributedMapParallelStack');
77
+
78
+ const testCase = new integ.IntegTest(app, 'DistributedMapParallel', {
79
+ testCases: [parallelStack],
80
+ });
81
+
82
+ setupAssertions(parallelStack, testCase.assertions);
@@ -0,0 +1,130 @@
1
+ import * as s3 from 'aws-cdk-lib/aws-s3';
2
+ import * as cdk from 'aws-cdk-lib/core';
3
+ import * as integ from '@aws-cdk/integ-tests-alpha';
4
+ import * as sfn from 'aws-cdk-lib/aws-stepfunctions';
5
+ import * as aws_stepfunction_tasks from 'aws-cdk-lib/aws-stepfunctions-tasks';
6
+
7
+ const CSV_KEY = 'my-key.csv';
8
+ const SUCCESS_MARKER_KEY = 'pass-flag.txt';
9
+
10
+ interface DistributedMapRedriveStackProps extends cdk.StackProps {
11
+ readonly mapRunLabel?: string;
12
+ }
13
+
14
+ class DistributedMapRedriveStack extends cdk.Stack {
15
+ readonly bucket: s3.Bucket;
16
+ readonly stateMachine: sfn.StateMachine;
17
+
18
+ constructor(scope: cdk.App, id: string, props?: DistributedMapRedriveStackProps) {
19
+ super(scope, id, props);
20
+
21
+ this.bucket = new s3.Bucket(this, 'Bucket', {
22
+ autoDeleteObjects: true,
23
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
24
+ });
25
+
26
+ const distributedMap = new sfn.DistributedMap(this, 'DistributedMap', {
27
+ label: props?.mapRunLabel,
28
+ itemReader: new sfn.S3CsvItemReader({
29
+ bucket: this.bucket,
30
+ key: CSV_KEY,
31
+ csvHeaders: sfn.CsvHeaders.useFirstRow(),
32
+ }),
33
+ });
34
+
35
+ // Existence of the success marker object determines if the distributed map succeeds or fails
36
+ const getSuccessMarker = new aws_stepfunction_tasks.CallAwsService(this, 'GetData', {
37
+ action: 'getObject',
38
+ iamResources: [this.bucket.arnForObjects('*')],
39
+ parameters: {
40
+ Bucket: this.bucket.bucketName,
41
+ Key: SUCCESS_MARKER_KEY,
42
+ },
43
+ service: 's3',
44
+ });
45
+
46
+ distributedMap.itemProcessor(getSuccessMarker);
47
+
48
+ this.stateMachine = new sfn.StateMachine(this, 'StateMachine', {
49
+ definitionBody: sfn.ChainDefinitionBody.fromChainable(distributedMap),
50
+ });
51
+ }
52
+ }
53
+
54
+ function setupAssertions(testCaseStack: DistributedMapRedriveStack, assertions: integ.IDeployAssert) {
55
+ const waitForStateMachineActive = assertions
56
+ .awsApiCall('StepFunctions', 'describeStateMachine', {
57
+ stateMachineArn: testCaseStack.stateMachine.stateMachineArn,
58
+ })
59
+ .expect(integ.ExpectedResult.objectLike({ status: 'ACTIVE' }))
60
+ .waitForAssertions({
61
+ interval: cdk.Duration.seconds(10),
62
+ totalTimeout: cdk.Duration.minutes(5),
63
+ });
64
+
65
+ // Upload the input to the DistributedMap
66
+ const uploadInput = assertions.awsApiCall('S3', 'putObject', {
67
+ Bucket: testCaseStack.bucket.bucketName,
68
+ Key: CSV_KEY,
69
+ Body: 'a,b,c\n1,2,3\n4,5,6',
70
+ });
71
+
72
+ // Start an execution
73
+ const startExecution = assertions.awsApiCall('StepFunctions', 'startExecution', {
74
+ stateMachineArn: testCaseStack.stateMachine.stateMachineArn,
75
+ });
76
+
77
+ const executionArn = startExecution.getAttString('executionArn');
78
+
79
+ // describe the results of the execution
80
+ const expectFailedExecution = assertions
81
+ .awsApiCall('StepFunctions', 'describeExecution', {
82
+ executionArn: executionArn,
83
+ })
84
+ .expect(integ.ExpectedResult.objectLike({ status: 'FAILED' }))
85
+ .waitForAssertions({
86
+ interval: cdk.Duration.seconds(10),
87
+ totalTimeout: cdk.Duration.minutes(1),
88
+ });
89
+
90
+ // Upload the success marker, so that the next execution succeeds
91
+ const uploadSucceedMarker = assertions.awsApiCall('S3', 'putObject', {
92
+ Bucket: testCaseStack.bucket.bucketName,
93
+ Key: SUCCESS_MARKER_KEY,
94
+ Body: '',
95
+ });
96
+
97
+ const redriveExecution = assertions.awsApiCall('StepFunctions', 'redriveExecution', {
98
+ executionArn: executionArn,
99
+ });
100
+
101
+ const expectRedrivenExecution = assertions
102
+ .awsApiCall('StepFunctions', 'describeExecution', { executionArn: executionArn })
103
+ .expect(integ.ExpectedResult.objectLike({ status: 'SUCCEEDED' }))
104
+ .waitForAssertions({
105
+ interval: cdk.Duration.seconds(10),
106
+ totalTimeout: cdk.Duration.minutes(1),
107
+ });
108
+
109
+ waitForStateMachineActive
110
+ .next(uploadInput)
111
+ .next(startExecution)
112
+ .next(expectFailedExecution)
113
+ .next(uploadSucceedMarker)
114
+ .next(redriveExecution)
115
+ .next(expectRedrivenExecution);
116
+ }
117
+
118
+ const app = new cdk.App();
119
+
120
+ const unlabeledDistributedMapStack = new DistributedMapRedriveStack(app, 'UnlabeledDistributedMapRedrive');
121
+ const labeledDistributedMapStack = new DistributedMapRedriveStack(app, 'LabeledDistributedMapRedrive', {
122
+ mapRunLabel: 'myLabel',
123
+ });
124
+
125
+ const testCase = new integ.IntegTest(app, 'DistributedMap', {
126
+ testCases: [unlabeledDistributedMapStack, labeledDistributedMapStack],
127
+ });
128
+
129
+ setupAssertions(labeledDistributedMapStack, testCase.assertions);
130
+ setupAssertions(unlabeledDistributedMapStack, testCase.assertions);
@@ -13,6 +13,7 @@ class DistributedMapStack extends cdk.Stack {
13
13
  super(scope, id, props);
14
14
 
15
15
  this.bucket = new s3.Bucket(this, 'Bucket', {
16
+ autoDeleteObjects: true,
16
17
  removalPolicy: cdk.RemovalPolicy.DESTROY,
17
18
  });
18
19
 
@@ -962,6 +962,18 @@ new tasks.EmrCreateCluster(this, 'SpotSpecification', {
962
962
  });
963
963
  ```
964
964
 
965
+ You can [customize EBS root device volume](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-custom-ami-root-volume-size.html).
966
+
967
+ ```ts
968
+ new tasks.EmrCreateCluster(this, 'Create Cluster', {
969
+ instances: {},
970
+ name: 'ClusterName',
971
+ ebsRootVolumeIops: 4000,
972
+ ebsRootVolumeSize: Size.gibibytes(20),
973
+ ebsRootVolumeThroughput: 200,
974
+ });
975
+ ```
976
+
965
977
  If you want to run multiple steps in [parallel](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-concurrent-steps.html),
966
978
  you can specify the `stepConcurrencyLevel` property. The concurrency range is between 1
967
979
  and 256 inclusive, where the default concurrency of 1 means no step concurrency is allowed.
@@ -987,6 +999,47 @@ new tasks.EmrCreateCluster(this, 'Create Cluster', {
987
999
  });
988
1000
  ```
989
1001
 
1002
+ If you want to use [managed scaling](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-managed-scaling.html),
1003
+ you can specify the `managedScalingPolicy` property.
1004
+
1005
+ ```ts
1006
+ new tasks.EmrCreateCluster(this, 'CreateCluster', {
1007
+ instances: {
1008
+ instanceFleets: [
1009
+ {
1010
+ instanceFleetType: tasks.EmrCreateCluster.InstanceRoleType.CORE,
1011
+ instanceTypeConfigs: [
1012
+ {
1013
+ instanceType: 'm5.xlarge',
1014
+ },
1015
+ ],
1016
+ targetOnDemandCapacity: 1,
1017
+ },
1018
+ {
1019
+ instanceFleetType: tasks.EmrCreateCluster.InstanceRoleType.MASTER,
1020
+ instanceTypeConfigs: [
1021
+ {
1022
+ instanceType: 'm5.xlarge',
1023
+ },
1024
+ ],
1025
+ targetOnDemandCapacity: 1,
1026
+ },
1027
+ ],
1028
+ },
1029
+ name: 'ClusterName',
1030
+ releaseLabel: 'emr-7.9.0',
1031
+ managedScalingPolicy: {
1032
+ computeLimits: {
1033
+ unitType: tasks.EmrCreateCluster.ComputeLimitsUnitType.INSTANCE_FLEET_UNITS,
1034
+ maximumCapacityUnits: 4,
1035
+ minimumCapacityUnits: 1,
1036
+ maximumOnDemandCapacityUnits: 4,
1037
+ maximumCoreCapacityUnits: 2,
1038
+ },
1039
+ },
1040
+ });
1041
+ ```
1042
+
990
1043
  ### Termination Protection
991
1044
 
992
1045
  Locks a cluster (job flow) so the EC2 instances in the cluster cannot be