konokenj.cdk-api-mcp-server 0.49.0__py3-none-any.whl → 0.51.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-bedrock-agentcore-alpha/README.md +796 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-eks-v2-alpha/README.md +116 -29
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-msk-alpha/README.md +38 -8
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/mixins-preview/README.md +16 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigateway/integ.api-with-authorizer-and-proxy.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigateway/integ.lambda-api.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-authorizers/integ.iam.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-authorizers/integ.lambda.ts +2 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-authorizers/integ.user-pool.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.add-subroute-integration.ts +7 -4
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.http-proxy.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.lambda-proxy.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.lambda.ts +4 -4
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-appsync/integ.graphql-lambda-permission.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-appsync/integ.js-resolver.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudformation/integ.core-custom-resources-node-18.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudformation/integ.core-custom-resources-service-timeout.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront-origins/integ.origin-response-completion-timeout.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudtrail/integ.cloudtrail-data-events-only.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/integ.pipeline-elastic-beanstalk-deploy.ts +4 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/README.md +53 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb.add-to-resource-policy.ts +80 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb.policy.ts +21 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ec2/integ.vpc-flow-logs.ts +4 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecr/README.md +40 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecr/integ.tag-mutability-exclusion.ts +30 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/README.md +3 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.managedinstances-capacity-provider.ts +5 -3
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.managedinstances-no-default-capacity-provider.ts +107 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs-patterns/integ.alb-fargate-service-public-private-switch.ts +45 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/README.md +34 -4
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/integ.alb-lambda-multi-value-headers.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/integ.alb.oidc.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/integ.nlb.security-group.ts +70 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2-actions/integ.cognito.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events-targets/README.md +22 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events-targets/integ.firehose-delivery-stream.ts +51 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-kinesisfirehose/README.md +96 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-kinesisfirehose/integ.record-format-conversion-schema.ts +154 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-kinesisfirehose/integ.record-format-conversion.ts +178 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/integ.binary-payload.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/integ.logging-config.ts +8 -8
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/integ.params-and-secrets.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/integ.runtime-management.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/integ.runtime.inlinecode.ts +0 -7
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-nodejs/integ.dependencies-pnpm.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-nodejs/integ.function-exclude-smithy-models.ts +2 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-nodejs/integ.nodejs.build.images.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-logs/integ.subscriptionfilter.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.cluster-data-api-to-imported-cluster.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.cluster-data-api.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-data.ts +4 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/README.md +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.call-aws-service-cross-region-lambda.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.invoke-json-path.ts +102 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/integ.canary.ts +2 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/custom-resources/integ.aws-custom-resource.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/custom-resources/integ.custom-resource-config-lambda-node-runtime.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/custom-resources/integ.invoke-function-payload.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +62 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/README.md +32 -1
- {konokenj_cdk_api_mcp_server-0.49.0.dist-info → konokenj_cdk_api_mcp_server-0.51.0.dist-info}/METADATA +2 -2
- {konokenj_cdk_api_mcp_server-0.49.0.dist-info → konokenj_cdk_api_mcp_server-0.51.0.dist-info}/RECORD +67 -57
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events-targets/integ.kinesis-firehose-stream.ts +0 -33
- {konokenj_cdk_api_mcp_server-0.49.0.dist-info → konokenj_cdk_api_mcp_server-0.51.0.dist-info}/WHEEL +0 -0
- {konokenj_cdk_api_mcp_server-0.49.0.dist-info → konokenj_cdk_api_mcp_server-0.51.0.dist-info}/entry_points.txt +0 -0
- {konokenj_cdk_api_mcp_server-0.49.0.dist-info → konokenj_cdk_api_mcp_server-0.51.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test for DynamoDB Table.addToResourcePolicy() method
|
|
3
|
+
*
|
|
4
|
+
* This test validates the fix for issue #35062: "(aws-dynamodb): `addToResourcePolicy` has no effect"
|
|
5
|
+
*
|
|
6
|
+
* WHAT WE'RE TESTING:
|
|
7
|
+
* - The addToResourcePolicy() method was broken - it had "no effect" when called
|
|
8
|
+
* - Resource policies weren't being added to the CloudFormation template
|
|
9
|
+
* - This created a security gap where developers thought they were securing tables but policies weren't applied
|
|
10
|
+
*
|
|
11
|
+
* TEST VALIDATION:
|
|
12
|
+
* 1. Creates DynamoDB tables with different resource policy configurations
|
|
13
|
+
* 2. Tests both wildcard resources (for auto-generated names) and scoped resources (for explicit names)
|
|
14
|
+
* 3. Verifies policies get added to CloudFormation templates with correct structure
|
|
15
|
+
* 4. Ensures both patterns work without circular dependencies
|
|
16
|
+
*
|
|
17
|
+
* @see https://github.com/aws/aws-cdk/issues/35062
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { App, Fn, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
|
|
21
|
+
import { Construct } from 'constructs';
|
|
22
|
+
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
|
|
23
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
24
|
+
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
25
|
+
|
|
26
|
+
export class TestStack extends Stack {
|
|
27
|
+
public readonly wildcardTable: dynamodb.Table;
|
|
28
|
+
public readonly scopedTable: dynamodb.Table;
|
|
29
|
+
|
|
30
|
+
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
31
|
+
super(scope, id, props);
|
|
32
|
+
|
|
33
|
+
// TEST 1: Table with wildcard resource policy (auto-generated name)
|
|
34
|
+
// This is the standard pattern to avoid circular dependencies
|
|
35
|
+
this.wildcardTable = new dynamodb.Table(this, 'WildcardTable', {
|
|
36
|
+
partitionKey: {
|
|
37
|
+
name: 'id',
|
|
38
|
+
type: dynamodb.AttributeType.STRING,
|
|
39
|
+
},
|
|
40
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Add resource policy with wildcard resources
|
|
44
|
+
this.wildcardTable.addToResourcePolicy(new iam.PolicyStatement({
|
|
45
|
+
actions: ['dynamodb:GetItem', 'dynamodb:PutItem', 'dynamodb:Query'],
|
|
46
|
+
principals: [new iam.AccountRootPrincipal()],
|
|
47
|
+
resources: ['*'], // Use wildcard to avoid circular dependency - standard pattern for resource policies
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
// TEST 2: Table with scoped resource policy (explicit table name)
|
|
51
|
+
// This demonstrates how to use scoped resources when table name is known at synthesis time
|
|
52
|
+
this.scopedTable = new dynamodb.Table(this, 'ScopedTable', {
|
|
53
|
+
tableName: 'my-explicit-scoped-table', // Explicit name enables scoped ARN construction
|
|
54
|
+
partitionKey: {
|
|
55
|
+
name: 'id',
|
|
56
|
+
type: dynamodb.AttributeType.STRING,
|
|
57
|
+
},
|
|
58
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Add resource policy with properly scoped resource using explicit table name
|
|
62
|
+
// This works because table name is known at synthesis time (no circular dependency)
|
|
63
|
+
this.scopedTable.addToResourcePolicy(new iam.PolicyStatement({
|
|
64
|
+
actions: ['dynamodb:GetItem', 'dynamodb:Query'],
|
|
65
|
+
principals: [new iam.AccountRootPrincipal()],
|
|
66
|
+
// Use CloudFormation intrinsic function to construct table ARN with known table name
|
|
67
|
+
resources: [Fn.sub('arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/my-explicit-scoped-table')],
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Test Setup
|
|
73
|
+
const app = new App();
|
|
74
|
+
const stack = new TestStack(app, 'add-to-resource-policy-test-stack');
|
|
75
|
+
|
|
76
|
+
// Integration Test Configuration
|
|
77
|
+
new IntegTest(app, 'add-to-resource-policy-integ-test', {
|
|
78
|
+
testCases: [stack],
|
|
79
|
+
});
|
|
80
|
+
|
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb.policy.ts
CHANGED
|
@@ -38,7 +38,27 @@ export class TestStack extends Stack {
|
|
|
38
38
|
removalPolicy: RemovalPolicy.DESTROY,
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
// IMPORTANT: Cross-account grants with auto-generated table names create circular dependencies
|
|
42
|
+
//
|
|
43
|
+
// WHY NOT this.tableTwo.grantReadData(new iam.AccountPrincipal('123456789012'))?
|
|
44
|
+
// - Cross-account principals cannot have policies attached to them
|
|
45
|
+
// - Grant falls back to adding a resource policy to the table
|
|
46
|
+
// - Resource policy tries to reference this.tableArn (the table's own ARN)
|
|
47
|
+
// - This creates a circular dependency: Table → ResourcePolicy → Table ARN → Table
|
|
48
|
+
// - CloudFormation fails with "Circular dependency between resources"
|
|
49
|
+
//
|
|
50
|
+
// SOLUTIONS:
|
|
51
|
+
// 1. Use addToResourcePolicy with wildcard resources (this approach)
|
|
52
|
+
// 2. Use explicit table names: tableName: 'my-table-name' (enables scoped resources)
|
|
53
|
+
// 3. Use same-account principals (grants go to principal policy, not resource policy)
|
|
54
|
+
//
|
|
55
|
+
this.tableTwo.addToResourcePolicy(new iam.PolicyStatement({
|
|
56
|
+
actions: ['dynamodb:*'],
|
|
57
|
+
// we need a valid account for cross-account principal otherwise it won't deploy
|
|
58
|
+
// this account is from fact-table.ts
|
|
59
|
+
principals: [new iam.AccountPrincipal('127311923021')],
|
|
60
|
+
resources: ['*'], // Wildcard avoids circular dependency - same pattern as KMS
|
|
61
|
+
}));
|
|
42
62
|
}
|
|
43
63
|
}
|
|
44
64
|
|
|
@@ -72,6 +72,10 @@ class TestStack extends Stack {
|
|
|
72
72
|
destination: FlowLogDestination.toS3(),
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
+
vpc.addFlowLog('FlowLogsCloudwatch', {
|
|
76
|
+
destination: FlowLogDestination.toCloudWatchLogs(),
|
|
77
|
+
});
|
|
78
|
+
|
|
75
79
|
const bucket = new s3.Bucket(this, 'Bucket', {
|
|
76
80
|
removalPolicy: RemovalPolicy.DESTROY,
|
|
77
81
|
autoDeleteObjects: true,
|
|
@@ -121,12 +121,51 @@ By using these methods, you can grant specific operational permissions on the EC
|
|
|
121
121
|
|
|
122
122
|
### Image tag immutability
|
|
123
123
|
|
|
124
|
-
You can set tag immutability on images in
|
|
124
|
+
You can set tag immutability on images in your repository using the `imageTagMutability` construct prop.
|
|
125
125
|
|
|
126
126
|
```ts
|
|
127
127
|
new ecr.Repository(this, 'Repo', { imageTagMutability: ecr.TagMutability.IMMUTABLE });
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
+
#### Image tag mutability with exclusion filters
|
|
131
|
+
|
|
132
|
+
ECR supports more granular control over image tag mutability by allowing you to specify exclusion filters. This enables you to make your repository immutable while allowing specific tag patterns to remain mutable (or vice versa).
|
|
133
|
+
|
|
134
|
+
There are two new mutability options that work with exclusion filters:
|
|
135
|
+
|
|
136
|
+
- `MUTABLE_WITH_EXCLUSION`: Tags are mutable by default, except those matching the exclusion filters
|
|
137
|
+
- `IMMUTABLE_WITH_EXCLUSION`: Tags are immutable by default, except those matching the exclusion filters
|
|
138
|
+
|
|
139
|
+
Use `ImageTagMutabilityExclusionFilter.wildcard()` to create filters with wildcard patterns:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
// Make all tags immutable except for those starting with 'dev-' or 'test-'
|
|
143
|
+
new ecr.Repository(this, 'Repo', {
|
|
144
|
+
imageTagMutability: ecr.TagMutability.IMMUTABLE_WITH_EXCLUSION,
|
|
145
|
+
imageTagMutabilityExclusionFilters: [
|
|
146
|
+
ecr.ImageTagMutabilityExclusionFilter.wildcard('dev-*'),
|
|
147
|
+
ecr.ImageTagMutabilityExclusionFilter.wildcard('test-*'),
|
|
148
|
+
],
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
// Make all tags mutable except for production releases
|
|
154
|
+
new ecr.Repository(this, 'Repo', {
|
|
155
|
+
imageTagMutability: ecr.TagMutability.MUTABLE_WITH_EXCLUSION,
|
|
156
|
+
imageTagMutabilityExclusionFilters: [
|
|
157
|
+
ecr.ImageTagMutabilityExclusionFilter.wildcard('prod-*'),
|
|
158
|
+
ecr.ImageTagMutabilityExclusionFilter.wildcard('release-v*'),
|
|
159
|
+
],
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
##### Exclusion filter pattern rules
|
|
164
|
+
|
|
165
|
+
- Patterns can contain alphanumeric characters, dots (.), underscores (_), hyphens (-), and asterisks (*) as wildcards
|
|
166
|
+
- Maximum pattern length is 128 characters
|
|
167
|
+
- You can specify up to 5 exclusion filters per repository
|
|
168
|
+
|
|
130
169
|
### Encryption
|
|
131
170
|
|
|
132
171
|
By default, Amazon ECR uses server-side encryption with Amazon S3-managed encryption keys which encrypts your data at rest using an AES-256 encryption algorithm. For more control over the encryption for your Amazon ECR repositories, you can use server-side encryption with KMS keys stored in AWS Key Management Service (AWS KMS). Read more about this feature in the [ECR Developer Guide](https://docs.aws.amazon.com/AmazonECR/latest/userguide/encryption-at-rest.html).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
3
|
+
import * as ecr from 'aws-cdk-lib/aws-ecr';
|
|
4
|
+
|
|
5
|
+
const app = new cdk.App();
|
|
6
|
+
const stack = new cdk.Stack(app, 'aws-ecr-tag-mutability-exclusion-stack');
|
|
7
|
+
|
|
8
|
+
new ecr.Repository(stack, 'ImmutableRepoWithExclusions', {
|
|
9
|
+
imageTagMutability: ecr.TagMutability.IMMUTABLE_WITH_EXCLUSION,
|
|
10
|
+
imageTagMutabilityExclusionFilters: [
|
|
11
|
+
ecr.ImageTagMutabilityExclusionFilter.wildcard('dev-*'),
|
|
12
|
+
ecr.ImageTagMutabilityExclusionFilter.wildcard('test-*'),
|
|
13
|
+
],
|
|
14
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
15
|
+
emptyOnDelete: true,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
new ecr.Repository(stack, 'MutableRepoWithExclusions', {
|
|
19
|
+
imageTagMutability: ecr.TagMutability.MUTABLE_WITH_EXCLUSION,
|
|
20
|
+
imageTagMutabilityExclusionFilters: [
|
|
21
|
+
ecr.ImageTagMutabilityExclusionFilter.wildcard('prod-*'),
|
|
22
|
+
ecr.ImageTagMutabilityExclusionFilter.wildcard('release-v*'),
|
|
23
|
+
],
|
|
24
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
25
|
+
emptyOnDelete: true,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
new IntegTest(app, 'cdk-ecr-tag-mutability-exclusion-test', {
|
|
29
|
+
testCases: [stack],
|
|
30
|
+
});
|
|
@@ -1687,6 +1687,9 @@ const miCapacityProvider = new ecs.ManagedInstancesCapacityProvider(this, 'MICap
|
|
|
1687
1687
|
propagateTags: ecs.PropagateManagedInstancesTags.CAPACITY_PROVIDER,
|
|
1688
1688
|
});
|
|
1689
1689
|
|
|
1690
|
+
// Optionally configure security group rules using IConnectable interface
|
|
1691
|
+
miCapacityProvider.connections.allowFrom(ec2.Peer.ipv4(vpc.vpcCidrBlock), ec2.Port.tcp(80));
|
|
1692
|
+
|
|
1690
1693
|
// Add the capacity provider to the cluster
|
|
1691
1694
|
cluster.addManagedInstancesCapacityProvider(miCapacityProvider);
|
|
1692
1695
|
|
|
@@ -24,7 +24,7 @@ const infrastructureRole = new iam.Role(stack, 'InfrastructureRole', {
|
|
|
24
24
|
roleName: 'AmazonECSInfrastructureRoleForOmakase',
|
|
25
25
|
assumedBy: new iam.ServicePrincipal('ecs.amazonaws.com'),
|
|
26
26
|
managedPolicies: [
|
|
27
|
-
iam.ManagedPolicy.fromAwsManagedPolicyName('
|
|
27
|
+
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonECSInfrastructureRolePolicyForManagedInstances'),
|
|
28
28
|
],
|
|
29
29
|
});
|
|
30
30
|
|
|
@@ -32,7 +32,7 @@ const instanceRole = new iam.Role(stack, 'InstanceRole', {
|
|
|
32
32
|
roleName: 'AmazonECSInstanceRoleForOmakase',
|
|
33
33
|
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
|
|
34
34
|
managedPolicies: [
|
|
35
|
-
iam.ManagedPolicy.fromAwsManagedPolicyName('
|
|
35
|
+
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonECSInstanceRolePolicyForManagedInstances'),
|
|
36
36
|
],
|
|
37
37
|
});
|
|
38
38
|
|
|
@@ -63,6 +63,9 @@ const miCapacityProvider = new ecs.ManagedInstancesCapacityProvider(stack, 'Mana
|
|
|
63
63
|
},
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
+
// Configure security group rules using IConnectable interface
|
|
67
|
+
miCapacityProvider.connections.allowFrom(ec2.Peer.ipv4(vpc.vpcCidrBlock), ec2.Port.tcp(80));
|
|
68
|
+
|
|
66
69
|
// Add FMI capacity provider to cluster
|
|
67
70
|
cluster.addManagedInstancesCapacityProvider(miCapacityProvider);
|
|
68
71
|
cluster.addDefaultCapacityProviderStrategy([
|
|
@@ -106,7 +109,6 @@ new ecs.FargateService(stack, 'ManagedInstancesService', {
|
|
|
106
109
|
|
|
107
110
|
new integ.IntegTest(app, 'ManagedInstancesCapacityProviders', {
|
|
108
111
|
testCases: [stack],
|
|
109
|
-
regions: ['us-west-2'],
|
|
110
112
|
});
|
|
111
113
|
|
|
112
114
|
app.synth();
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
2
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
3
|
+
import * as cdk from 'aws-cdk-lib';
|
|
4
|
+
import * as ecs from 'aws-cdk-lib/aws-ecs';
|
|
5
|
+
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
6
|
+
|
|
7
|
+
const app = new cdk.App({
|
|
8
|
+
postCliContext: {
|
|
9
|
+
'@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm': true,
|
|
10
|
+
'@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false,
|
|
11
|
+
'@aws-cdk/aws-ecs:disableEcsImdsBlocking': false,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
const stack = new cdk.Stack(app, 'integ-managedinstances-no-default-capacity-provider');
|
|
15
|
+
|
|
16
|
+
const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false });
|
|
17
|
+
const cluster = new ecs.Cluster(stack, 'ManagedInstancesCluster', {
|
|
18
|
+
vpc,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Create IAM roles required for FMI following Omakase specifications
|
|
22
|
+
const infrastructureRole = new iam.Role(stack, 'InfrastructureRole', {
|
|
23
|
+
roleName: 'InfrastructureRole',
|
|
24
|
+
assumedBy: new iam.ServicePrincipal('ecs.amazonaws.com'),
|
|
25
|
+
managedPolicies: [
|
|
26
|
+
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonECSInfrastructureRolePolicyForManagedInstances'),
|
|
27
|
+
],
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const instanceRole = new iam.Role(stack, 'InstanceRole', {
|
|
31
|
+
roleName: 'InstanceRole',
|
|
32
|
+
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
|
|
33
|
+
managedPolicies: [
|
|
34
|
+
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonECSInstanceRolePolicyForManagedInstances'),
|
|
35
|
+
],
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
infrastructureRole.grantPassRole(instanceRole);
|
|
39
|
+
|
|
40
|
+
const instanceProfile = new iam.InstanceProfile(stack, 'InstanceProfile', {
|
|
41
|
+
instanceProfileName: 'InstanceProfile',
|
|
42
|
+
role: instanceRole,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Create a security group for FMI instances
|
|
46
|
+
const fmiSecurityGroup = new ec2.SecurityGroup(stack, 'ManagedInstancesSecurityGroup', {
|
|
47
|
+
vpc,
|
|
48
|
+
description: 'Security group for ManagedInstances capacity provider instances',
|
|
49
|
+
allowAllOutbound: true,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Create MI Capacity Provider
|
|
53
|
+
const miCapacityProvider = new ecs.ManagedInstancesCapacityProvider(stack, 'ManagedInstancesCapacityProvider', {
|
|
54
|
+
infrastructureRole: infrastructureRole,
|
|
55
|
+
ec2InstanceProfile: instanceProfile,
|
|
56
|
+
subnets: vpc.privateSubnets,
|
|
57
|
+
securityGroups: [fmiSecurityGroup],
|
|
58
|
+
propagateTags: ecs.PropagateManagedInstancesTags.CAPACITY_PROVIDER,
|
|
59
|
+
instanceRequirements: {
|
|
60
|
+
vCpuCountMin: 1,
|
|
61
|
+
memoryMin: cdk.Size.gibibytes(2),
|
|
62
|
+
cpuManufacturers: [ec2.CpuManufacturer.INTEL],
|
|
63
|
+
acceleratorManufacturers: [ec2.AcceleratorManufacturer.NVIDIA],
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Add FMI capacity provider to cluster
|
|
68
|
+
cluster.addManagedInstancesCapacityProvider(miCapacityProvider);
|
|
69
|
+
|
|
70
|
+
// Create a task definition compatible with Managed Instances and Fargate
|
|
71
|
+
const taskDefinition = new ecs.TaskDefinition(stack, 'TaskDef', {
|
|
72
|
+
compatibility: ecs.Compatibility.FARGATE_AND_MANAGED_INSTANCES,
|
|
73
|
+
cpu: '256',
|
|
74
|
+
memoryMiB: '512',
|
|
75
|
+
networkMode: ecs.NetworkMode.AWS_VPC,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
taskDefinition.addContainer('web', {
|
|
79
|
+
image: ecs.ContainerImage.fromRegistry('public.ecr.aws/docker/library/httpd:2.4'),
|
|
80
|
+
memoryLimitMiB: 512,
|
|
81
|
+
portMappings: [
|
|
82
|
+
{
|
|
83
|
+
containerPort: 80,
|
|
84
|
+
protocol: ecs.Protocol.TCP,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Create a service using the MI capacity provider
|
|
90
|
+
new ecs.FargateService(stack, 'ManagedInstancesService', {
|
|
91
|
+
cluster,
|
|
92
|
+
taskDefinition,
|
|
93
|
+
capacityProviderStrategies: [
|
|
94
|
+
{
|
|
95
|
+
capacityProvider: miCapacityProvider.capacityProviderName,
|
|
96
|
+
weight: 1,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
desiredCount: 1,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
new integ.IntegTest(app, 'ManagedInstancesCapacityProviders', {
|
|
103
|
+
testCases: [stack],
|
|
104
|
+
regions: ['us-west-2'],
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
app.synth();
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
2
|
+
import * as ecs from 'aws-cdk-lib/aws-ecs';
|
|
3
|
+
import * as cdk from 'aws-cdk-lib';
|
|
4
|
+
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
5
|
+
import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns';
|
|
6
|
+
|
|
7
|
+
const app = new cdk.App();
|
|
8
|
+
const stack = new cdk.Stack(app, 'aws-ecs-integ-alb-fargate-public-private-switch');
|
|
9
|
+
|
|
10
|
+
const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false });
|
|
11
|
+
const cluster = new ecs.Cluster(stack, 'FargateCluster', { vpc });
|
|
12
|
+
|
|
13
|
+
// Test private load balancer (the problematic case from the issue)
|
|
14
|
+
new ecsPatterns.ApplicationLoadBalancedFargateService(stack, 'PrivateALBFargateService', {
|
|
15
|
+
cluster,
|
|
16
|
+
memoryLimitMiB: 1024,
|
|
17
|
+
cpu: 512,
|
|
18
|
+
publicLoadBalancer: false, // This should create ECSPrivate target group
|
|
19
|
+
taskImageOptions: {
|
|
20
|
+
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Test public load balancer for comparison
|
|
25
|
+
new ecsPatterns.ApplicationLoadBalancedFargateService(stack, 'PublicALBFargateService', {
|
|
26
|
+
cluster,
|
|
27
|
+
memoryLimitMiB: 1024,
|
|
28
|
+
cpu: 512,
|
|
29
|
+
publicLoadBalancer: true, // This should create ECS target group
|
|
30
|
+
taskImageOptions: {
|
|
31
|
+
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
new integ.IntegTest(app, 'ALBFargatePublicPrivateSwitchTest', {
|
|
36
|
+
testCases: [stack],
|
|
37
|
+
allowDestroy: [
|
|
38
|
+
'PrivateALBFargateServiceLB3F43693F',
|
|
39
|
+
'PrivateALBFargateServiceLBPublicListenerECSPrivateGroup81AA5B8B',
|
|
40
|
+
'PublicALBFargateServiceLBBDD839E7',
|
|
41
|
+
'PublicALBFargateServiceLBPublicListenerECSGroupD991EA00',
|
|
42
|
+
],
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
app.synth();
|
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-elasticloadbalancingv2/README.md
CHANGED
|
@@ -338,17 +338,13 @@ Balancers:
|
|
|
338
338
|
```ts
|
|
339
339
|
declare const vpc: ec2.Vpc;
|
|
340
340
|
declare const asg: autoscaling.AutoScalingGroup;
|
|
341
|
-
declare const sg1: ec2.ISecurityGroup;
|
|
342
|
-
declare const sg2: ec2.ISecurityGroup;
|
|
343
341
|
|
|
344
342
|
// Create the load balancer in a VPC. 'internetFacing' is 'false'
|
|
345
343
|
// by default, which creates an internal load balancer.
|
|
346
344
|
const lb = new elbv2.NetworkLoadBalancer(this, 'LB', {
|
|
347
345
|
vpc,
|
|
348
346
|
internetFacing: true,
|
|
349
|
-
securityGroups: [sg1],
|
|
350
347
|
});
|
|
351
|
-
lb.addSecurityGroup(sg2);
|
|
352
348
|
|
|
353
349
|
// Add a listener on a particular port.
|
|
354
350
|
const listener = lb.addListener('Listener', {
|
|
@@ -362,6 +358,40 @@ listener.addTargets('AppFleet', {
|
|
|
362
358
|
});
|
|
363
359
|
```
|
|
364
360
|
|
|
361
|
+
### Security Groups for Network Load Balancer
|
|
362
|
+
|
|
363
|
+
By default, Network Load Balancers (NLB) have a security group associated with them.
|
|
364
|
+
This is controlled by the feature flag `@aws-cdk/aws-elasticloadbalancingv2:networkLoadBalancerWithSecurityGroupByDefault`.
|
|
365
|
+
When this flag is enabled (the default for new projects), a security group will be automatically created and attached to the NLB unless you explicitly provide your own security groups via the `securityGroups` property.
|
|
366
|
+
|
|
367
|
+
If you wish to create an NLB without any security groups, you can set the `disableSecurityGroups` property to `true`. When this property is set, no security group will be associated with the NLB, regardless of the feature flag.
|
|
368
|
+
|
|
369
|
+
```ts
|
|
370
|
+
declare const vpc: ec2.IVpc;
|
|
371
|
+
|
|
372
|
+
const nlb = new elbv2.NetworkLoadBalancer(this, 'LB', {
|
|
373
|
+
vpc,
|
|
374
|
+
// To disable security groups for this NLB
|
|
375
|
+
disableSecurityGroups: true,
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
If you want to use your own security groups, provide them via the `securityGroups` property:
|
|
380
|
+
|
|
381
|
+
```ts
|
|
382
|
+
declare const vpc: ec2.IVpc;
|
|
383
|
+
declare const sg1: ec2.ISecurityGroup;
|
|
384
|
+
declare const sg2: ec2.ISecurityGroup;
|
|
385
|
+
|
|
386
|
+
const nlb = new elbv2.NetworkLoadBalancer(this, 'LB', {
|
|
387
|
+
vpc,
|
|
388
|
+
// Provide your own security groups
|
|
389
|
+
securityGroups: [sg1],
|
|
390
|
+
});
|
|
391
|
+
// Add another security group to the NLB
|
|
392
|
+
nlb.addSecurityGroup(sg2);
|
|
393
|
+
```
|
|
394
|
+
|
|
365
395
|
### Enforce security group inbound rules on PrivateLink traffic for a Network Load Balancer
|
|
366
396
|
|
|
367
397
|
You can indicate whether to evaluate inbound security group rules for traffic
|
|
@@ -19,7 +19,7 @@ const vpc = new ec2.Vpc(stack, 'VPC', {
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
const fn = new lambda.Function(stack, 'Function', {
|
|
22
|
-
runtime: lambda.Runtime.
|
|
22
|
+
runtime: lambda.Runtime.NODEJS_20_X,
|
|
23
23
|
handler: 'index.handler',
|
|
24
24
|
code: lambda.Code.fromInline(`
|
|
25
25
|
exports.handler = async (event) => {
|
|
@@ -186,7 +186,7 @@ const signinFunction = new lambda.Function(testCase, 'Signin', {
|
|
|
186
186
|
functionName: 'cdk-integ-alb-oidc-signin-handler',
|
|
187
187
|
code: lambda.Code.fromAsset('alb-oidc-signin-handler', { exclude: ['*.ts'] }),
|
|
188
188
|
handler: 'index.handler',
|
|
189
|
-
runtime: lambda.Runtime.
|
|
189
|
+
runtime: lambda.Runtime.NODEJS_20_X,
|
|
190
190
|
environment: {
|
|
191
191
|
TEST_USERNAME: testUser.username,
|
|
192
192
|
TEST_PASSWORD: testUser.password,
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ExpectedResult, IntegTest, Match } from '@aws-cdk/integ-tests-alpha';
|
|
2
|
+
import { Stack, aws_ec2 as ec2, aws_elasticloadbalancingv2 as elbv2, App } from 'aws-cdk-lib';
|
|
3
|
+
import { Construct } from 'constructs';
|
|
4
|
+
|
|
5
|
+
class TestStack extends Stack {
|
|
6
|
+
public readonly lbWithSg: elbv2.NetworkLoadBalancer;
|
|
7
|
+
public readonly lbWithSg2: elbv2.NetworkLoadBalancer;
|
|
8
|
+
public readonly lbWithoutSg: elbv2.NetworkLoadBalancer;
|
|
9
|
+
|
|
10
|
+
constructor(scope: Construct, id: string) {
|
|
11
|
+
super(scope, id);
|
|
12
|
+
|
|
13
|
+
const vpc = new ec2.Vpc(this, 'Stack', {
|
|
14
|
+
maxAzs: 1,
|
|
15
|
+
natGateways: 0,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
this.lbWithSg = new elbv2.NetworkLoadBalancer(this, 'NlbWithSecurityGroup', {
|
|
19
|
+
vpc,
|
|
20
|
+
});
|
|
21
|
+
this.lbWithSg2 = new elbv2.NetworkLoadBalancer(this, 'NlbWithSecurityGroup2', {
|
|
22
|
+
vpc,
|
|
23
|
+
securityGroups: [new ec2.SecurityGroup(this, 'SecurityGroup', {
|
|
24
|
+
vpc,
|
|
25
|
+
allowAllOutbound: true,
|
|
26
|
+
})],
|
|
27
|
+
});
|
|
28
|
+
this.lbWithSg.connections.allowTo(this.lbWithSg2, ec2.Port.tcp(1229));
|
|
29
|
+
this.lbWithoutSg = new elbv2.NetworkLoadBalancer(this, 'NlbWithoutSecurityGroup', {
|
|
30
|
+
vpc,
|
|
31
|
+
disableSecurityGroups: true,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const app = new App({
|
|
37
|
+
postCliContext: {
|
|
38
|
+
'@aws-cdk/aws-elasticloadbalancingv2:networkLoadBalancerWithSecurityGroupByDefault': true,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
const stack = new TestStack(app, 'NlbSecurityGroupStack');
|
|
42
|
+
const integ = new IntegTest(app, 'NlbSecurityGroupInteg', {
|
|
43
|
+
testCases: [stack],
|
|
44
|
+
});
|
|
45
|
+
integ.assertions.awsApiCall('elastic-load-balancing-v2', 'describeLoadBalancers', {
|
|
46
|
+
LoadBalancerArns: [
|
|
47
|
+
stack.lbWithSg.loadBalancerArn,
|
|
48
|
+
stack.lbWithSg2.loadBalancerArn,
|
|
49
|
+
stack.lbWithoutSg.loadBalancerArn,
|
|
50
|
+
],
|
|
51
|
+
}).expect(ExpectedResult.objectLike({
|
|
52
|
+
LoadBalancers: [
|
|
53
|
+
Match.objectLike({
|
|
54
|
+
LoadBalancerArn: stack.lbWithSg.loadBalancerArn,
|
|
55
|
+
SecurityGroups: Match.arrayWith([
|
|
56
|
+
Match.stringLikeRegexp('sg-[0-9a-f]{8,17}'),
|
|
57
|
+
]),
|
|
58
|
+
}),
|
|
59
|
+
Match.objectLike({
|
|
60
|
+
LoadBalancerArn: stack.lbWithSg2.loadBalancerArn,
|
|
61
|
+
SecurityGroups: Match.arrayWith([
|
|
62
|
+
Match.stringLikeRegexp('sg-[0-9a-f]{8,17}'),
|
|
63
|
+
]),
|
|
64
|
+
}),
|
|
65
|
+
Match.objectLike({
|
|
66
|
+
LoadBalancerArn: stack.lbWithoutSg.loadBalancerArn,
|
|
67
|
+
SecurityGroups: undefined,
|
|
68
|
+
}),
|
|
69
|
+
],
|
|
70
|
+
}));
|
|
@@ -206,7 +206,7 @@ const signinFunction = new lambda.Function(testCase, 'Signin', {
|
|
|
206
206
|
functionName: 'cdk-integ-alb-cognito-signin-handler',
|
|
207
207
|
code: lambda.Code.fromAsset('alb-cognito-signin-handler', { exclude: ['*.ts'] }),
|
|
208
208
|
handler: 'index.handler',
|
|
209
|
-
runtime: lambda.Runtime.
|
|
209
|
+
runtime: lambda.Runtime.NODEJS_20_X,
|
|
210
210
|
environment: {
|
|
211
211
|
TEST_USERNAME: testUser.username,
|
|
212
212
|
TEST_PASSWORD: testUser.password,
|
|
@@ -19,6 +19,7 @@ Currently supported are:
|
|
|
19
19
|
- [Invoke an API Destination](#invoke-an-api-destination)
|
|
20
20
|
- [Invoke an AppSync GraphQL API](#invoke-an-appsync-graphql-api)
|
|
21
21
|
- [Put an event on an EventBridge bus](#put-an-event-on-an-eventbridge-bus)
|
|
22
|
+
- [Put an event on a Firehose delivery stream](#put-an-event-on-a-firehose-delivery-stream)
|
|
22
23
|
- [Run an ECS Task](#run-an-ecs-task)
|
|
23
24
|
- [Tagging Tasks](#tagging-tasks)
|
|
24
25
|
- [Launch type for ECS Task](#launch-type-for-ecs-task)
|
|
@@ -528,6 +529,27 @@ rule.addTarget(new targets.EventBus(
|
|
|
528
529
|
));
|
|
529
530
|
```
|
|
530
531
|
|
|
532
|
+
## Put an event on a Firehose delivery stream
|
|
533
|
+
|
|
534
|
+
Use the `FirehoseDeliveryStream` target to put event to an Amazon Data Firehose delivery stream.
|
|
535
|
+
|
|
536
|
+
The code snippet below creates the scheduled event rule that put events to an Amazon Data Firehose delivery stream.
|
|
537
|
+
|
|
538
|
+
```ts
|
|
539
|
+
import * as firehose from 'aws-cdk-lib/aws-kinesisfirehose';
|
|
540
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
541
|
+
|
|
542
|
+
declare const bucket: s3.Bucket;
|
|
543
|
+
const stream = new firehose.DeliveryStream(this, 'DeliveryStream', {
|
|
544
|
+
destination: new firehose.S3Bucket(bucket),
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
const rule = new events.Rule(this, 'Rule', {
|
|
548
|
+
schedule: events.Schedule.expression('rate(1 minute)'),
|
|
549
|
+
});
|
|
550
|
+
rule.addTarget(new targets.FirehoseDeliveryStream(stream));
|
|
551
|
+
```
|
|
552
|
+
|
|
531
553
|
## Run an ECS Task
|
|
532
554
|
|
|
533
555
|
Use the `EcsTask` target to run an ECS Task.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as events from 'aws-cdk-lib/aws-events';
|
|
2
|
+
import * as firehose from 'aws-cdk-lib/aws-kinesisfirehose';
|
|
3
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
4
|
+
import * as cdk from 'aws-cdk-lib';
|
|
5
|
+
import * as targets from 'aws-cdk-lib/aws-events-targets';
|
|
6
|
+
import { IntegTest, ExpectedResult, AwsApiCall } from '@aws-cdk/integ-tests-alpha';
|
|
7
|
+
|
|
8
|
+
// ---------------------------------
|
|
9
|
+
// Define a rule that triggers a put to a Firehose delivery stream every 1min.
|
|
10
|
+
|
|
11
|
+
const app = new cdk.App();
|
|
12
|
+
|
|
13
|
+
const stack = new cdk.Stack(app, 'aws-cdk-firehose-event-target');
|
|
14
|
+
|
|
15
|
+
const bucket = new s3.Bucket(stack, 'firehose-bucket', {
|
|
16
|
+
autoDeleteObjects: true,
|
|
17
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
18
|
+
});
|
|
19
|
+
const deliveryStream = new firehose.DeliveryStream(stack, 'MyDeliveryStream', {
|
|
20
|
+
destination: new firehose.S3Bucket(bucket, {
|
|
21
|
+
bufferingInterval: cdk.Duration.seconds(30),
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const event = new events.Rule(stack, 'EveryMinute', {
|
|
26
|
+
schedule: events.Schedule.rate(cdk.Duration.minutes(1)),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
event.addTarget(new targets.FirehoseDeliveryStream(deliveryStream));
|
|
30
|
+
|
|
31
|
+
const testCase = new IntegTest(app, 'firehose-event-target-integ', {
|
|
32
|
+
testCases: [stack],
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const s3ApiCall = testCase.assertions.awsApiCall('S3', 'listObjectsV2', {
|
|
36
|
+
Bucket: bucket.bucketName,
|
|
37
|
+
MaxKeys: 1,
|
|
38
|
+
}).expect(ExpectedResult.objectLike({
|
|
39
|
+
KeyCount: 1,
|
|
40
|
+
})).waitForAssertions({
|
|
41
|
+
interval: cdk.Duration.seconds(30),
|
|
42
|
+
totalTimeout: cdk.Duration.minutes(10),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (s3ApiCall instanceof AwsApiCall) {
|
|
46
|
+
s3ApiCall.waiterProvider?.addToRolePolicy({
|
|
47
|
+
Effect: 'Allow',
|
|
48
|
+
Action: ['s3:GetObject', 's3:ListBucket'],
|
|
49
|
+
Resource: ['*'],
|
|
50
|
+
});
|
|
51
|
+
}
|