konokenj.cdk-api-mcp-server 0.41.0__py3-none-any.whl → 0.43.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 (46) hide show
  1. cdk_api_mcp_server/__about__.py +1 -1
  2. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-bedrock-alpha/README.md +540 -0
  3. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-eks-v2-alpha/README.md +44 -46
  4. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-glue-alpha/README.md +9 -9
  5. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-lambda-python-alpha/README.md +6 -6
  6. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-s3tables-alpha/README.md +28 -1
  7. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api-dualstack.ts +3 -4
  8. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api.ts +2 -4
  9. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.stage.ts +7 -20
  10. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-authorizers/integ.iam.ts +34 -38
  11. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.sqs.ts +58 -71
  12. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-certificatemanager/README.md +11 -0
  13. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/README.md +13 -0
  14. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/integ.dashboard-with-graphwidget-with-labels-visible.ts +92 -0
  15. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/integ.pipeline-elastic-beanstalk-deploy.ts +1 -1
  16. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cognito/README.md +11 -0
  17. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cognito/integ.user-pool-client-explicit-props.ts +1 -0
  18. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/README.md +38 -13
  19. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb-v2.cci.ts +49 -0
  20. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb.cci.ts +27 -0
  21. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb.contirubtor-insights-for-gsi.ts +6 -2
  22. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.table-v2-global.ts +9 -3
  23. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/README.md +3 -0
  24. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.ebs-volume-initialization-rate.ts +80 -0
  25. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs-patterns/README.md +2 -0
  26. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs-patterns/integ.alb-fargate-service-smart-defaults.ts +143 -0
  27. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events/README.md +25 -3
  28. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events/integ.archive-customer-managed-key.ts +23 -0
  29. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events-targets/README.md +64 -2
  30. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/README.md +18 -0
  31. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.cluster.ts +1 -1
  32. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-assets/integ.assets.bundling.docker-opts.ts +4 -1
  33. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/README.md +18 -0
  34. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-sns/README.md +2 -0
  35. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-sns-subscriptions/integ.sns-sqs-subscription-filter.ts +75 -0
  36. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-sns-subscriptions/integ.sns-sqs.ts +21 -40
  37. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.evaluate-expression-nodejs22.ts +27 -0
  38. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.invoke-jsonata.ts +87 -80
  39. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.invoke.ts +87 -69
  40. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.start-job-run.ts +102 -104
  41. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +28 -1
  42. {konokenj_cdk_api_mcp_server-0.41.0.dist-info → konokenj_cdk_api_mcp_server-0.43.0.dist-info}/METADATA +2 -2
  43. {konokenj_cdk_api_mcp_server-0.41.0.dist-info → konokenj_cdk_api_mcp_server-0.43.0.dist-info}/RECORD +46 -38
  44. {konokenj_cdk_api_mcp_server-0.41.0.dist-info → konokenj_cdk_api_mcp_server-0.43.0.dist-info}/WHEEL +0 -0
  45. {konokenj_cdk_api_mcp_server-0.41.0.dist-info → konokenj_cdk_api_mcp_server-0.43.0.dist-info}/entry_points.txt +0 -0
  46. {konokenj_cdk_api_mcp_server-0.41.0.dist-info → konokenj_cdk_api_mcp_server-0.43.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Integration test for the conditional openListener behavior in ApplicationLoadBalancedFargateService.
3
+ *
4
+ * This test validates the security feature that automatically sets openListener to false when custom
5
+ * security groups are detected on the load balancer, preventing unintended internet exposure.
6
+ *
7
+ * Test scenarios:
8
+ * 1. DefaultService: No custom security groups provided
9
+ * - Expected: openListener defaults to true, creates 0.0.0.0/0 ingress rules
10
+ * - Validates: Default behavior when CDK manages all security groups
11
+ *
12
+ * 2. ExplicitOpenService: Explicit openListener: true
13
+ * - Expected: Creates 0.0.0.0/0 ingress rules regardless of other settings
14
+ * - Validates: Explicit override functionality works correctly
15
+ *
16
+ * 3. ExplicitClosedService: Explicit openListener: false
17
+ * - Expected: Does NOT create 0.0.0.0/0 ingress rules
18
+ * - Validates: Explicit closed listener prevents internet access
19
+ *
20
+ * 4. ConditionalWithCustomSG: Custom security groups + no explicit openListener
21
+ * - Expected: Conditional behavior kicks in, openListener defaults to false
22
+ * - Validates: Core feature - prevents 0.0.0.0/0 rules when custom SGs detected
23
+ *
24
+ * The test uses AWS SDK calls to verify actual security group configurations in deployed resources,
25
+ * ensuring the feature works correctly in real AWS environments.
26
+ */
27
+
28
+ import { Vpc, SecurityGroup, Port } from 'aws-cdk-lib/aws-ec2';
29
+ import { Cluster, ContainerImage } from 'aws-cdk-lib/aws-ecs';
30
+ import { ApplicationLoadBalancer } from 'aws-cdk-lib/aws-elasticloadbalancingv2';
31
+ import { App, Stack, Duration } from 'aws-cdk-lib';
32
+ import * as integ from '@aws-cdk/integ-tests-alpha';
33
+ import { ApplicationLoadBalancedFargateService } from 'aws-cdk-lib/aws-ecs-patterns';
34
+
35
+ const app = new App({
36
+ postCliContext: {
37
+ // Enable the feature flag for this test
38
+ '@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener': true,
39
+ },
40
+ });
41
+
42
+ const stack = new Stack(app, 'aws-ecs-integ-alb-fg-smart-defaults');
43
+ const vpc = new Vpc(stack, 'Vpc', { maxAzs: 3, natGateways: 1, restrictDefaultSecurityGroup: false });
44
+ const cluster = new Cluster(stack, 'Cluster', { vpc });
45
+
46
+ // Test case 1: Service with conditional default (no openListener specified)
47
+ // CDK creates load balancer, should default to openListener: true (no custom security groups)
48
+ new ApplicationLoadBalancedFargateService(stack, 'SmartDefaultService', {
49
+ cluster,
50
+ memoryLimitMiB: 512,
51
+ taskImageOptions: {
52
+ image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
53
+ },
54
+ // No openListener specified - should default to true since no custom security groups
55
+ });
56
+
57
+ // Test case 2: Service with explicit openListener: true
58
+ new ApplicationLoadBalancedFargateService(stack, 'ExplicitOpenService', {
59
+ cluster,
60
+ memoryLimitMiB: 512,
61
+ taskImageOptions: {
62
+ image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
63
+ },
64
+ openListener: true, // Should create 0.0.0.0/0 rules
65
+ listenerPort: 8080,
66
+ });
67
+
68
+ // Test case 3: Service with explicit openListener: false
69
+ new ApplicationLoadBalancedFargateService(stack, 'ExplicitClosedService', {
70
+ cluster,
71
+ memoryLimitMiB: 512,
72
+ taskImageOptions: {
73
+ image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
74
+ },
75
+ openListener: false, // Should NOT create 0.0.0.0/0 rules
76
+ listenerPort: 9090,
77
+ });
78
+
79
+ // Test case 4: Service with custom security groups (conditional default should apply)
80
+ const customSecurityGroup = new SecurityGroup(stack, 'CustomSecurityGroup', {
81
+ vpc,
82
+ description: 'Custom security group for load balancer',
83
+ });
84
+
85
+ // Add a custom rule to the security group
86
+ customSecurityGroup.addIngressRule(
87
+ customSecurityGroup,
88
+ Port.tcp(80),
89
+ 'Allow HTTP from custom security group',
90
+ );
91
+
92
+ const customLoadBalancer = new ApplicationLoadBalancer(stack, 'CustomLoadBalancer', {
93
+ vpc,
94
+ internetFacing: true,
95
+ securityGroup: customSecurityGroup,
96
+ });
97
+
98
+ // This should use conditional default (openListener: false) because custom security groups are detected
99
+ new ApplicationLoadBalancedFargateService(stack, 'SmartDefaultWithCustomSG', {
100
+ cluster,
101
+ memoryLimitMiB: 512,
102
+ taskImageOptions: {
103
+ image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
104
+ },
105
+ loadBalancer: customLoadBalancer,
106
+ // No openListener specified - should default to false due to custom security groups
107
+ });
108
+
109
+ const integTest = new integ.IntegTest(app, 'albFargateServiceSmartDefaultsTest', {
110
+ testCases: [stack],
111
+ });
112
+
113
+ // Validate the core conditional behavior by checking the custom security group
114
+ // This confirms that when custom security groups are provided, the conditional default prevents
115
+ // creating overly permissive 0.0.0.0/0 ingress rules
116
+ // Assert that the custom security group only contains self-referencing rules (no 0.0.0.0/0)
117
+ // This validates the feature prevents unintended internet exposure
118
+ integTest.assertions.awsApiCall('EC2', 'describeSecurityGroups', {
119
+ GroupIds: [customSecurityGroup.securityGroupId],
120
+ }).expect(integ.ExpectedResult.objectLike({
121
+ SecurityGroups: [
122
+ {
123
+ IpPermissions: integ.Match.arrayWith([
124
+ integ.Match.objectLike({
125
+ FromPort: 80,
126
+ ToPort: 80,
127
+ // Verify only security group references exist, no public internet access (0.0.0.0/0)
128
+ UserIdGroupPairs: integ.Match.arrayWith([
129
+ integ.Match.objectLike({
130
+ GroupId: customSecurityGroup.securityGroupId,
131
+ }),
132
+ ]),
133
+ // Ensure no IpRanges with 0.0.0.0/0 are present
134
+ IpRanges: [],
135
+ }),
136
+ ]),
137
+ },
138
+ ],
139
+ })).waitForAssertions({
140
+ totalTimeout: Duration.minutes(5),
141
+ });
142
+
143
+ app.synth();
@@ -332,6 +332,28 @@ new events.EventBus(this, 'Bus', {
332
332
  });
333
333
  ```
334
334
 
335
- **Note**: Archives and schema discovery are not supported for event buses encrypted using a customer managed key.
336
- To enable archives or schema discovery on an event bus, choose to use an AWS owned key.
337
- For more information, see [KMS key options for event bus encryption](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-encryption-at-rest-key-options.html).
335
+ To use a customer managed key for an archive, use the `kmsKey` attribute.
336
+
337
+ Note: When you attach a customer managed key to either an EventBus or an Archive, a policy that allows EventBridge to interact with your resource will be added.
338
+
339
+ ```ts
340
+ import * as kms from 'aws-cdk-lib/aws-kms';
341
+ import { Archive, EventBus } from 'aws-cdk-lib/aws-events';
342
+
343
+ const stack = new Stack();
344
+
345
+ declare const kmsKey: kms.IKey;
346
+
347
+ const eventBus = new EventBus(stack, 'Bus');
348
+
349
+ const archive = new Archive(stack, 'Archive', {
350
+ kmsKey: kmsKey,
351
+ sourceEventBus: eventBus,
352
+ eventPattern: {
353
+ source: ['aws.ec2']
354
+ },
355
+ });
356
+ ```
357
+
358
+ To enable archives or schema discovery on an event bus, customers has the choice of using either an AWS owned key or a customer managed key.
359
+ For more information, see [KMS key options for event bus encryption](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-encryption-at-rest-key-options.html).
@@ -0,0 +1,23 @@
1
+ import * as kms from 'aws-cdk-lib/aws-kms';
2
+ import { App, RemovalPolicy, Stack } from 'aws-cdk-lib';
3
+ import { IntegTest } from '@aws-cdk/integ-tests-alpha';
4
+ import { Archive, EventBus } from 'aws-cdk-lib/aws-events';
5
+
6
+ const app = new App();
7
+ const stack = new Stack(app, 'archive-customer-managed-key');
8
+
9
+ const kmsKey = new kms.Key(stack, 'KmsKey', {
10
+ removalPolicy: RemovalPolicy.DESTROY,
11
+ });
12
+
13
+ new Archive(stack, 'Archive', {
14
+ kmsKey: kmsKey,
15
+ sourceEventBus: EventBus.fromEventBusName(stack, 'DefaultEventBus', 'default'),
16
+ eventPattern: {
17
+ source: ['test'],
18
+ },
19
+ });
20
+
21
+ new IntegTest(app, 'archive-customer-managed-key-test', {
22
+ testCases: [stack],
23
+ });
@@ -15,6 +15,7 @@ Currently supported are:
15
15
  - [Start a StepFunctions state machine](#start-a-stepfunctions-state-machine)
16
16
  - [Queue a Batch job](#queue-a-batch-job)
17
17
  - [Invoke an API Gateway REST API](#invoke-an-api-gateway-rest-api)
18
+ - [Invoke an AWS API](#invoke-an-aws-api)
18
19
  - [Invoke an API Destination](#invoke-an-api-destination)
19
20
  - [Invoke an AppSync GraphQL API](#invoke-an-appsync-graphql-api)
20
21
  - [Put an event on an EventBridge bus](#put-an-event-on-an-eventbridge-bus)
@@ -333,6 +334,67 @@ declare const rule: events.Rule;
333
334
  rule.addTarget(new targets.ApiGatewayV2(httpApi));
334
335
  ```
335
336
 
337
+ ## Invoke an AWS API
338
+
339
+ Use the `AwsApi` target to make direct AWS API calls from EventBridge rules. This is useful for invoking AWS services that don't have a dedicated EventBridge target.
340
+
341
+ ### Basic Usage
342
+
343
+ The following example shows how to update an ECS service when a rule is triggered:
344
+
345
+ ```ts
346
+ const rule = new events.Rule(this, 'Rule', {
347
+ schedule: events.Schedule.rate(Duration.hours(1)),
348
+ });
349
+
350
+ rule.addTarget(new targets.AwsApi({
351
+ service: 'ECS',
352
+ action: 'updateService',
353
+ parameters: {
354
+ service: 'my-service',
355
+ forceNewDeployment: true,
356
+ },
357
+ }));
358
+ ```
359
+
360
+ ### IAM Permissions
361
+
362
+ By default, the AwsApi target automatically creates the necessary IAM permissions based on the service and action you specify. The permission format follows the pattern: `service:Action`.
363
+
364
+ For example:
365
+
366
+ - `ECS` service with `updateService` action → `ecs:UpdateService` permission
367
+ - `RDS` service with `createDBSnapshot` action → `rds:CreateDBSnapshot` permission
368
+
369
+ ### Custom IAM Policy
370
+
371
+ In some cases, you may need to provide a custom IAM policy statement, especially when:
372
+
373
+ - You need to restrict permissions to specific resources (instead of `*`)
374
+ - The service requires additional permissions beyond the main action
375
+ - You want more granular control over the permissions
376
+
377
+ ```ts
378
+ import * as iam from 'aws-cdk-lib/aws-iam';
379
+ import * as s3 from 'aws-cdk-lib/aws-s3';
380
+
381
+ declare const rule: events.Rule;
382
+ declare const bucket: s3.Bucket;
383
+
384
+ rule.addTarget(new targets.AwsApi({
385
+ service: 's3',
386
+ action: 'GetBucketEncryption',
387
+ parameters: {
388
+ Bucket: bucket.bucketName,
389
+ },
390
+ policyStatement: new iam.PolicyStatement({
391
+ effect: iam.Effect.ALLOW,
392
+ actions: ['s3:GetEncryptionConfiguration'],
393
+ resources: [bucket.bucketArn],
394
+ }),
395
+ }));
396
+ ```
397
+
336
398
  ## Invoke an API Destination
337
399
 
338
400
  Use the `targets.ApiDestination` target to trigger an external API. You need to
@@ -636,7 +698,7 @@ rule.addTarget(new targets.RedshiftQuery(workgroup.attrWorkgroupWorkgroupArn, {
636
698
 
637
699
  ## Publish to an SNS Topic
638
700
 
639
- Use the `SnsTopic` target to publish to an SNS Topic.
701
+ Use the `SnsTopic` target to publish to an SNS Topic.
640
702
 
641
703
  The code snippet below creates the scheduled event rule that publishes to an SNS Topic using a resource policy.
642
704
 
@@ -664,4 +726,4 @@ const rule = new events.Rule(this, 'Rule', {
664
726
  });
665
727
 
666
728
  rule.addTarget(new targets.SnsTopic(topic, { authorizeUsingRole: true }));
667
- ```
729
+ ```
@@ -418,6 +418,24 @@ To apply changes of the cluster, such as engine version, in the next scheduled m
418
418
 
419
419
  For details, see [Modifying an Amazon Aurora DB cluster](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Modifying.html).
420
420
 
421
+ ### Retaining Automated Backups
422
+
423
+ By default, when a database cluster is deleted, automated backups are removed immediately unless an AWS Backup policy specifies a point-in-time restore rule. You can control this behavior using the `deleteAutomatedBackups` property:
424
+
425
+ ```ts
426
+ declare const vpc: ec2.IVpc;
427
+ // Retain automated backups after cluster deletion
428
+ new rds.DatabaseCluster(this, 'Database', {
429
+ engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_01_0 }),
430
+ writer: rds.ClusterInstance.provisioned('writer'),
431
+ vpc,
432
+ deleteAutomatedBackups: false,
433
+ });
434
+ ```
435
+
436
+ When set to `false`, automated backups are retained according to the configured retention period after the cluster is deleted. When set to `true` or not specified (default), automated backups are deleted immediately when the cluster is deleted.
437
+ Detail about this feature can be found in the [AWS documentation](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Managing.Backups.Retaining.html).
438
+
421
439
  ### Migrating from instanceProps
422
440
 
423
441
  Creating instances in a `DatabaseCluster` using `instanceProps` & `instances` is
@@ -63,6 +63,7 @@ class TestStack extends cdk.Stack {
63
63
  parameterGroup: params,
64
64
  storageEncryptionKey: kmsKey,
65
65
  autoMinorVersionUpgrade: false,
66
+ deleteAutomatedBackups: false,
66
67
  });
67
68
 
68
69
  cluster.connections.allowDefaultPortFromAnyIpv4('Open to the world');
@@ -100,4 +101,3 @@ const stackWithFeatureFlag = new TestStack(appWithFeatureFlag, 'aws-cdk-rds-inte
100
101
  new IntegTest(appWithFeatureFlag, 'test-rds-cluster-with-feature-flag', {
101
102
  testCases: [stackWithFeatureFlag],
102
103
  });
103
- appWithFeatureFlag.synth();
@@ -9,7 +9,10 @@ const stack = new Stack(app, 'cdk-integ-assets-bundling-docker-opts');
9
9
  new assets.Asset(stack, 'BundledAsset', {
10
10
  path: path.join(__dirname, 'markdown-asset'), // /asset-input and working directory in the container
11
11
  bundling: {
12
- image: DockerImage.fromBuild(path.join(__dirname, 'alpine-markdown')), // Build an image
12
+ // Build an image
13
+ image: DockerImage.fromBuild(path.join(__dirname, 'alpine-markdown'), {
14
+ platform: 'linux/amd64',
15
+ }),
13
16
  command: [
14
17
  'sh', '-c', `
15
18
  markdown index.md > /asset-output/index.html
@@ -325,6 +325,24 @@ new s3deploy.BucketDeployment(this, 'DeployWithInvalidation', {
325
325
  });
326
326
  ```
327
327
 
328
+ By default, the deployment will wait for invalidation to succeed to complete. This will poll Cloudfront for a maximum of 13 minutes to check for a successful invalidation. The drawback to this is that the deployment will fail if invalidation fails or if it takes longer than 13 minutes. As a workaround, there is the option `waitForDistributionInvalidation`, which can be set to false to skip waiting for the invalidation, but this can be risky as invalidation errors will not be reported.
329
+
330
+ ```ts
331
+ import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
332
+
333
+ declare const bucket: s3.IBucket;
334
+ declare const distribution: cloudfront.IDistribution;
335
+
336
+ new s3deploy.BucketDeployment(this, 'DeployWithInvalidation', {
337
+ sources: [s3deploy.Source.asset('./website-dist')],
338
+ destinationBucket: bucket,
339
+ distribution,
340
+ distributionPaths: ['/images/*.png'],
341
+ // Invalidate cache but don't wait or verify that invalidation has completed successfully.
342
+ waitForDistributionInvalidation: false
343
+ });
344
+ ```
345
+
328
346
  ## Signed Content Payloads
329
347
 
330
348
  By default, deployment uses streaming uploads which set the `x-amz-content-sha256`
@@ -121,6 +121,7 @@ declare const fn: lambda.Function;
121
121
 
122
122
  // Lambda should receive only message matching the following conditions on message body:
123
123
  // color: 'red' or 'orange'
124
+ // store: property must not be present
124
125
  myTopic.addSubscription(new subscriptions.LambdaSubscription(fn, {
125
126
  filterPolicyWithMessageBody: {
126
127
  background: sns.FilterOrPolicy.policy({
@@ -128,6 +129,7 @@ myTopic.addSubscription(new subscriptions.LambdaSubscription(fn, {
128
129
  allowlist: ['red', 'orange'],
129
130
  })),
130
131
  }),
132
+ store: sns.FilterOrPolicy.filter(sns.SubscriptionFilter.notExistsFilter()),
131
133
  },
132
134
  }));
133
135
  ```
@@ -0,0 +1,75 @@
1
+ import * as sns from 'aws-cdk-lib/aws-sns';
2
+ import * as sqs from 'aws-cdk-lib/aws-sqs';
3
+ import * as cdk from 'aws-cdk-lib';
4
+ import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests-alpha';
5
+ import * as subs from 'aws-cdk-lib/aws-sns-subscriptions';
6
+
7
+ const app = new cdk.App();
8
+
9
+ const stack = new cdk.Stack(app, 'sns-sqs-subscription-filter');
10
+
11
+ const topic = new sns.Topic(stack, 'MyTopic');
12
+
13
+ const queue1 = new sqs.Queue(stack, 'MyQueue1');
14
+ const queue2 = new sqs.Queue(stack, 'MyQueue2');
15
+
16
+ topic.addSubscription(new subs.SqsSubscription(queue1, {
17
+ filterPolicyWithMessageBody: {
18
+ background: sns.Policy.policy({
19
+ color: sns.Filter.filter(sns.SubscriptionFilter.stringFilter({
20
+ allowlist: ['red', 'green'],
21
+ })),
22
+ }),
23
+ price: sns.Filter.filter(sns.SubscriptionFilter.numericFilter({
24
+ allowlist: [100, 200],
25
+ })),
26
+ store: sns.Filter.filter(sns.SubscriptionFilter.existsFilter()),
27
+ },
28
+ rawMessageDelivery: true,
29
+ }));
30
+
31
+ topic.addSubscription(new subs.SqsSubscription(queue2, {
32
+ filterPolicyWithMessageBody: {
33
+ background: sns.Policy.policy({
34
+ color: sns.Filter.filter(sns.SubscriptionFilter.stringFilter({
35
+ denylist: ['red', 'green'],
36
+ })),
37
+ }),
38
+ price: sns.Filter.filter(sns.SubscriptionFilter.numericFilter({
39
+ betweenStrict: { start: 100, stop: 200 },
40
+ })),
41
+ store: sns.Filter.filter(sns.SubscriptionFilter.notExistsFilter()),
42
+ },
43
+ rawMessageDelivery: true,
44
+ }));
45
+
46
+ const integTest = new IntegTest(app, 'SNS Subscription filters', {
47
+ testCases: [stack],
48
+ });
49
+
50
+ const message1 = JSON.stringify({ background: { color: 'green' }, price: 200, store: 'fans' }); // matches queue1 subscription filter
51
+ const message2 = JSON.stringify({ background: { color: 'blue' }, price: 150 }); // matches queue2 subscription filter
52
+
53
+ // publish messages to SNS topic
54
+ integTest.assertions.awsApiCall('SNS', 'publish', {
55
+ Message: message1,
56
+ TopicArn: topic.topicArn,
57
+ });
58
+ integTest.assertions.awsApiCall('SNS', 'publish', {
59
+ Message: message2,
60
+ TopicArn: topic.topicArn,
61
+ });
62
+
63
+ // check messages arrived at expected destination queue
64
+ integTest.assertions.awsApiCall('SQS', 'receiveMessage', {
65
+ QueueUrl: queue1.queueUrl,
66
+ WaitTimeSeconds: 20,
67
+ }).expect(ExpectedResult.objectLike({
68
+ Messages: [{ Body: message1 }],
69
+ }));
70
+ integTest.assertions.awsApiCall('SQS', 'receiveMessage', {
71
+ QueueUrl: queue2.queueUrl,
72
+ WaitTimeSeconds: 20,
73
+ }).expect(ExpectedResult.objectLike({
74
+ Messages: [{ Body: message2 }],
75
+ }));
@@ -3,50 +3,31 @@ import * as sqs from 'aws-cdk-lib/aws-sqs';
3
3
  import * as cdk from 'aws-cdk-lib';
4
4
  import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests-alpha';
5
5
  import * as subs from 'aws-cdk-lib/aws-sns-subscriptions';
6
- class SnsToSqsStack extends cdk.Stack {
7
- topic: sns.Topic;
8
- queue: sqs.Queue;
9
- constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
10
- super(scope, id, props);
11
- this.topic = new sns.Topic(this, 'MyTopic');
12
- const queueStack = new cdk.Stack(app, 'QueueStack');
13
- this.queue = new sqs.Queue(queueStack, 'MyQueue');
14
- this.topic.addSubscription(new subs.SqsSubscription(this.queue, {
15
- filterPolicyWithMessageBody: {
16
- background: sns.Policy.policy({
17
- color: sns.Filter.filter(sns.SubscriptionFilter.stringFilter({
18
- allowlist: ['red', 'green'],
19
- denylist: ['white', 'orange'],
20
- })),
21
- }),
22
- price: sns.Filter.filter(sns.SubscriptionFilter.numericFilter({
23
- allowlist: [100, 200],
24
- between: { start: 300, stop: 350 },
25
- greaterThan: 500,
26
- lessThan: 1000,
27
- betweenStrict: { start: 2000, stop: 3000 },
28
- })),
29
- },
30
- }));
31
- }
32
- }
33
- // Beginning of the test suite
6
+
34
7
  const app = new cdk.App();
35
- const stack = new SnsToSqsStack(app, 'SnsToSqsStack');
8
+
9
+ const stack = new cdk.Stack(app, 'SnsToSqsStack');
10
+
11
+ const topic = new sns.Topic(stack, 'MyTopic');
12
+
13
+ const queue = new sqs.Queue(stack, 'MyQueue');
14
+
15
+ topic.addSubscription(new subs.SqsSubscription(queue, { rawMessageDelivery: true }));
16
+
36
17
  const integTest = new IntegTest(app, 'SNS Subscriptions', {
37
- testCases: [
38
- stack,
39
- ],
18
+ testCases: [stack],
40
19
  });
20
+
21
+ const message = JSON.stringify({ color: 'green', price: 200 });
22
+
41
23
  integTest.assertions.awsApiCall('SNS', 'publish', {
42
- Message: '{ background: { color: \'green\' }, price: 200 }',
43
- TopicArn: stack.topic.topicArn,
24
+ Message: message,
25
+ TopicArn: topic.topicArn,
44
26
  });
45
- const message = integTest.assertions.awsApiCall('SQS', 'receiveMessage', {
46
- QueueUrl: stack.queue.queueUrl,
27
+
28
+ integTest.assertions.awsApiCall('SQS', 'receiveMessage', {
29
+ QueueUrl: queue.queueUrl,
47
30
  WaitTimeSeconds: 20,
48
- });
49
- message.expect(ExpectedResult.objectLike({
50
- Messages: [{ Body: '{color: "green", price: 200}' }],
31
+ }).expect(ExpectedResult.objectLike({
32
+ Messages: [{ Body: message }],
51
33
  }));
52
- app.synth();
@@ -0,0 +1,27 @@
1
+ import { App, Stack, StackProps } from 'aws-cdk-lib';
2
+ import * as integ from '@aws-cdk/integ-tests-alpha';
3
+ import { Construct } from 'constructs';
4
+ import * as sfn from 'aws-cdk-lib/aws-stepfunctions';
5
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
6
+ import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks';
7
+
8
+ class TestStack extends Stack {
9
+ constructor(scope: Construct, id: string, props?: StackProps) {
10
+ super(scope, id, props);
11
+
12
+ const task = new tasks.EvaluateExpression(this, 'Task', {
13
+ expression: '$.a + $.b',
14
+ runtime: lambda.Runtime.NODEJS_22_X,
15
+ });
16
+
17
+ new sfn.StateMachine(this, 'StateMachine', {
18
+ definition: task,
19
+ });
20
+ }
21
+ }
22
+
23
+ const app = new App();
24
+
25
+ new integ.IntegTest(app, 'EvaluateExpressionNodejs22', {
26
+ testCases: [new TestStack(app, 'evaluate-expression-nodejs22')],
27
+ });