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.
- cdk_api_mcp_server/__about__.py +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-iot-alpha/README.md +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/README.md +8 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api.ts +4 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-batch/README.md +34 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-batch/integ.ecs-exec-batch-job.ts +148 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront-origins/README.md +36 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront-origins/integ.origin-response-completion-timeout.ts +50 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/README.md +1 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/integ.project-docker-server.ts +44 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/integ.pipeline-elastic-beanstalk-deploy.ts +22 -16
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecr-assets/README.md +4 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/README.md +2 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/README.md +21 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/integ.alb-target-group-attributes.ts +45 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/integ.nlb-target-group-attributes.ts +45 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events/README.md +18 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events/integ.eventbus.ts +13 -3
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-nodejs/README.md +3 -3
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-nodejs/integ.dependencies-bun-lock.ts +50 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/README.md +20 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.proxy-endpoint.ts +36 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53/README.md +24 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53/integ.route53.ts +51 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53-targets/integ.cloudfront-alias-target.ts +16 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3/integ.bucket.notifications-scoped-permissions.ts +71 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.distributed-map-parallel.ts +82 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.distributed-map-redrive.ts +130 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.map-with-catch.ts +1 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/README.md +53 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.emr-create-cluster-with-ebs.ts +126 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/README.md +27 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/integ.canary-browser-type.ts +35 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cloudformation-include/integ.novalue-nonstring.ts +25 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +2 -2
- {konokenj_cdk_api_mcp_server-0.43.0.dist-info → konokenj_cdk_api_mcp_server-0.45.0.dist-info}/METADATA +2 -2
- {konokenj_cdk_api_mcp_server-0.43.0.dist-info → konokenj_cdk_api_mcp_server-0.45.0.dist-info}/RECORD +40 -27
- {konokenj_cdk_api_mcp_server-0.43.0.dist-info → konokenj_cdk_api_mcp_server-0.45.0.dist-info}/WHEEL +0 -0
- {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
- {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
|
|
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
|
-
|
|
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);
|
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/README.md
CHANGED
|
@@ -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
|