diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d7e89f3d..09cecc0a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.45.0](https://github.com/awslabs/aws-solutions-constructs/compare/v2.44.0...v2.45.0) (2023-10-14) + +Built on CDK v2.99.1 +Significant internal clean up chores + +### Bug Fixes + +* **all:** typos ([#1010](https://github.com/awslabs/aws-solutions-constructs/issues/1010)) ([0787baf](https://github.com/awslabs/aws-solutions-constructs/commit/0787baf7c68f84599139e5b886d5942b076174f2)) + ## [2.44.0](https://github.com/awslabs/aws-solutions-constructs/compare/v2.43.0...v2.44.0) (2023-08-29) Built on CDK v2.82.0 (no new features, just internal housekeeping) @@ -319,7 +328,7 @@ This is one of a number of identical releases we have created as we overhaul our ### Features -* Includes all funcionality of V1.137.0 +* Includes all functionality of V1.137.0 * Build upon underlying CDK version V2.4.0 * **aws-alb-fargate:** New Construct ([#560](https://github.com/awslabs/aws-solutions-constructs/issues/560)) ([5a21b76](https://github.com/awslabs/aws-solutions-constructs/commit/5a21b7652be0be2c77957155a504a9582830eeba)) @@ -333,7 +342,7 @@ This is one of a number of identical releases we have created as we overhaul our ## [2.0.0](https://github.com/awslabs/aws-solutions-constructs/compare/v2.0.0-rc.2...v2.0.0) (2021-12-02) -* Includes all funcionality of V1.129.0 +* Includes all functionality of V1.129.0 ### Features @@ -369,7 +378,7 @@ This is one of a number of identical releases we have created as we overhaul our * **apigateway-helper:** fixed condition for cloudWatchRole creation ([#468](https://github.com/awslabs/aws-solutions-constructs/issues/468)) ([e454349](https://github.com/awslabs/aws-solutions-constructs/commit/e45434928a17cde580698a82ee53f6ee7463c6cf)) * **scripts:** Fix postinstall script ([#477](https://github.com/awslabs/aws-solutions-constructs/issues/477)) ([3902a91](https://github.com/awslabs/aws-solutions-constructs/commit/3902a912547b2e7645ad352feec9811d88678543)) * **service-staff:** Fix create-order lambda ([#479](https://github.com/awslabs/aws-solutions-constructs/issues/479)) ([982c026](https://github.com/awslabs/aws-solutions-constructs/commit/982c02619d0bb4a5f9fd1433f60b74ef89a1603c)) -* **Set outputBucket property on aws-kinesisstreams-gluejob:** Issue [#448](https://github.com/awslabs/aws-solutions-constructs/issues/448) to include S3 bucket for Glue Job that the consturct creates ([#452](https://github.com/awslabs/aws-solutions-constructs/issues/452)) ([c40e1f7](https://github.com/awslabs/aws-solutions-constructs/commit/c40e1f7c3524652ac8e3277b1c482975e6df9e36)) +* **Set outputBucket property on aws-kinesisstreams-gluejob:** Issue [#448](https://github.com/awslabs/aws-solutions-constructs/issues/448) to include S3 bucket for Glue Job that the construct creates ([#452](https://github.com/awslabs/aws-solutions-constructs/issues/452)) ([c40e1f7](https://github.com/awslabs/aws-solutions-constructs/commit/c40e1f7c3524652ac8e3277b1c482975e6df9e36)) ## 2.0.0-rc.1 (2021-10-12) @@ -422,4 +431,4 @@ This is the first release candidate of Solutions Constructs 2.0 based on CDK v2. - aws-sns-sqs - aws-sqs-lambda - aws-wafwebacl-apigateway -- aws-wafwebacl-cloudfront \ No newline at end of file +- aws-wafwebacl-cloudfront diff --git a/CHANGELOG.v1.md b/CHANGELOG.v1.md index f7fde29ee..6f4dc876b 100644 --- a/CHANGELOG.v1.md +++ b/CHANGELOG.v1.md @@ -261,7 +261,7 @@ All notable changes to this project will be documented in this file. See [standa ### Bug Fixes * **apigateway-helper:** fixed condition for cloudWatchRole creation ([#468](https://github.com/awslabs/aws-solutions-constructs/issues/468)) ([e454349](https://github.com/awslabs/aws-solutions-constructs/commit/e45434928a17cde580698a82ee53f6ee7463c6cf)) -* **Set outputBucket property on aws-kinesisstreams-gluejob:** Issue [#448](https://github.com/awslabs/aws-solutions-constructs/issues/448) to include S3 bucket for Glue Job that the consturct creates ([#452](https://github.com/awslabs/aws-solutions-constructs/issues/452)) ([c40e1f7](https://github.com/awslabs/aws-solutions-constructs/commit/c40e1f7c3524652ac8e3277b1c482975e6df9e36)) +* **Set outputBucket property on aws-kinesisstreams-gluejob:** Issue [#448](https://github.com/awslabs/aws-solutions-constructs/issues/448) to include S3 bucket for Glue Job that the construct creates ([#452](https://github.com/awslabs/aws-solutions-constructs/issues/452)) ([c40e1f7](https://github.com/awslabs/aws-solutions-constructs/commit/c40e1f7c3524652ac8e3277b1c482975e6df9e36)) ## [1.125.0](https://github.com/awslabs/aws-solutions-constructs/compare/v1.124.0...v1.125.0) (2021-10-08) @@ -515,7 +515,7 @@ All notable changes to this project will be documented in this file. See [standa ### Changed * Upgraded all patterns to CDK v1.105.0 -* aws-s3-step-function now triggers for Mulitpart uploads and Copy Object [#198](https://github.com/awslabs/aws-solutions-constructs/pull/198) +* aws-s3-step-function now triggers for Multipart uploads and Copy Object [#198](https://github.com/awslabs/aws-solutions-constructs/pull/198) * Change S3 protocol in glue to use s3a:// [#197](https://github.com/awslabs/aws-solutions-constructs/pull/197) * Change policy name in for glue so multiple constructs can be included in a single stack [#197](https://github.com/awslabs/aws-solutions-constructs/pull/197) @@ -579,14 +579,14 @@ All notable changes to this project will be documented in this file. See [standa ### Changed - Upgraded all patterns to CDK v1.97.0 -- Made changes to accomodate cfn_nag rule W92 +- Made changes to accommodate cfn_nag rule W92 - Updated integration tests to destroy S3 buckets when tearing down the test stack ## 1.96.0 (2021-04-07) ### Changed - Upgraded all patterns to CDK v1.96.0 -- Made changes to accomodate cfn_nag rules W89 and W90 +- Made changes to accommodate cfn_nag rules W89 and W90 ## 1.95.2 (2021-04-03) @@ -745,7 +745,7 @@ All notable changes to this project will be documented in this file. See [standa ### Changed - Upgraded all patterns to CDK v1.76.0 -- Added ESLint rule to enfore 2 space indentation +- Added ESLint rule to enforce 2 space indentation - Updated `aws-lambda-sqs` to support for VPC ## 1.75.0 (2020-12-03) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 09f16ad94..2c8ba3d82 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,7 +81,7 @@ Now it's time to work your magic. Here are some guidelines: it might be easier to get started that way. * To ensure CDKv2 compatibility of all the Solutions Constructs, please ensure the code meets the following guidelines: * Import statement for `Construct` is standalone, for example, `import { Construct } from '@aws-cdk/core';` instead of `import { Construct, App, Aws } from '@aws-cdk/core';` - * Check to make sure the usage of `Construct` in the code is also standalone, for example, `export class IotToSqs extends Construct` insted of `export class IotToSqs extends cdk.Construct` + * Check to make sure the usage of `Construct` in the code is also standalone, for example, `export class IotToSqs extends Construct` instead of `export class IotToSqs extends cdk.Construct` * Core classes are imported from `@aws-cdk/core` only, for example, `import { Duration } from "@aws-cdk/core;` instead of `import { Duration } from "@aws-cdk/core/lib/duration";` * DO NOT USE deprecated APIs, it will not build in CDKv2, for example, using `statistic?` attribute of [@aws-cdk/aws-cloudwatch.Alarm](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.Alarm.html) Construct Props will fail to build in CDKv2 * DO NOT USE experimental modules, it will not build in CDKv2, for example, avoid using L2 constructs for [HTTP or Websocket API](https://docs.aws.amazon.com/cdk/api/latest/docs/aws-apigatewayv2-readme.html) will fail to build in CDKv2 @@ -135,7 +135,7 @@ Each integration test generates a .expected.json file by actually deploying the The standard `npm run build+lint+test` command will compare the cdk synth output against the .expected.json file. The Solutions Constructs team will run `npm run integ` in each construct periodically to guard against drift and ensure each construct still deploys. -NOTE: Running `npm run integ` will launch a stack including the construct for each integration test. It will also delete the stack after collecting the CloudFormation template. While the stack will only be around for a few seconds, during this time you account will be billed for the resoruces. Some tests may leave behind an S3 bucket - you should check after running this step. Ideally, +NOTE: Running `npm run integ` will launch a stack including the construct for each integration test. It will also delete the stack after collecting the CloudFormation template. While the stack will only be around for a few seconds, during this time you account will be billed for the resources. Some tests may leave behind an S3 bucket - you should check after running this step. Ideally, ### Step 4: Commit diff --git a/DESIGN_GUIDELINES.md b/DESIGN_GUIDELINES.md index f1052c964..a7cf6f699 100644 --- a/DESIGN_GUIDELINES.md +++ b/DESIGN_GUIDELINES.md @@ -184,7 +184,7 @@ Existing Inconsistencies would not be published, that’s for our internal use | Name | Type | Description | Notes | | --- | --- | --- | --- | -| eventsRule | [`events.Rule`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_events.Rule.html)|Returns an instance of `events.Rule` created by the construct. Only exposed when EventBridge is the soure of events, not exposed when other services (Lambda, Fargate) are triggering events. | +| eventsRule | [`events.Rule`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_events.Rule.html)|Returns an instance of `events.Rule` created by the construct. Only exposed when EventBridge is the source of events, not exposed when other services (Lambda, Fargate) are triggering events. | | eventBus? | [`events.IEventBus`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_events.IEventBus.html)|Returns the instance of `events.IEventBus` used by the construct| Required only for non-default Event Buses.| ## Fargate @@ -369,7 +369,7 @@ Existing Inconsistencies would not be published, that’s for our internal use | --- | --- | --- |--- | | existingVpc? | [`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An existing VPC in which to deploy the construct. Providing both this and `vpcProps` is an error.| | deployVpc? |`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| -| vpcProps? |[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the Construct, so any values for those properties supplied here will be overrriden. If `deployVpc?` is not `true` then this property will be ignored. | +| vpcProps? |[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the Construct, so any values for those properties supplied here will be overridden. If `deployVpc?` is not `true` then this property will be ignored. | **Required Construct Properties** diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 57b8e47a9..f67c2852f 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -2,7 +2,7 @@ Solutions Constructs are built in typescript in a rather complex build environment. This is to support all the associated testing, code checking and compilation for Java, Python and .NET client. So that you don't have to recreate the entire toolset on your workstation, all building is done on a publicly available docker container. Using this container has both advantages and drawbacks. This document isn't going to pass judgment on these tradeoffs, it's just going to teach you how to build constructs. -Install Docker on your workstation. We're not going to go into detail on how to do this, you probably already have it installed. If not, you can get it [here](https://docs.docker.com/get-docker/). We strongly recommend you increase the amount of system resources dedicated to a docker container prior to starting the build - this can make the difference between the build taking several hours and the build taking 45 minutes. You can adjust these in the Resources tab under the Settings page on the Docker Dahsboard. A good starting point where we have had success is: +Install Docker on your workstation. We're not going to go into detail on how to do this, you probably already have it installed. If not, you can get it [here](https://docs.docker.com/get-docker/). We strongly recommend you increase the amount of system resources dedicated to a docker container prior to starting the build - this can make the difference between the build taking several hours and the build taking 45 minutes. You can adjust these in the Resources tab under the Settings page on the Docker Dashboard. A good starting point where we have had success is: CPUs: 6 Memory: 8 GB @@ -24,7 +24,7 @@ Disk image size: 60 GB ## Working on Your Construct -The build-patterns.sh script sets everything up to build constructs, builds everything, then resets all the settings back where it started. What kind of settings? For instance - you may have noticed that the version numbers in package.json are 0.0.0 for all CDK and construct references. build-patterns.sh runs a script (align-version.sh) that sets all version numbers to the current version of the Solutions Constructs library. After the build it runs the script again (`align-version.sh revert`) to set the version numbers back to 0.0.0 so the code is back in sync with the repo. The steps below perform the first part of build-patterns.sh so you can compile an indivdual folder, such as a single construct or /core. We call building a single construct rather than the whole library a partial build. +The build-patterns.sh script sets everything up to build constructs, builds everything, then resets all the settings back where it started. What kind of settings? For instance - you may have noticed that the version numbers in package.json are 0.0.0 for all CDK and construct references. build-patterns.sh runs a script (align-version.sh) that sets all version numbers to the current version of the Solutions Constructs library. After the build it runs the script again (`align-version.sh revert`) to set the version numbers back to 0.0.0 so the code is back in sync with the repo. The steps below perform the first part of build-patterns.sh so you can compile an individual folder, such as a single construct or /core. We call building a single construct rather than the whole library a partial build. | Action | Explanation | | :------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/deployment/build-cdk-dist.sh b/deployment/build-cdk-dist.sh index 9a2ad875e..b5789c55b 100755 --- a/deployment/build-cdk-dist.sh +++ b/deployment/build-cdk-dist.sh @@ -36,7 +36,7 @@ for subdir in $source_dir/patterns/\@aws-solutions-constructs/* ; do then if [ "$cnt" -eq "0" ] then - echo "************** [ERROR] ************* Did not find any integ CFN templates in $subdir; please add atleast one by writing an integ test case and running cdk-integ command to generate the CFN template for it" + echo "************** [ERROR] ************* Did not find any integ CFN templates in $subdir; please add at least one by writing an integ test case and running cdk-integ command to generate the CFN template for it" exit 1 fi fi diff --git a/deployment/v2/align-version.js b/deployment/v2/align-version.js index 09d2f8e82..7650ba383 100755 --- a/deployment/v2/align-version.js +++ b/deployment/v2/align-version.js @@ -10,7 +10,7 @@ const findVersion = process.argv[2]; const replaceVersion = process.argv[3]; // these versions need to be sourced from a config file -const awsCdkLibVersion = '2.82.0'; +const awsCdkLibVersion = '2.99.1'; const constructsVersion = '10.0.0'; const MODULE_EXEMPTIONS = new Set([ '@aws-cdk/cloudformation-diff', diff --git a/deployment/v2/build-cdk-dist.sh b/deployment/v2/build-cdk-dist.sh index 43d08f849..cd6790415 100755 --- a/deployment/v2/build-cdk-dist.sh +++ b/deployment/v2/build-cdk-dist.sh @@ -29,7 +29,7 @@ for subdir in $source_dir/patterns/\@aws-solutions-constructs/* ; do then if [ "$cnt" -eq "0" ] then - echo "************** [ERROR] ************* Did not find any integ CFN templates in $subdir; please add atleast one by writing an integ test case and running cdk-integ command to generate the CFN template for it" + echo "************** [ERROR] ************* Did not find any integ CFN templates in $subdir; please add at least one by writing an integ test case and running cdk-integ command to generate the CFN template for it" exit 1 fi fi diff --git a/deployment/v2/build-patterns.sh b/deployment/v2/build-patterns.sh index 3e35cb875..ca3b2e65d 100755 --- a/deployment/v2/build-patterns.sh +++ b/deployment/v2/build-patterns.sh @@ -12,7 +12,7 @@ bail="--bail" runtarget="build+lint+test" cd $source_dir/ -export PATH=$(npm bin):$PATH +export PATH=$source_dir/node_modules/.bin:$PATH export NODE_OPTIONS="--max-old-space-size=4096 ${NODE_OPTIONS:-}" echo "=============================================================================================" diff --git a/sonar-project.properties b/sonar-project.properties index 63bdcdbdb..f6b2fc410 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -69,6 +69,7 @@ sonar.javascript.lcov.reportPaths= \ source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/coverage/lcov.info, \ + source/patterns/@aws-solutions-constructs/aws-lambda-kendra/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/coverage/lcov.info, \ @@ -80,6 +81,7 @@ sonar.javascript.lcov.reportPaths= \ source/patterns/@aws-solutions-constructs/aws-lambda-sqs/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/coverage/lcov.info, \ + source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-route53-alb/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-route53-apigateway/coverage/lcov.info, \ source/patterns/@aws-solutions-constructs/aws-s3-lambda/coverage/lcov.info, \ diff --git a/source/lerna.json b/source/lerna.json index d345e11d4..189481e63 100644 --- a/source/lerna.json +++ b/source/lerna.json @@ -6,5 +6,5 @@ "./patterns/@aws-solutions-constructs/*" ], "rejectCycles": "true", - "version": "2.44.0" + "version": "2.45.0" } diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/README.md b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/README.md index 012837493..5a6ee8d5c 100755 --- a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/README.md @@ -140,7 +140,7 @@ new AlbToFargate(this, "AlbToFargatePattern", new AlbToFargateProps.Builder() | containerDefinitionProps? | [ecs.ContainerDefinitionProps \| any](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerDefinitionProps.html) | Optional props to define the container created for the Fargate Service (defaults found in fargate-defaults.ts) | | fargateTaskDefinitionProps? | [ecs.FargateTaskDefinitionProps \| any](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.FargateTaskDefinitionProps.html) | Optional props to define the Fargate Task Definition for this construct (defaults found in fargate-defaults.ts) | | fargateServiceProps? | [ecs.FargateServiceProps \| any](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.FargateServiceProps.html) | Optional properties to override default values for the Fargate service. Service will set up in the Public or Isolated subnets of the VPC by default, override that (e.g. - choose Private subnets) by setting vpcSubnets on this object. | -| existingFargateServiceObject? | [ecs.FargateService](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.FargateService.html) | A Fargate Service already instantiated (probably by another Solutions Construct). If this is specified, then no props defining a new service can be provided, including: existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface | +| existingFargateServiceObject? | [ecs.FargateService](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.FargateService.html) | A Fargate Service already instantiated (probably by another Solutions Construct). If this is specified, then no props defining a new service can be provided, including: existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface | | existingContainerDefinitionObject? | [ecs.ContainerDefinition](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerDefinition.html) | A container definition already instantiated as part of a Fargate service. This must be the container in the existingFargateServiceObject | ## Pattern Properties diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/lib/index.ts index bee06a834..3b4821b7d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/lib/index.ts @@ -140,7 +140,7 @@ export interface AlbToFargateProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface * * @default - none @@ -164,9 +164,9 @@ export class AlbToFargate extends Construct { constructor(scope: Construct, id: string, props: AlbToFargateProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckAlbProps(props); defaults.CheckFargateProps(props); + defaults.CheckVpcProps(props); // Obtain VPC for construct (existing or created) this.vpc = defaults.buildVpc(scope, { diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/alb-fargate.test.ts b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/alb-fargate.test.ts index cedb5437f..3bd238d69 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/alb-fargate.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/alb-fargate.test.ts @@ -463,3 +463,59 @@ test('Test HTTPS API with new vpc, load balancer, service and private API', () = ] }); }); + +test('Confirm that CheckVpcProps is called', () => { + const stack = new cdk.Stack(undefined, undefined, { + env: { account: "123456789012", region: 'us-east-1' }, + }); + + const props: AlbToFargateProps = { + ecrRepositoryArn: defaults.fakeEcrRepoArn, + listenerProps: { + certificates: [defaults.getFakeCertificate(stack, "fake-cert")] + }, + publicApi: false, + vpcProps: {}, + existingVpc: defaults.getTestVpc(stack), + }; + const app = () => { + new AlbToFargate(stack, 'new-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm that CheckAlbProps is called', () => { + const stack = new cdk.Stack(undefined, undefined, { + env: { account: "123456789012", region: 'us-east-1' }, + }); + const testName = 'test-value'; + + const existingVpc = defaults.getTestVpc(stack); + + const existingAlb = new elb.ApplicationLoadBalancer(stack, 'test-alb', { + vpc: existingVpc, + internetFacing: true, + loadBalancerName: testName, + }); + + const props: AlbToFargateProps = { + existingVpc, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + listenerProps: { + certificates: [defaults.getFakeCertificate(stack, "fake-cert")] + }, + publicApi: false, + vpcProps: {}, + loadBalancerProps: { + loadBalancerName: 'new-loadbalancer', + internetFacing: true, + }, + existingLoadBalancerObj: existingAlb, + }; + const app = () => { + new AlbToFargate(stack, 'new-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide loadBalancerProps or existingLoadBalancerObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-existing-private-http.expected.json b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-existing-private-http.expected.json index f552779d8..db34b0132 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-existing-private-http.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-existing-private-http.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "all-existing-private-http/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-existing-private-http/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "all-existing-private-http/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-existing-private-http/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "all-existing-private-http/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-existing-private-http/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "all-existing-private-http/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-existing-private-http/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "all-existing-private-http/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-existing-private-http/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "all-existing-private-http/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-existing-private-http/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "all-existing-private-http/Vpc" + "Value": "all-existing-private-http/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "all-existing-private-http/Vpc" + "Value": "all-existing-private-http/Vpc/FlowLog" } ] }, @@ -647,10 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -661,10 +657,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "all-existing-private-http/Vpc" + "Value": "all-existing-private-http/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -673,10 +673,6 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,7 +753,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "allexistingprivatehttpECRAPIsecuritygroupD77FBBD5": { @@ -972,7 +972,6 @@ "testsgfromallexistingprivatehttptestalbSecurityGroup4B36914B80803EB3A82F": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { - "IpProtocol": "tcp", "Description": "Load balancer to target", "FromPort": 8080, "GroupId": { @@ -981,6 +980,7 @@ "GroupId" ] }, + "IpProtocol": "tcp", "SourceSecurityGroupId": { "Fn::GetAtt": [ "testalbSecurityGroup0C84CDF9", @@ -997,6 +997,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1043,7 +1048,8 @@ } }, "DependsOn": [ - "testconstructtestconstructlistener484444F1" + "testconstructtestconstructlistener484444F1", + "testtaskdefTaskRoleB2DEF113" ] }, "testalb9AFCD824": { @@ -1135,13 +1141,6 @@ "testalbSecurityGrouptoallexistingprivatehttptestsgC280D41D8080C6A2C196": { "Type": "AWS::EC2::SecurityGroupEgress", "Properties": { - "GroupId": { - "Fn::GetAtt": [ - "testalbSecurityGroup0C84CDF9", - "GroupId" - ] - }, - "IpProtocol": "tcp", "Description": "Load balancer to target", "DestinationSecurityGroupId": { "Fn::GetAtt": [ @@ -1150,6 +1149,13 @@ ] }, "FromPort": 8080, + "GroupId": { + "Fn::GetAtt": [ + "testalbSecurityGroup0C84CDF9", + "GroupId" + ] + }, + "IpProtocol": "tcp", "ToPort": 8080 } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-new-public-http.expected.json b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-new-public-http.expected.json index 8140221e1..5f1ba0d9d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-new-public-http.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-new-public-http.expected.json @@ -50,9 +50,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -69,7 +66,10 @@ "Key": "Name", "Value": "all-new-public-http/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -85,15 +85,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-public-http/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -110,12 +110,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -137,15 +137,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -161,9 +161,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -180,7 +177,10 @@ "Key": "Name", "Value": "all-new-public-http/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -196,15 +196,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-public-http/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -221,12 +221,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -248,15 +248,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -272,9 +272,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -291,7 +288,10 @@ "Key": "Name", "Value": "all-new-public-http/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -307,15 +307,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-public-http/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -332,12 +332,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -359,15 +359,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -383,9 +383,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -402,21 +399,24 @@ "Key": "Name", "Value": "all-new-public-http/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-public-http/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -433,21 +433,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -464,21 +461,24 @@ "Key": "Name", "Value": "all-new-public-http/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-public-http/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -495,21 +495,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -526,21 +523,24 @@ "Key": "Name", "Value": "all-new-public-http/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-public-http/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -557,12 +557,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -580,11 +580,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -606,7 +606,7 @@ "Tags": [ { "Key": "Name", - "Value": "all-new-public-http/Vpc" + "Value": "all-new-public-http/Vpc/FlowLog" } ] } @@ -658,7 +658,7 @@ "Tags": [ { "Key": "Name", - "Value": "all-new-public-http/Vpc" + "Value": "all-new-public-http/Vpc/FlowLog" } ] }, @@ -678,10 +678,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -692,10 +688,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "all-new-public-http/Vpc" + "Value": "all-new-public-http/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -704,10 +704,6 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -717,6 +713,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -728,16 +725,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -747,6 +743,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -758,27 +755,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -799,7 +784,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testconstructlbalb33E0EB59": { @@ -903,13 +903,6 @@ "testconstructlbalbSecurityGrouptoallnewpublichttptestconstructsgEFBACDED8080226DB910": { "Type": "AWS::EC2::SecurityGroupEgress", "Properties": { - "GroupId": { - "Fn::GetAtt": [ - "testconstructlbalbSecurityGroup5F187AF4", - "GroupId" - ] - }, - "IpProtocol": "tcp", "Description": "Load balancer to target", "DestinationSecurityGroupId": { "Fn::GetAtt": [ @@ -918,6 +911,13 @@ ] }, "FromPort": 8080, + "GroupId": { + "Fn::GetAtt": [ + "testconstructlbalbSecurityGroup5F187AF4", + "GroupId" + ] + }, + "IpProtocol": "tcp", "ToPort": 8080 }, "DependsOn": [ @@ -1179,18 +1179,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "40aa87cdf43c4095cec18bc443965f22ab2f8c1ace47e482a0ba4e35d83b0cc9.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -1427,7 +1427,6 @@ "testconstructsgfromallnewpublichttptestconstructlbalbSecurityGroupA1A7ABDB8080D3FFEE20": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { - "IpProtocol": "tcp", "Description": "Load balancer to target", "FromPort": 8080, "GroupId": { @@ -1436,6 +1435,7 @@ "GroupId" ] }, + "IpProtocol": "tcp", "SourceSecurityGroupId": { "Fn::GetAtt": [ "testconstructlbalbSecurityGroup5F187AF4", @@ -1452,6 +1452,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1498,6 +1503,7 @@ } }, "DependsOn": [ + "testconstructtaskdefTaskRoleC60414C4", "testconstructtestconstructlistener484444F1" ] }, diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-new-two-targets.expected.json b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-new-two-targets.expected.json index 49d5ae829..8a08f7628 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-new-two-targets.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-alb-fargate/test/integ.all-new-two-targets.expected.json @@ -53,10 +53,10 @@ } } ], - "Priority": 10, "ListenerArn": { "Ref": "testconstructtestconstructlistener484444F1" - } + }, + "Priority": 10 } }, "Vpc8378EB38": { @@ -77,9 +77,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -96,7 +93,10 @@ "Key": "Name", "Value": "all-new-two-targets/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -112,15 +112,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-two-targets/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -137,12 +137,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -164,15 +164,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -188,9 +188,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -207,7 +204,10 @@ "Key": "Name", "Value": "all-new-two-targets/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -223,15 +223,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-two-targets/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -248,12 +248,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -275,15 +275,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -299,9 +299,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -318,7 +315,10 @@ "Key": "Name", "Value": "all-new-two-targets/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -334,15 +334,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-two-targets/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -359,12 +359,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -386,15 +386,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -410,9 +410,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -429,21 +426,24 @@ "Key": "Name", "Value": "all-new-two-targets/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-two-targets/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -460,21 +460,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -491,21 +488,24 @@ "Key": "Name", "Value": "all-new-two-targets/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-two-targets/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -522,21 +522,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -553,21 +550,24 @@ "Key": "Name", "Value": "all-new-two-targets/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "all-new-two-targets/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -584,12 +584,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -607,11 +607,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -633,7 +633,7 @@ "Tags": [ { "Key": "Name", - "Value": "all-new-two-targets/Vpc" + "Value": "all-new-two-targets/Vpc/FlowLog" } ] } @@ -685,7 +685,7 @@ "Tags": [ { "Key": "Name", - "Value": "all-new-two-targets/Vpc" + "Value": "all-new-two-targets/Vpc/FlowLog" } ] }, @@ -705,10 +705,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -719,10 +715,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "all-new-two-targets/Vpc" + "Value": "all-new-two-targets/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -731,10 +731,6 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -744,6 +740,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -755,16 +752,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -774,6 +770,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -785,27 +782,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -826,7 +811,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testconstructlbalb33E0EB59": { @@ -930,13 +930,6 @@ "testconstructlbalbSecurityGrouptoallnewtwotargetstestconstructsgCB4347D58080785349CD": { "Type": "AWS::EC2::SecurityGroupEgress", "Properties": { - "GroupId": { - "Fn::GetAtt": [ - "testconstructlbalbSecurityGroup5F187AF4", - "GroupId" - ] - }, - "IpProtocol": "tcp", "Description": "Load balancer to target", "DestinationSecurityGroupId": { "Fn::GetAtt": [ @@ -945,6 +938,13 @@ ] }, "FromPort": 8080, + "GroupId": { + "Fn::GetAtt": [ + "testconstructlbalbSecurityGroup5F187AF4", + "GroupId" + ] + }, + "IpProtocol": "tcp", "ToPort": 8080 }, "DependsOn": [ @@ -1206,18 +1206,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "40aa87cdf43c4095cec18bc443965f22ab2f8c1ace47e482a0ba4e35d83b0cc9.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -1454,7 +1454,6 @@ "testconstructsgfromallnewtwotargetstestconstructlbalbSecurityGroup7AE13AD9808027E2CC4F": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { - "IpProtocol": "tcp", "Description": "Load balancer to target", "FromPort": 8080, "GroupId": { @@ -1463,6 +1462,7 @@ "GroupId" ] }, + "IpProtocol": "tcp", "SourceSecurityGroupId": { "Fn::GetAtt": [ "testconstructlbalbSecurityGroup5F187AF4", @@ -1479,6 +1479,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1532,6 +1537,7 @@ } }, "DependsOn": [ + "testconstructtaskdefTaskRoleC60414C4", "testconstructtestconstructlistenerallnewtwotargetstargetsRule897FD7B6", "testconstructtestconstructlistener484444F1" ] diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/lib/index.ts index 147becab9..2dc1315fe 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/lib/index.ts @@ -121,8 +121,9 @@ export class AlbToLambda extends Construct { constructor(scope: Construct, id: string, props: AlbToLambdaProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckAlbProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); // Obtain VPC for construct (existing or created) this.vpc = defaults.buildVpc(scope, { @@ -145,7 +146,7 @@ export class AlbToLambda extends Construct { this.lambdaFunction = defaults.buildLambdaFunction(this, { existingLambdaObj: props.existingLambdaObj, lambdaFunctionProps: props.lambdaFunctionProps, - vpc: this.vpc, + vpc: this.vpc }); let newListener: boolean; @@ -157,12 +158,7 @@ export class AlbToLambda extends Construct { // If there's no listener, then we add one here if (newListener) { - this.listener = defaults.AddListener( - this, - id, - this.loadBalancer, - props.listenerProps - ); + this.listener = defaults.AddListener(this, id, this.loadBalancer, props.listenerProps); } else { this.listener = GetActiveListener(this.loadBalancer.listeners); } @@ -177,13 +173,12 @@ export class AlbToLambda extends Construct { // this.listener needs to be set on the construct. // could be above: else { defaults.GetActiveListener } - // do we then move that funcionality back into the construct (not the function). If so do + // do we then move that functionality back into the construct (not the function). If so do // we leave it in AddNewTarget or just do it here and pass the listener? if (newListener && this.listener) { const levelOneListener = this.listener.node.defaultChild as CfnListener; const cfnTargetGroup = newTargetGroup.node.defaultChild as CfnTargetGroup; levelOneListener.addDependency(cfnTargetGroup); } - } } diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/alb-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/alb-lambda.test.ts index 6e8f60539..366e532e6 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/alb-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/alb-lambda.test.ts @@ -247,7 +247,7 @@ test("Test existing load balancer and existing lambda function", () => { existingLambdaObj: lambdaFunction, existingLoadBalancerObj: existingAlb, listenerProps: { - certificates: [ defaults.getFakeCertificate(stack, "fake-cert") ], + certificates: [defaults.getFakeCertificate(stack, "fake-cert")], }, publicApi: true, existingVpc: testExistingVpc, @@ -289,7 +289,7 @@ test('Test new load balancer and new lambda function', () => { }); const props: AlbToLambdaProps = { - lambdaFunctionProps: { + lambdaFunctionProps: { code: lambda.Code.fromAsset(`${__dirname}/lambda`), runtime: lambda.Runtime.NODEJS_16_X, handler: 'index.handler', @@ -952,3 +952,101 @@ test('Test existingLoadBalancerObj and no existingVpc is an error', () => { expect(app).toThrowError( /An existing ALB is already in a VPC, that VPC must be provided in props.existingVpc for the rest of the construct to use./); }); + +test('Confirm that CheckLambdaProps is called', () => { + const stack = new cdk.Stack(undefined, undefined, { + env: { account: "123456789012", region: 'us-east-1' }, + }); + const testExistingVpc = defaults.getTestVpc(stack); + + const lambdaFunction = new lambda.Function(stack, 'existing-function', { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + functionName: 'name', + vpc: testExistingVpc + }); + + const props: AlbToLambdaProps = { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, + existingLambdaObj: lambdaFunction, + listenerProps: { + certificates: [defaults.getFakeCertificate(stack, "fake-cert")] + }, + publicApi: false, + existingVpc: testExistingVpc, + }; + const app = () => { + new AlbToLambda(stack, 'new-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); + +test('Confirm that CheckVpcProps is called', () => { + const stack = new cdk.Stack(undefined, undefined, { + env: { account: "123456789012", region: 'us-east-1' }, + }); + + const props: AlbToLambdaProps = { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, + listenerProps: { + certificates: [defaults.getFakeCertificate(stack, "fake-cert")] + }, + publicApi: false, + vpcProps: {}, + existingVpc: defaults.getTestVpc(stack), + }; + const app = () => { + new AlbToLambda(stack, 'new-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm that CheckAlbProps is called', () => { + const stack = new cdk.Stack(undefined, undefined, { + env: { account: "123456789012", region: 'us-east-1' }, + }); + const testName = 'test-value'; + + const existingVpc = defaults.getTestVpc(stack); + + const existingAlb = new elb.ApplicationLoadBalancer(stack, 'test-alb', { + vpc: existingVpc, + internetFacing: true, + loadBalancerName: testName, + }); + + const props: AlbToLambdaProps = { + existingVpc, + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, + listenerProps: { + certificates: [defaults.getFakeCertificate(stack, "fake-cert")] + }, + publicApi: false, + vpcProps: {}, + loadBalancerProps: { + loadBalancerName: 'new-loadbalancer', + internetFacing: true, + }, + existingLoadBalancerObj: existingAlb, + }; + const app = () => { + new AlbToLambda(stack, 'new-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide loadBalancerProps or existingLoadBalancerObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.privateApiExistingResources.expected.json b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.privateApiExistingResources.expected.json index a464cff7e..ebe2a257f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.privateApiExistingResources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.privateApiExistingResources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "privateApiExistingResources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "privateApiExistingResources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "privateApiExistingResources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "privateApiExistingResources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "privateApiExistingResources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "privateApiExistingResources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "privateApiExistingResources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "privateApiExistingResources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "privateApiExistingResources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "privateApiExistingResources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "privateApiExistingResources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "privateApiExistingResources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "privateApiExistingResources/Vpc" + "Value": "privateApiExistingResources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "privateApiExistingResources/Vpc" + "Value": "privateApiExistingResources/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,12 +657,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "privateApiExistingResources/Vpc" + "Value": "privateApiExistingResources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "lambdasg93781054": { @@ -807,18 +807,18 @@ }, "S3Key": "7caf594b8ad91abecca72f7f10a23a5cf446d05dc00d6194619935e7e3fd5a79.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -1249,18 +1249,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e57c1acaa363d7d2b81736776007a7091bc73dff4aeb8135627c4511a51e7dca.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -1330,6 +1330,7 @@ "testonetg2tg6459EC7C": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { + "TargetType": "lambda", "Targets": [ { "Id": { @@ -1339,8 +1340,7 @@ ] } } - ], - "TargetType": "lambda" + ] }, "DependsOn": [ "LambdaFunctionInvoke2UTWxhlfyqbT5FTn5jvgbLgjFfJwzswGk55DU1HYAD69E89D" diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.privateApiNewResources.expected.json b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.privateApiNewResources.expected.json index 26e533c99..c24fba1c8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.privateApiNewResources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.privateApiNewResources.expected.json @@ -465,18 +465,18 @@ }, "S3Key": "7caf594b8ad91abecca72f7f10a23a5cf446d05dc00d6194619935e7e3fd5a79.zip" }, - "Role": { - "Fn::GetAtt": [ - "testoneLambdaFunctionServiceRoleE92573D3", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testoneLambdaFunctionServiceRoleE92573D3", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -581,6 +581,7 @@ "testonetg2tg6459EC7C": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { + "TargetType": "lambda", "Targets": [ { "Id": { @@ -590,8 +591,7 @@ ] } } - ], - "TargetType": "lambda" + ] }, "DependsOn": [ "testoneLambdaFunctionInvoke2UTWxhlfyqbT5FTn5jvgbLgjFfJwzswGk55DU1HY508A8518" @@ -615,9 +615,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -634,21 +631,24 @@ "Key": "Name", "Value": "privateApiNewResources/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "privateApiNewResources/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -665,9 +665,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -684,21 +681,24 @@ "Key": "Name", "Value": "privateApiNewResources/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "privateApiNewResources/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -715,9 +715,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -734,21 +731,24 @@ "Key": "Name", "Value": "privateApiNewResources/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "privateApiNewResources/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -780,7 +780,7 @@ "Tags": [ { "Key": "Name", - "Value": "privateApiNewResources/Vpc" + "Value": "privateApiNewResources/Vpc/FlowLog" } ] } @@ -832,7 +832,7 @@ "Tags": [ { "Key": "Name", - "Value": "privateApiNewResources/Vpc" + "Value": "privateApiNewResources/Vpc/FlowLog" } ] }, @@ -852,11 +852,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -867,12 +862,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "privateApiNewResources/Vpc" + "Value": "privateApiNewResources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { @@ -904,18 +904,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e57c1acaa363d7d2b81736776007a7091bc73dff4aeb8135627c4511a51e7dca.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.publicApiExistingResources.expected.json b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.publicApiExistingResources.expected.json index f8efc14d1..ef2fc7821 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.publicApiExistingResources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.publicApiExistingResources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "publicApiExistingResources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiExistingResources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "publicApiExistingResources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiExistingResources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "publicApiExistingResources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiExistingResources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "publicApiExistingResources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiExistingResources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "publicApiExistingResources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiExistingResources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "publicApiExistingResources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiExistingResources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "publicApiExistingResources/Vpc" + "Value": "publicApiExistingResources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "publicApiExistingResources/Vpc" + "Value": "publicApiExistingResources/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,12 +657,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "publicApiExistingResources/Vpc" + "Value": "publicApiExistingResources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "lambdasg93781054": { @@ -807,18 +807,18 @@ }, "S3Key": "7caf594b8ad91abecca72f7f10a23a5cf446d05dc00d6194619935e7e3fd5a79.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -1249,18 +1249,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e57c1acaa363d7d2b81736776007a7091bc73dff4aeb8135627c4511a51e7dca.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -1330,6 +1330,7 @@ "testonetg2tg6459EC7C": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { + "TargetType": "lambda", "Targets": [ { "Id": { @@ -1339,8 +1340,7 @@ ] } } - ], - "TargetType": "lambda" + ] }, "DependsOn": [ "LambdaFunctionInvoke2UTWxhlfyqbT5FTn5jvgbLgjFfJwzswGk55DU1HYAD69E89D" diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.publicApiNewResources.expected.json b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.publicApiNewResources.expected.json index c01076512..b6c7be27d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.publicApiNewResources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.publicApiNewResources.expected.json @@ -471,18 +471,18 @@ }, "S3Key": "7caf594b8ad91abecca72f7f10a23a5cf446d05dc00d6194619935e7e3fd5a79.zip" }, - "Role": { - "Fn::GetAtt": [ - "testoneLambdaFunctionServiceRoleE92573D3", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testoneLambdaFunctionServiceRoleE92573D3", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -593,6 +593,7 @@ "testonetg2tg6459EC7C": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { + "TargetType": "lambda", "Targets": [ { "Id": { @@ -602,8 +603,7 @@ ] } } - ], - "TargetType": "lambda" + ] }, "DependsOn": [ "testoneLambdaFunctionInvoke2UTWxhlfyqbT5FTn5jvgbLgjFfJwzswGk55DU1HY508A8518" @@ -627,9 +627,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -646,7 +643,10 @@ "Key": "Name", "Value": "publicApiNewResources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -662,15 +662,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiNewResources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -687,12 +687,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -714,15 +714,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -738,9 +738,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -757,7 +754,10 @@ "Key": "Name", "Value": "publicApiNewResources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -773,15 +773,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiNewResources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -798,12 +798,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -825,15 +825,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -849,9 +849,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -868,7 +865,10 @@ "Key": "Name", "Value": "publicApiNewResources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -884,15 +884,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiNewResources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -909,12 +909,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -936,15 +936,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -960,9 +960,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -979,21 +976,24 @@ "Key": "Name", "Value": "publicApiNewResources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiNewResources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -1010,21 +1010,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -1041,21 +1038,24 @@ "Key": "Name", "Value": "publicApiNewResources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiNewResources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -1072,21 +1072,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -1103,21 +1100,24 @@ "Key": "Name", "Value": "publicApiNewResources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "publicApiNewResources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -1134,12 +1134,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -1157,11 +1157,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -1183,7 +1183,7 @@ "Tags": [ { "Key": "Name", - "Value": "publicApiNewResources/Vpc" + "Value": "publicApiNewResources/Vpc/FlowLog" } ] } @@ -1235,7 +1235,7 @@ "Tags": [ { "Key": "Name", - "Value": "publicApiNewResources/Vpc" + "Value": "publicApiNewResources/Vpc/FlowLog" } ] }, @@ -1255,11 +1255,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1270,12 +1265,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "publicApiNewResources/Vpc" + "Value": "publicApiNewResources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { @@ -1307,18 +1307,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e57c1acaa363d7d2b81736776007a7091bc73dff4aeb8135627c4511a51e7dca.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", diff --git a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.twoTargets.expected.json b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.twoTargets.expected.json index fcf04b74a..447e2e805 100644 --- a/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.twoTargets.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-alb-lambda/test/integ.twoTargets.expected.json @@ -471,18 +471,18 @@ }, "S3Key": "7caf594b8ad91abecca72f7f10a23a5cf446d05dc00d6194619935e7e3fd5a79.zip" }, - "Role": { - "Fn::GetAtt": [ - "testoneLambdaFunctionServiceRoleE92573D3", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testoneLambdaFunctionServiceRoleE92573D3", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -620,6 +620,7 @@ "testonetg2tg6459EC7C": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { + "TargetType": "lambda", "Targets": [ { "Id": { @@ -629,8 +630,7 @@ ] } } - ], - "TargetType": "lambda" + ] }, "DependsOn": [ "testoneLambdaFunctionInvoke2UTWxhlfyqbT5FTn5jvgbLgjFfJwzswGk55DU1HY508A8518" @@ -654,9 +654,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -673,7 +670,10 @@ "Key": "Name", "Value": "twoTargets/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -689,15 +689,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "twoTargets/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -714,12 +714,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -741,15 +741,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -765,9 +765,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -784,7 +781,10 @@ "Key": "Name", "Value": "twoTargets/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -800,15 +800,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "twoTargets/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -825,12 +825,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -852,15 +852,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -876,9 +876,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -895,7 +892,10 @@ "Key": "Name", "Value": "twoTargets/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -911,15 +911,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "twoTargets/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -936,12 +936,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -963,15 +963,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -987,9 +987,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -1006,21 +1003,24 @@ "Key": "Name", "Value": "twoTargets/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "twoTargets/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -1037,21 +1037,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -1068,21 +1065,24 @@ "Key": "Name", "Value": "twoTargets/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "twoTargets/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -1099,21 +1099,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -1130,21 +1127,24 @@ "Key": "Name", "Value": "twoTargets/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "twoTargets/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -1161,12 +1161,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -1184,11 +1184,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -1210,7 +1210,7 @@ "Tags": [ { "Key": "Name", - "Value": "twoTargets/Vpc" + "Value": "twoTargets/Vpc/FlowLog" } ] } @@ -1262,7 +1262,7 @@ "Tags": [ { "Key": "Name", - "Value": "twoTargets/Vpc" + "Value": "twoTargets/Vpc/FlowLog" } ] }, @@ -1282,11 +1282,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1297,12 +1292,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "twoTargets/Vpc" + "Value": "twoTargets/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { @@ -1334,18 +1334,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e57c1acaa363d7d2b81736776007a7091bc73dff4aeb8135627c4511a51e7dca.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -1520,18 +1520,18 @@ }, "S3Key": "7caf594b8ad91abecca72f7f10a23a5cf446d05dc00d6194619935e7e3fd5a79.zip" }, - "Role": { - "Fn::GetAtt": [ - "testtwoLambdaFunctionServiceRoleD100E5F8", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testtwoLambdaFunctionServiceRoleD100E5F8", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -1611,6 +1611,7 @@ "testtwotg2tg35BE6697": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { + "TargetType": "lambda", "Targets": [ { "Id": { @@ -1620,8 +1621,7 @@ ] } } - ], - "TargetType": "lambda" + ] }, "DependsOn": [ "testtwoLambdaFunctionInvoke2UTWxhlfyqbT5FTn5jvgbLgjFfJwzswGk55DU1HY068D8D47" diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/lib/index.ts index 05724b22d..84cc33e36 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/lib/index.ts @@ -203,25 +203,21 @@ export class ApiGatewayToDynamoDB extends Construct { */ constructor(scope: Construct, id: string, props: ApiGatewayToDynamoDBProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckDynamoDBProps(props); - if ((props.createRequestTemplate || props.additionalCreateRequestTemplates || props.createIntegrationResponses) - && props.allowCreateOperation !== true) { + if (this.CheckCreateRequestProps(props)) { throw new Error(`The 'allowCreateOperation' property must be set to true when setting any of the following: ` + `'createRequestTemplate', 'additionalCreateRequestTemplates', 'createIntegrationResponses'`); } - if ((props.readRequestTemplate || props.additionalReadRequestTemplates || props.readIntegrationResponses) - && props.allowReadOperation === false) { + if (this.CheckReadRequestProps(props)) { throw new Error(`The 'allowReadOperation' property must be set to true or undefined when setting any of the following: ` + `'readRequestTemplate', 'additionalReadRequestTemplates', 'readIntegrationResponses'`); } - if ((props.updateRequestTemplate || props.additionalUpdateRequestTemplates || props.updateIntegrationResponses) - && props.allowUpdateOperation !== true) { + if (this.CheckUpdateRequestProps(props)) { throw new Error(`The 'allowUpdateOperation' property must be set to true when setting any of the following: ` + `'updateRequestTemplate', 'additionalUpdateRequestTemplates', 'updateIntegrationResponses'`); } - if ((props.deleteRequestTemplate || props.additionalDeleteRequestTemplates || props.deleteIntegrationResponses) - && props.allowDeleteOperation !== true) { + if (this.CheckDeleteRequestProps(props)) { throw new Error(`The 'allowDeleteOperation' property must be set to true when setting any of the following: ` + `'deleteRequestTemplate', 'additionalDeleteRequestTemplates', 'deleteIntegrationResponses'`); } @@ -261,8 +257,9 @@ export class ApiGatewayToDynamoDB extends Construct { // Setup API Gateway Method // Create - if (props.allowCreateOperation && props.allowCreateOperation === true && props.createRequestTemplate) { - const createRequestTemplate = props.createRequestTemplate.replace("${Table}", this.dynamoTable.tableName); + if (this.ImplementCreateOperation(props)) { + // ImplementCreateOperation has confirmed that createRequestTemplate exists) + const createRequestTemplate = props.createRequestTemplate!.replace("${Table}", this.dynamoTable.tableName); this.addActionToPolicy("dynamodb:PutItem"); defaults.addProxyMethodToApiResource({ service: "dynamodb", @@ -276,7 +273,7 @@ export class ApiGatewayToDynamoDB extends Construct { }); } // Read - if (props.allowReadOperation === undefined || props.allowReadOperation === true) { + if (this.ImplementReaOperation(props)) { const readRequestTemplate = props.readRequestTemplate ?? `{ \ "TableName": "${this.dynamoTable.tableName}", \ @@ -301,8 +298,9 @@ export class ApiGatewayToDynamoDB extends Construct { }); } // Update - if (props.allowUpdateOperation && props.allowUpdateOperation === true && props.updateRequestTemplate) { - const updateRequestTemplate = props.updateRequestTemplate.replace("${Table}", this.dynamoTable.tableName); + if (this.ImplementUpdateOperation(props)) { + // ImplementUpdateOperation confirmed the existence of updateRequestTemplate + const updateRequestTemplate = props.updateRequestTemplate!.replace("${Table}", this.dynamoTable.tableName); this.addActionToPolicy("dynamodb:UpdateItem"); defaults.addProxyMethodToApiResource({ service: "dynamodb", @@ -316,7 +314,7 @@ export class ApiGatewayToDynamoDB extends Construct { }); } // Delete - if (props.allowDeleteOperation && props.allowDeleteOperation === true) { + if (this.ImplementDeleteOperation(props)) { const deleteRequestTemplate = props.deleteRequestTemplate ?? `{ \ "TableName": "${this.dynamoTable.tableName}", \ @@ -342,6 +340,64 @@ export class ApiGatewayToDynamoDB extends Construct { } } + private CheckReadRequestProps(props: ApiGatewayToDynamoDBProps): boolean { + if ((props.readRequestTemplate || props.additionalReadRequestTemplates || props.readIntegrationResponses) + && props.allowReadOperation === false) { + return true; + } + return false; + } + private CheckUpdateRequestProps(props: ApiGatewayToDynamoDBProps): boolean { + if ((props.updateRequestTemplate || props.additionalUpdateRequestTemplates || props.updateIntegrationResponses) + && props.allowUpdateOperation !== true) { + return true; + } + return false; + } + private CheckDeleteRequestProps(props: ApiGatewayToDynamoDBProps): boolean { + if ((props.deleteRequestTemplate || props.additionalDeleteRequestTemplates || props.deleteIntegrationResponses) + && props.allowDeleteOperation !== true) { + return true; + } + return false; + } + + private CheckCreateRequestProps(props: ApiGatewayToDynamoDBProps): boolean { + if ((props.createRequestTemplate || props.additionalCreateRequestTemplates || props.createIntegrationResponses) + && props.allowCreateOperation !== true) { + return true; + } + return false; + } + + private ImplementCreateOperation(props: ApiGatewayToDynamoDBProps): boolean { + if (props.allowCreateOperation && props.allowCreateOperation === true && props.createRequestTemplate) { + return true; + } + return false; + } + + private ImplementReaOperation(props: ApiGatewayToDynamoDBProps): boolean { + if (props.allowReadOperation === undefined || props.allowReadOperation === true) { + return true; + } + return false; + } + + private ImplementUpdateOperation(props: ApiGatewayToDynamoDBProps): boolean { + if (props.allowUpdateOperation && props.allowUpdateOperation === true && props.updateRequestTemplate) { + return true; + } + return false; + } + + private ImplementDeleteOperation(props: ApiGatewayToDynamoDBProps): boolean { + if (props.allowDeleteOperation && props.allowDeleteOperation === true) { + return true; + } + return false; + } + private addActionToPolicy(action: string) { this.apiGatewayRole.addToPolicy(new iam.PolicyStatement({ resources: [ diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/apigateway-dynamodb.test.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/apigateway-dynamodb.test.ts index af4b249ae..d3b0ca594 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/apigateway-dynamodb.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/apigateway-dynamodb.test.ts @@ -23,11 +23,11 @@ test("check properties", () => { const apiGatewayToDynamoDBProps: ApiGatewayToDynamoDBProps = {}; const construct = new ApiGatewayToDynamoDB( stack, "test-api-gateway-dynamodb-default", apiGatewayToDynamoDBProps); - expect(construct.dynamoTable !== null); - expect(construct.apiGateway !== null); - expect(construct.apiGatewayRole !== null); - expect(construct.apiGatewayCloudWatchRole !== null); - expect(construct.apiGatewayLogGroup !== null); + expect(construct.dynamoTable).toBeDefined(); + expect(construct.apiGateway).toBeDefined(); + expect(construct.apiGatewayRole).toBeDefined(); + expect(construct.apiGatewayCloudWatchRole).toBeDefined(); + expect(construct.apiGatewayLogGroup).toBeDefined(); }); test("check allow CRUD operations", () => { @@ -742,4 +742,35 @@ test('Construct throws error when deleteIntegrationResponses is set and allowDel }); expect(app).toThrowError(/The 'allowDeleteOperation' property must be set to true when setting any of the following: 'deleteRequestTemplate', 'additionalDeleteRequestTemplates', 'deleteIntegrationResponses'/); -}); \ No newline at end of file +}); + +test('Test that CheckDynamoDBProps is getting called', () => { + const stack = new Stack(); + const tableName = 'custom-table-name'; + + const existingTable = new ddb.Table(stack, 'MyTablet', { + tableName, + partitionKey: { + name: 'id', + type: ddb.AttributeType.STRING + } + }); + + const props: ApiGatewayToDynamoDBProps = { + existingTableObj: existingTable, + dynamoTableProps: { + tableName, + partitionKey: { + name: 'id', + type: ddb.AttributeType.STRING + }, + }, + }; + + const app = () => { + new ApiGatewayToDynamoDB(stack, 'test-apigateway-dynamodb-stack', props); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide existingTableObj or dynamoTableProps, but not both.\n/); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.additional-request-templates-custom-resource-name.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.additional-request-templates-custom-resource-name.expected.json index eed3a0f92..782a0bdc5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.additional-request-templates-custom-resource-name.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.additional-request-templates-custom-resource-name.expected.json @@ -82,7 +82,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -423,4 +423,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.additional-request-templates.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.additional-request-templates.expected.json index fd2c4df63..8a7cb091d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.additional-request-templates.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.additional-request-templates.expected.json @@ -74,7 +74,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -415,4 +415,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.apigateway-dynamodb-CRUD.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.apigateway-dynamodb-CRUD.expected.json index daaaa1812..facc03a46 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.apigateway-dynamodb-CRUD.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.apigateway-dynamodb-CRUD.expected.json @@ -77,7 +77,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -688,4 +688,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.apigateway-dynamodb-existing-table.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.apigateway-dynamodb-existing-table.expected.json index 3dbfbe88b..84ec8af74 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.apigateway-dynamodb-existing-table.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.apigateway-dynamodb-existing-table.expected.json @@ -74,7 +74,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -403,4 +403,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.custom-integration-responses.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.custom-integration-responses.expected.json index 09e5898b1..e67df73de 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.custom-integration-responses.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.custom-integration-responses.expected.json @@ -74,7 +74,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -403,4 +403,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.no-arguments.expected.json index 521cd4b5a..5c02ac352 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.no-arguments.expected.json @@ -74,7 +74,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -403,4 +403,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/README.md b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/README.md index 168da9202..de65e6499 100755 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/README.md @@ -104,8 +104,8 @@ Below is a description of the different resources and methods exposed by the API |Method | Resource | Query parameter(s) | Return code(s) | Description| |-------------- | --------------------- | ------------------ | ----------------- | -----------------| | **POST** | `/message/` | **qos** | `200/403/500` | By calling this endpoint, you need to pass the topics on which you would like to publish (e.g `/message/device/foo`).| -| **POST** | `/shadow/` | **None** | `200/403/500` | This route allows to update the shadow document of a thing, given its `thingName` using Unnamed (classic) shadow type. The body shall comply with the standard shadow stucture comprising a `state` node and associated `desired` and `reported` nodes. See the [Updating device shadows](#updating-device-shadows) section for an example.| -| **POST** | `/shadow//` | **None** | `200/403/500` | This route allows to update the named shadow document of a thing, given its `thingName` and the `shadowName` using the Named shadow type. The body shall comply with the standard shadow stucture comprising a `state` node and associated `desired` and `reported` nodes. See the [Updating named shadows](#updating-named-shadows) section for an example.| +| **POST** | `/shadow/` | **None** | `200/403/500` | This route allows to update the shadow document of a thing, given its `thingName` using Unnamed (classic) shadow type. The body shall comply with the standard shadow structure comprising a `state` node and associated `desired` and `reported` nodes. See the [Updating device shadows](#updating-device-shadows) section for an example.| +| **POST** | `/shadow//` | **None** | `200/403/500` | This route allows to update the named shadow document of a thing, given its `thingName` and the `shadowName` using the Named shadow type. The body shall comply with the standard shadow structure comprising a `state` node and associated `desired` and `reported` nodes. See the [Updating named shadows](#updating-named-shadows) section for an example.| ## Architecture diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/lib/index.ts index 2ceec6366..33fa931ab 100755 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/lib/index.ts @@ -82,7 +82,6 @@ export class ApiGatewayToIot extends Construct { */ constructor(scope: Construct, id: string, props: ApiGatewayToIotProps) { super(scope, id); - defaults.CheckProps(props); // Assignment to local member variables to make these available to all member methods of the class. // (Split the string just in case user supplies fully qualified endpoint eg. ab123cdefghij4l-ats.iot.ap-south-1.amazonaws.com) @@ -204,7 +203,7 @@ export class ApiGatewayToIot extends Construct { * Adds a method to specified resource * @param resource API Gateway resource to which this method is added * @param resourcePath path of resource from root - * @param integReqParams request paramters for the Integration method + * @param integReqParams request parameters for the Integration method * @param methodReqParams request parameters at Method level */ private addResourceMethod(resource: api.IResource, props: ApiGatewayToIotProps, resourcePath: string, @@ -279,12 +278,12 @@ export class ApiGatewayToIot extends Construct { ); if (props.apiGatewayCreateApiKey === true) { - // cfn Nag doesn't like having a HTTP Method with Authorization Set to None, supress the warning + // cfn Nag doesn't like having a HTTP Method with Authorization Set to None, suppress the warning defaults.addCfnSuppressRules(apiMethod, [ { id: "W59", reason: - "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE", + "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE", }, ]); } diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.defaultParams.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.defaultParams.expected.json index 43342533a..cb176c354 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.defaultParams.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.defaultParams.expected.json @@ -146,7 +146,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -1300,4 +1300,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.overrideParams.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.overrideParams.expected.json index d1350f303..1133dd641 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.overrideParams.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.overrideParams.expected.json @@ -1,5 +1,5 @@ { - "Description": "Integration Test for aws-apigateway-iot with overriden params", + "Description": "Integration Test for aws-apigateway-iot with overridden params", "Resources": { "apigatewayiotrole39B3B182": { "Type": "AWS::IAM::Role", @@ -140,7 +140,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -294,7 +294,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -405,7 +405,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -518,7 +518,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -633,7 +633,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -750,7 +750,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -869,7 +869,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -990,7 +990,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -1114,7 +1114,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -1225,7 +1225,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -1421,4 +1421,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.overrideParams.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.overrideParams.ts index e232337a1..373913c2b 100755 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.overrideParams.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.overrideParams.ts @@ -21,7 +21,7 @@ import { generateIntegStackName } from '@aws-solutions-constructs/core'; // App setup const app = new cdk.App(); const stack = new cdk.Stack(app, generateIntegStackName(__filename)); -stack.templateOptions.description = 'Integration Test for aws-apigateway-iot with overriden params'; +stack.templateOptions.description = 'Integration Test for aws-apigateway-iot with overridden params'; const apiGatewayProps = { restApiName: 'RestApi-Regional', @@ -74,4 +74,4 @@ const props: ApiGatewayToIotProps = { new ApiGatewayToIot(stack, 'test-apigateway-iot', props); // Synth -app.synth(); \ No newline at end of file +app.synth(); diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.override_auth_api_keys.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.override_auth_api_keys.expected.json index 0956ec2ad..1a2184a10 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.override_auth_api_keys.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/integ.override_auth_api_keys.expected.json @@ -146,7 +146,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -300,7 +300,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -411,7 +411,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -524,7 +524,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -639,7 +639,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -756,7 +756,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -875,7 +875,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -996,7 +996,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -1120,7 +1120,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -1231,7 +1231,7 @@ "rules_to_suppress": [ { "id": "W59", - "reason": "When ApiKey is being created, we also set apikeyRequired to true, so techincally apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" + "reason": "When ApiKey is being created, we also set apikeyRequired to true, so technically apiGateway still looks for apiKey even though user specified AuthorizationType to NONE" } ] } @@ -1427,4 +1427,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/test.apigateway-iot.test.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/test.apigateway-iot.test.ts index 08167903f..15fe5f509 100755 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/test.apigateway-iot.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-iot/test/test.apigateway-iot.test.ts @@ -18,9 +18,6 @@ import * as api from 'aws-cdk-lib/aws-apigateway'; import * as iam from 'aws-cdk-lib/aws-iam'; import { Template } from "aws-cdk-lib/assertions"; -// -------------------------------------------------------------- -// Check for ApiGateway params -// -------------------------------------------------------------- test('Test for default Params construct props', () => { // Initial Setup const stack = new cdk.Stack(); @@ -35,9 +32,6 @@ test('Test for default Params construct props', () => { expect(construct.apiGatewayRole).not.toBeNull(); }); -// -------------------------------------------------------------- -// Check for Default IAM Role -// -------------------------------------------------------------- test('Test for default IAM Role', () => { // Initial Setup const stack = new cdk.Stack(); @@ -45,7 +39,7 @@ test('Test for default IAM Role', () => { iotEndpoint: `a1234567890123-ats` }; new ApiGatewayToIot(stack, 'test-apigateway-iot-default-iam-role', props); - // Check whether default IAM role is creted to access IoT core + // Check whether default IAM role is created to access IoT core const template = Template.fromStack(stack); template.hasResourceProperties("AWS::IAM::Role", { AssumeRolePolicyDocument: { @@ -122,9 +116,6 @@ test('Test for default IAM Role', () => { }); }); -// -------------------------------------------------------------- -// Check for Request Validator -// -------------------------------------------------------------- test('Test for default Params request validator', () => { // Initial Setup const stack = new cdk.Stack(); @@ -140,9 +131,6 @@ test('Test for default Params request validator', () => { }); }); -// -------------------------------------------------------------- -// Check for Integ Props and Method Props -// -------------------------------------------------------------- test('Test for default Params Integ Props and Method Props', () => { // Initial Setup const stack = new cdk.Stack(); @@ -152,7 +140,7 @@ test('Test for default Params Integ Props and Method Props', () => { new ApiGatewayToIot(stack, 'test-apigateway-iot-integpros-methodprops', props); // Assertion for {topic-level-7} to ensure all Integration Request Params, Integration Responses, - // Method Request Params and Method Reponses are intact + // Method Request Params and Method Reposes are intact const template = Template.fromStack(stack); template.hasResourceProperties("AWS::ApiGateway::Method", { HttpMethod: "POST", @@ -234,11 +222,7 @@ test('Test for default Params Integ Props and Method Props', () => { } }); }); - -// -------------------------------------------------------------- -// Check for valid IoT Endpoint -// -------------------------------------------------------------- -test('Test for valid iot enpoint', () => { +test('Test for valid iot endpoint', () => { // Initial Setup const stack = new cdk.Stack(); const props: ApiGatewayToIotProps = { @@ -252,9 +236,6 @@ test('Test for valid iot enpoint', () => { expect(app).toThrowError(); }); -// -------------------------------------------------------------- -// Check for binaryMediaTypes -// -------------------------------------------------------------- test('Test for Binary Media types', () => { // Stack const stack = new cdk.Stack(); @@ -272,9 +253,6 @@ test('Test for Binary Media types', () => { }); }); -// -------------------------------------------------------------- -// Check for Api Name and Desc -// -------------------------------------------------------------- test('Test for Api Name and Desc', () => { // Stack const stack = new cdk.Stack(); @@ -296,10 +274,7 @@ test('Test for Api Name and Desc', () => { }); }); -// -------------------------------------------------------------- -// Check for Overriden IAM Role -// -------------------------------------------------------------- -test('Test for overriden IAM Role', () => { +test('Test for overridden IAM Role', () => { // Initial Setup const stack = new cdk.Stack(); @@ -337,8 +312,8 @@ test('Test for overriden IAM Role', () => { apiGatewayExecutionRole, }; - new ApiGatewayToIot(stack, 'test-apigateway-iot-overriden-iam-role', props); - // Check whether default IAM role is creted to access IoT core + new ApiGatewayToIot(stack, 'test-apigateway-iot-overridden-iam-role', props); + // Check whether default IAM role is created to access IoT core const template = Template.fromStack(stack); template.hasResourceProperties("AWS::IAM::Role", { AssumeRolePolicyDocument: { @@ -407,9 +382,6 @@ test('Test for overriden IAM Role', () => { }); }); -// -------------------------------------------------------------- -// Check for Api Key Source -// -------------------------------------------------------------- test('Test for APi Key Source', () => { // Stack const stack = new cdk.Stack(); @@ -430,9 +402,6 @@ test('Test for APi Key Source', () => { }); }); -// -------------------------------------------------------------- -// Check for Api Key Creation -// -------------------------------------------------------------- test('Test for Api Key Creation', () => { // Initial Setup const stack = new cdk.Stack(); @@ -467,9 +436,6 @@ test('Test for Api Key Creation', () => { }); }); -// ----------------------------------------------------------------- -// Test deployment for ApiGateway endPointCongiurationOverride -// ----------------------------------------------------------------- test('Test for deployment ApiGateway AuthorizationType override', () => { // Stack const stack = new cdk.Stack(); @@ -491,9 +457,6 @@ test('Test for deployment ApiGateway AuthorizationType override', () => { }); }); -// ----------------------------------------------------------------- -// Test deployment for override ApiGateway AuthorizationType to NONE -// ----------------------------------------------------------------- test('Test for deployment ApiGateway AuthorizationType override', () => { // Stack const stack = new cdk.Stack(); @@ -514,9 +477,6 @@ test('Test for deployment ApiGateway AuthorizationType override', () => { }); }); -// ----------------------------------------------------------------- -// Test deployment for fully qualified iotEndpoint name -// ----------------------------------------------------------------- test('Test for handling fully qualified iotEndpoint', () => { // Stack const stack = new cdk.Stack(); @@ -550,4 +510,4 @@ test('Test for handling fully qualified iotEndpoint', () => { ] } } }); -}); \ No newline at end of file +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/lib/index.ts index 52f389453..767bc37c4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/lib/index.ts @@ -137,7 +137,7 @@ export class ApiGatewayToKinesisStreams extends Construct { */ constructor(scope: Construct, id: string, props: ApiGatewayToKinesisStreamsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckKinesisStreamProps(props); // Setup the Kinesis stream this.kinesisStream = defaults.buildKinesisStream(scope, { diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/apigateway-kinesisstreams.test.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/apigateway-kinesisstreams.test.ts index 0eaed6ecc..a3bbaf0ff 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/apigateway-kinesisstreams.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/apigateway-kinesisstreams.test.ts @@ -13,28 +13,22 @@ // Imports import { Stack, Duration } from 'aws-cdk-lib'; -import { ApiGatewayToKinesisStreams } from '../lib'; +import { ApiGatewayToKinesisStreams, ApiGatewayToKinesisStreamsProps } from '../lib'; import * as kinesis from 'aws-cdk-lib/aws-kinesis'; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Test construct properties -// -------------------------------------------------------------- test('Test construct properties', () => { const stack = new Stack(); const pattern = new ApiGatewayToKinesisStreams(stack, 'api-gateway-kinesis', {}); - expect(pattern.apiGateway !== null); - expect(pattern.apiGatewayRole !== null); - expect(pattern.apiGatewayCloudWatchRole !== null); - expect(pattern.apiGatewayLogGroup !== null); - expect(pattern.kinesisStream !== null); - expect(pattern.cloudwatchAlarms !== null); + expect(pattern.apiGateway).toBeDefined(); + expect(pattern.apiGatewayRole).toBeDefined(); + expect(pattern.apiGatewayCloudWatchRole).toBeDefined(); + expect(pattern.apiGatewayLogGroup).toBeDefined(); + expect(pattern.kinesisStream).toBeDefined(); + expect(pattern.cloudwatchAlarms).toBeDefined(); }); -// -------------------------------------------------------------- -// Test deployment w/ overwritten properties -// -------------------------------------------------------------- test('Test deployment w/ overwritten properties', () => { const stack = new Stack(); @@ -87,9 +81,6 @@ test('Test deployment w/ overwritten properties', () => { template.resourceCountIs('AWS::CloudWatch::Alarm', 2); }); -// -------------------------------------------------------------- -// Test deployment w/ existing stream without default cloudwatch alarms -// -------------------------------------------------------------- test('Test deployment w/ existing stream', () => { const stack = new Stack(); @@ -110,13 +101,13 @@ test('Test deployment w/ existing stream', () => { expect(construct.cloudwatchAlarms == null); - // Since createCloudWatchAlars is set to false, no Alarm should exist + // Since createCloudWatchAlarm is set to false, no Alarm should exist template.resourceCountIs('AWS::CloudWatch::Alarm', 0); }); test('Construct accepts additional PutRecord request templates', () => { const stack = new Stack(); - new ApiGatewayToKinesisStreams(stack, 'api-gateway-kinesis-streams ', { + new ApiGatewayToKinesisStreams(stack, 'api-gateway-kinesis-streams', { additionalPutRecordRequestTemplates: { 'text/plain': 'custom-template' } @@ -232,4 +223,18 @@ test('Construct uses custom putRecordsIntegrationResponses property', () => { ] } }); -}); \ No newline at end of file +}); + +test('Confirm that CheckKinesisStreamProps is called', () => { + const stack = new Stack(); + + const props: ApiGatewayToKinesisStreamsProps = { + existingStreamObj: new kinesis.Stream(stack, 'test', {}), + kinesisStreamProps: {} + }; + + const app = () => { + new ApiGatewayToKinesisStreams(stack, 'test-eventbridge-kinesisstreams', props); + }; + expect(app).toThrowError(); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.additional-request-templates.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.additional-request-templates.expected.json index b25627113..8108502ac 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.additional-request-templates.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.additional-request-templates.expected.json @@ -53,7 +53,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -626,4 +626,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.apigateway-kinesis-overwrite.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.apigateway-kinesis-overwrite.expected.json index 4cb3f8ff3..5de730a4e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.apigateway-kinesis-overwrite.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.apigateway-kinesis-overwrite.expected.json @@ -53,7 +53,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -578,4 +578,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.custom-integration-responses.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.custom-integration-responses.expected.json index 4ead90e0f..bbdf26eb8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.custom-integration-responses.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.custom-integration-responses.expected.json @@ -53,7 +53,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -610,4 +610,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.no-arguments.expected.json index c59473e94..7037d7e4f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-kinesisstreams/test/integ.no-arguments.expected.json @@ -53,7 +53,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -614,4 +614,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/lib/index.ts index 6a69f86d8..570a4f30c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/lib/index.ts @@ -69,7 +69,7 @@ export class ApiGatewayToLambda extends Construct { */ constructor(scope: Construct, id: string, props: ApiGatewayToLambdaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckLambdaProps(props); // Setup the Lambda function this.lambdaFunction = defaults.buildLambdaFunction(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/integ.deployFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/integ.deployFunction.expected.json index 6418ca233..e154b7aa8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/integ.deployFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/integ.deployFunction.expected.json @@ -187,7 +187,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -629,4 +629,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/integ.existingFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/integ.existingFunction.expected.json index ca87bbb51..500d0accd 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/integ.existingFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/integ.existingFunction.expected.json @@ -187,7 +187,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -629,4 +629,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/test.apigateway-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/test.apigateway-lambda.test.ts index bb97187d7..784eb57c5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/test.apigateway-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-lambda/test/test.apigateway-lambda.test.ts @@ -19,9 +19,6 @@ import * as api from 'aws-cdk-lib/aws-apigateway'; import { Template } from "aws-cdk-lib/assertions"; import * as defaults from '@aws-solutions-constructs/core'; -// -------------------------------------------------------------- -// Test for error with existingLambdaObj=undefined (not supplied by user). -// -------------------------------------------------------------- test('Error on existingLambdaObj=undefined', () => { // Initial Setup const stack = new Stack(); @@ -34,9 +31,6 @@ test('Error on existingLambdaObj=undefined', () => { expect(app).toThrowError(); }); -// -------------------------------------------------------------- -// Test with lambdaFunctionProps. -// -------------------------------------------------------------- test('Test with lambdaFunctionProps', () => { // Initial Setup const stack = new Stack(); @@ -66,9 +60,6 @@ test('Test with lambdaFunctionProps', () => { }); }); -// -------------------------------------------------------------- -// Test getter methods -// -------------------------------------------------------------- test('Test properties', () => { // Initial Setup const stack = new Stack(); @@ -81,16 +72,13 @@ test('Test properties', () => { }; const app = new ApiGatewayToLambda(stack, 'test-apigateway-lambda', props); // Assertion 1 - expect(app.lambdaFunction !== null); + expect(app.lambdaFunction).toBeDefined(); // Assertion 2 - expect(app.apiGateway !== null); - expect(app.apiGatewayCloudWatchRole !== null); - expect(app.apiGatewayLogGroup !== null); + expect(app.apiGateway).toBeDefined(); + expect(app.apiGatewayCloudWatchRole).toBeDefined(); + expect(app.apiGatewayLogGroup).toBeDefined(); }); -// -------------------------------------------------------------- -// Test for error with lambdaFunctionProps=undefined (not supplied by user). -// -------------------------------------------------------------- test('Error on lambdaFunctionProps=undefined', () => { // Initial Setup const stack = new Stack(); @@ -103,9 +91,6 @@ test('Error on lambdaFunctionProps=undefined', () => { expect(app).toThrowError(); }); -// ----------------------------------------------------------------- -// Test deployment for override ApiGateway AuthorizationType to NONE -// ----------------------------------------------------------------- test('Test deployment ApiGateway AuthorizationType override', () => { // Stack const stack = new Stack(); @@ -130,9 +115,6 @@ test('Test deployment ApiGateway AuthorizationType override', () => { }); }); -// ----------------------------------------------------------------- -// Test deployment for override ApiGateway cloudWatchRole = false -// ----------------------------------------------------------------- test('Test deployment ApiGateway override cloudWatchRole = false', () => { // Stack const stack = new Stack(); @@ -149,4 +131,34 @@ test('Test deployment ApiGateway override cloudWatchRole = false', () => { }); // Assertion 1 defaults.expectNonexistence(stack, "AWS::ApiGateway::Account", {}); -}); \ No newline at end of file +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: ApiGatewayToLambdaProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + environment: { + OVERRIDE_STATUS: 'true' + } + }, + existingLambdaObj: lambdaFunction, + apiGatewayProps: { + description: "sampleApiProp" + } + }; + const app = () => { + new ApiGatewayToLambda(stack, 'test-apigateway-lambda', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/lib/index.ts index 0ff4b0628..7d2324c18 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/lib/index.ts @@ -100,7 +100,7 @@ export class ApiGatewayToSageMakerEndpoint extends Construct { */ constructor(scope: Construct, id: string, props: ApiGatewayToSageMakerEndpointProps) { super(scope, id); - defaults.CheckProps(props); + // CheckSagemakerProps is not called because this construct can't create a Sagemaker resource // Setup the API Gateway const globalRestApiResponse = defaults.GlobalRestApi(this, props.apiGatewayProps, props.logGroupProps); diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/apigateway-sagemakerendpoint.test.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/apigateway-sagemakerendpoint.test.ts index c31b4da3b..472f6550d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/apigateway-sagemakerendpoint.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/apigateway-sagemakerendpoint.test.ts @@ -17,9 +17,6 @@ import { ApiGatewayToSageMakerEndpoint } from '../lib'; import * as iam from 'aws-cdk-lib/aws-iam'; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Test construct properties -// -------------------------------------------------------------- test('Test construct properties', () => { const stack = new Stack(); const pattern = new ApiGatewayToSageMakerEndpoint(stack, 'api-gateway-sagemakerendpoint', { @@ -28,15 +25,12 @@ test('Test construct properties', () => { requestMappingTemplate: 'my-request-vtl-template' }); - expect(pattern.apiGateway !== null); - expect(pattern.apiGatewayRole !== null); - expect(pattern.apiGatewayCloudWatchRole !== null); - expect(pattern.apiGatewayLogGroup !== null); + expect(pattern.apiGateway).toBeDefined(); + expect(pattern.apiGatewayRole).toBeDefined(); + expect(pattern.apiGatewayCloudWatchRole).toBeDefined(); + expect(pattern.apiGatewayLogGroup).toBeDefined(); }); -// -------------------------------------------------------------- -// Test deployment w/ overwritten properties -// -------------------------------------------------------------- test('Test deployment w/ overwritten properties', () => { const stack = new Stack(); diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.additional-request-templates.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.additional-request-templates.expected.json index fb8b6a00d..a56e9da6a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.additional-request-templates.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.additional-request-templates.expected.json @@ -49,7 +49,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -393,4 +393,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.apigateway-sagemakerendpoint-overwrite.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.apigateway-sagemakerendpoint-overwrite.expected.json index ff698689f..f42bbea54 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.apigateway-sagemakerendpoint-overwrite.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.apigateway-sagemakerendpoint-overwrite.expected.json @@ -102,7 +102,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -403,4 +403,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.no-overwrite.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.no-overwrite.expected.json index 818f748dc..7ab66b90f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.no-overwrite.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sagemakerendpoint/test/integ.no-overwrite.expected.json @@ -49,7 +49,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -392,4 +392,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/lib/index.ts index 1b4d00221..b97e9198d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/lib/index.ts @@ -196,20 +196,17 @@ export class ApiGatewayToSqs extends Construct { */ constructor(scope: Construct, id: string, props: ApiGatewayToSqsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckSqsProps(props); - if ((props.createRequestTemplate || props.additionalCreateRequestTemplates || props.createIntegrationResponses) - && props.allowCreateOperation !== true) { + if (this.CheckCreateRequestProps(props)) { throw new Error(`The 'allowCreateOperation' property must be set to true when setting any of the following: ` + `'createRequestTemplate', 'additionalCreateRequestTemplates', 'createIntegrationResponses'`); } - if ((props.readRequestTemplate || props.additionalReadRequestTemplates || props.readIntegrationResponses) - && props.allowReadOperation === false) { + if (this.CheckReadRequestProps(props)) { throw new Error(`The 'allowReadOperation' property must be set to true or undefined when setting any of the following: ` + `'readRequestTemplate', 'additionalReadRequestTemplates', 'readIntegrationResponses'`); } - if ((props.deleteRequestTemplate || props.additionalDeleteRequestTemplates || props.deleteIntegrationResponses) - && props.allowDeleteOperation !== true) { + if (this.CheckDeleteRequestProps(props)) { throw new Error(`The 'allowDeleteOperation' property must be set to true when setting any of the following: ` + `'deleteRequestTemplate', 'additionalDeleteRequestTemplates', 'deleteIntegrationResponses'`); } @@ -298,6 +295,28 @@ export class ApiGatewayToSqs extends Construct { }); } } + private CheckReadRequestProps(props: ApiGatewayToSqsProps): boolean { + if ((props.readRequestTemplate || props.additionalReadRequestTemplates || props.readIntegrationResponses) + && props.allowReadOperation === false) { + return true; + } + return false; + } + private CheckDeleteRequestProps(props: ApiGatewayToSqsProps): boolean { + if ((props.deleteRequestTemplate || props.additionalDeleteRequestTemplates || props.deleteIntegrationResponses) + && props.allowDeleteOperation !== true) { + return true; + } + return false; + } + + private CheckCreateRequestProps(props: ApiGatewayToSqsProps): boolean { + if ((props.createRequestTemplate || props.additionalCreateRequestTemplates || props.createIntegrationResponses) + && props.allowCreateOperation !== true) { + return true; + } + return false; + } private addActionToPolicy(action: string) { this.apiGatewayRole.addToPolicy(new iam.PolicyStatement({ diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/apigateway-sqs.test.ts b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/apigateway-sqs.test.ts index bffefbe46..83b3907ad 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/apigateway-sqs.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/apigateway-sqs.test.ts @@ -12,7 +12,7 @@ */ // Imports -import { Stack } from "aws-cdk-lib"; +import { RemovalPolicy, Stack } from "aws-cdk-lib"; import { ApiGatewayToSqs } from '../lib'; import * as api from "aws-cdk-lib/aws-apigateway"; import * as kms from 'aws-cdk-lib/aws-kms'; @@ -70,14 +70,14 @@ test('Test properties', () => { maxReceiveCount: 3 }); // Assertion 1 - expect(pattern.apiGateway !== null); + expect(pattern.apiGateway).toBeDefined(); // Assertion 2 - expect(pattern.sqsQueue !== null); + expect(pattern.sqsQueue).toBeDefined(); // Assertion 3 - expect(pattern.apiGatewayRole !== null); - expect(pattern.apiGatewayCloudWatchRole !== null); - expect(pattern.apiGatewayLogGroup !== null); - expect(pattern.deadLetterQueue !== null); + expect(pattern.apiGatewayRole).toBeDefined(); + expect(pattern.apiGatewayCloudWatchRole).toBeDefined(); + expect(pattern.apiGatewayLogGroup).toBeDefined(); + expect(pattern.deadLetterQueue).toBeDefined(); }); test('Test deployment ApiGateway AuthorizationType override', () => { @@ -220,7 +220,7 @@ test('Queue is encrypted with imported CMK when set on queueProps.encryptionKeyP }); }); -test('Queue is encrypted with provided encrytionKeyProps', () => { +test('Queue is encrypted with provided encryptionKeyProps', () => { const stack = new Stack(); new ApiGatewayToSqs(stack, 'api-gateway-sqs', { encryptionKeyProps: { @@ -634,4 +634,19 @@ test('Construct throws error when deleteIntegrationResponses is set and allowDel }); expect(app).toThrowError(/The 'allowDeleteOperation' property must be set to true when setting any of the following: 'deleteRequestTemplate', 'additionalDeleteRequestTemplates', 'deleteIntegrationResponses'/); -}); \ No newline at end of file +}); + +test('Confirm the CheckSqsProps is being called', () => { + const stack = new Stack(); + + const app = () => { + new ApiGatewayToSqs(stack, 'api-gateway-sqs', { + queueProps: { + removalPolicy: RemovalPolicy.DESTROY, + }, + existingQueueObj: new sqs.Queue(stack, 'test', {}) + }); + }; + + expect(app).toThrowError(/Error - Either provide queueProps or existingQueueObj, but not both.\n/); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.additional-request-templates.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.additional-request-templates.expected.json index 32f5d3a15..f50cec09a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.additional-request-templates.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.additional-request-templates.expected.json @@ -216,7 +216,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -643,4 +643,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.apigateway-sqs-crud.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.apigateway-sqs-crud.expected.json index 41bd2c1ca..752ae8ec5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.apigateway-sqs-crud.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.apigateway-sqs-crud.expected.json @@ -217,7 +217,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -735,4 +735,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.custom-integration-responses.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.custom-integration-responses.expected.json index 1ba7f0556..746f632fa 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.custom-integration-responses.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.custom-integration-responses.expected.json @@ -215,7 +215,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -542,4 +542,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.existing-queue.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.existing-queue.expected.json index abb0ac42b..fb76a1f8a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.existing-queue.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.existing-queue.expected.json @@ -127,7 +127,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -458,4 +458,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.no-arguments.expected.json index e800a3522..4797bac67 100644 --- a/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-apigateway-sqs/test/integ.no-arguments.expected.json @@ -215,7 +215,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -546,4 +546,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/lib/index.ts index 6af19fa39..6ef986a5a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/lib/index.ts @@ -104,7 +104,8 @@ export class CloudFrontToApiGatewayToLambda extends Construct { */ constructor(scope: Construct, id: string, props: CloudFrontToApiGatewayToLambdaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckLambdaProps(props); + // CheckCloudFrontProps() is called by internal aws-cloudfront-apigateway construct this.lambdaFunction = defaults.buildLambdaFunction(this, { existingLambdaObj: props.existingLambdaObj, diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.customCloudfrontLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.customCloudfrontLoggingBucket.expected.json index d5ef6110f..159abab0a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.customCloudfrontLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.customCloudfrontLoggingBucket.expected.json @@ -187,7 +187,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -895,14 +895,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -967,109 +967,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", @@ -1104,4 +1001,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.no-arguments.expected.json index 634d54238..46696cee7 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.no-arguments.expected.json @@ -187,7 +187,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -895,14 +895,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -967,109 +967,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", @@ -1104,4 +1001,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.override-behavior.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.override-behavior.expected.json index c67b521d0..120092782 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.override-behavior.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/integ.override-behavior.expected.json @@ -236,7 +236,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -934,14 +934,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -1006,109 +1006,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", @@ -1143,4 +1040,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/test.cloudfront-apigateway-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/test.cloudfront-apigateway-lambda.test.ts index a44bffeee..e5e225b2d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/test.cloudfront-apigateway-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/test/test.cloudfront-apigateway-lambda.test.ts @@ -47,13 +47,13 @@ test('check properties', () => { const construct: CloudFrontToApiGatewayToLambda = deployNewFunc(stack); - expect(construct.cloudFrontWebDistribution !== null); - expect(construct.apiGateway !== null); - expect(construct.lambdaFunction !== null); - expect(construct.cloudFrontFunction !== null); - expect(construct.cloudFrontLoggingBucket !== null); - expect(construct.apiGatewayCloudWatchRole !== null); - expect(construct.apiGatewayLogGroup !== null); + expect(construct.cloudFrontWebDistribution).toBeDefined(); + expect(construct.apiGateway).toBeDefined(); + expect(construct.lambdaFunction).toBeDefined(); + expect(construct.cloudFrontFunction).toBeDefined(); + expect(construct.cloudFrontLoggingBucket).toBeDefined(); + expect(construct.apiGatewayCloudWatchRole).toBeDefined(); + expect(construct.apiGatewayLogGroup).toBeDefined(); }); test('check lambda function properties for deploy: true', () => { @@ -202,9 +202,6 @@ test('override api gateway properties without existingLambdaObj', () => { }); }); -// -------------------------------------------------------------- -// Cloudfront logging bucket with destroy removal policy and auto delete objects -// -------------------------------------------------------------- test('Cloudfront logging bucket with destroy removal policy and auto delete objects', () => { const stack = new cdk.Stack(); @@ -243,9 +240,6 @@ test('Cloudfront logging bucket with destroy removal policy and auto delete obje }); }); -// -------------------------------------------------------------- -// Cloudfront logging bucket error providing existing log bucket and logBucketProps -// -------------------------------------------------------------- test('Cloudfront logging bucket error when providing existing log bucket and logBucketProps', () => { const stack = new cdk.Stack(); const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {}); @@ -272,4 +266,52 @@ test('Cloudfront logging bucket error when providing existing log bucket and log }; expect(app).toThrowError(); -}); \ No newline at end of file +}); + +test('Confirm CheckLambdaProps is being called', () => { + const stack = new cdk.Stack(); + const existingLambdaObj = new lambda.Function(stack, 'ExistingLambda', { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: CloudFrontToApiGatewayToLambdaProps = { + existingLambdaObj, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + } + }; + + const app = () => { + new CloudFrontToApiGatewayToLambda(stack, 'cf-test-apigateway-lambda', props); + }; + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); + +test("Confirm CheckCloudFrontProps is being called", () => { + const stack = new cdk.Stack(); + + expect(() => { + new CloudFrontToApiGatewayToLambda(stack, "test-cloudfront-apigateway-lambda", { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + insertHttpSecurityHeaders: true, + responseHeadersPolicyProps: { + securityHeadersBehavior: { + strictTransportSecurity: { + accessControlMaxAge: cdk.Duration.seconds(63072), + includeSubdomains: true, + override: false, + preload: true + } + } + } + }); + }).toThrowError('responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/lib/index.ts index 3deb82336..2114518b1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/lib/index.ts @@ -79,7 +79,7 @@ export class CloudFrontToApiGateway extends Construct { */ constructor(scope: Construct, id: string, props: CloudFrontToApiGatewayProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckCloudFrontProps(props); this.apiGateway = props.existingApiGatewayObj; diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/integ.customCloudfrontLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/integ.customCloudfrontLoggingBucket.expected.json index 2f08d62ff..954c1541e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/integ.customCloudfrontLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/integ.customCloudfrontLoggingBucket.expected.json @@ -187,7 +187,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -895,14 +895,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -967,109 +967,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", @@ -1104,4 +1001,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/integ.no-arguments.expected.json index 4f4e17671..ba44a3a00 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/integ.no-arguments.expected.json @@ -187,7 +187,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -895,14 +895,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -967,109 +967,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", @@ -1104,4 +1001,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/test.cloudfront-apigateway.test.ts b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/test.cloudfront-apigateway.test.ts index d7ad60d05..c78c782ab 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/test.cloudfront-apigateway.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/test.cloudfront-apigateway.test.ts @@ -40,10 +40,10 @@ test('check getter methods', () => { const construct: CloudFrontToApiGateway = deploy(stack); - expect(construct.cloudFrontWebDistribution !== null); - expect(construct.apiGateway !== null); - expect(construct.cloudFrontFunction !== null); - expect(construct.cloudFrontLoggingBucket !== null); + expect(construct.cloudFrontWebDistribution).toBeDefined(); + expect(construct.apiGateway).toBeDefined(); + expect(construct.cloudFrontFunction).toBeDefined(); + expect(construct.cloudFrontLoggingBucket).toBeDefined(); }); test('test cloudfront DomainName', () => { @@ -177,9 +177,6 @@ function createApi() { return {stack, api: regionalLambdaRestApiResponse.api}; } -// -------------------------------------------------------------- -// Cloudfront logging bucket with destroy removal policy and auto delete objects -// -------------------------------------------------------------- test('Cloudfront logging bucket with destroy removal policy and auto delete objects', () => { const {stack, api} = createApi(); @@ -209,9 +206,6 @@ test('Cloudfront logging bucket with destroy removal policy and auto delete obje }); }); -// -------------------------------------------------------------- -// Cloudfront logging bucket error providing existing log bucket and logBucketProps -// -------------------------------------------------------------- test('Cloudfront logging bucket error when providing existing log bucket and logBucketProps', () => { const {stack, api} = createApi(); @@ -275,7 +269,7 @@ test('Test the deployment with securityHeadersBehavior instead of HTTP security expect(cloudFrontToS3.cloudFrontFunction).toEqual(undefined); }); -test("throw exception if insertHttpSecurityHeaders and responseHeadersPolicyProps are provided", () => { +test("Confirm CheckCloudFrontProps is being called", () => { const {stack, api} = createApi(); expect(() => { @@ -293,5 +287,5 @@ test("throw exception if insertHttpSecurityHeaders and responseHeadersPolicyProp } } }); - }).toThrowError(); + }).toThrowError('responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.'); }); diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/lib/index.ts index e8b4c4fbd..f8110107f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/lib/index.ts @@ -23,7 +23,7 @@ import { Aws } from 'aws-cdk-lib'; */ export interface CloudFrontToMediaStoreProps { /** - * Existing instance of mediastore.CfnContainer obejct. + * Existing instance of mediastore.CfnContainer object. * * @default - None */ @@ -87,7 +87,8 @@ export class CloudFrontToMediaStore extends Construct { */ constructor(scope: Construct, id: string, props: CloudFrontToMediaStoreProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckMediaStoreProps(props); + defaults.CheckCloudFrontProps(props); let cloudFrontDistributionProps = props.cloudFrontDistributionProps; diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/cloudfront-mediastore.test.ts b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/cloudfront-mediastore.test.ts index 73363676c..7aaddb2ef 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/cloudfront-mediastore.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/cloudfront-mediastore.test.ts @@ -20,9 +20,6 @@ import { CloudFrontToMediaStore } from '../lib'; import * as cdk from "aws-cdk-lib"; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Test the default deployment pattern variables -// -------------------------------------------------------------- test('Test the default deployment pattern variables', () => { // Initial setup const stack = new Stack(); @@ -37,9 +34,6 @@ test('Test the default deployment pattern variables', () => { expect(cloudFrontToMediaStore.cloudFrontFunction).not.toEqual(undefined); }); -// -------------------------------------------------------------- -// Test the deployment without HTTP security headers -// -------------------------------------------------------------- test('Test the deployment without HTTP security headers', () => { // Initial setup const stack = new Stack(); @@ -170,7 +164,7 @@ test('Test the deployment with securityHeadersBehavior instead of HTTP security expect(cloudFrontToMediaStore.cloudFrontFunction).toEqual(undefined); }); -test("throw exception if insertHttpSecurityHeaders and responseHeadersPolicyProps are provided", () => { +test("Confirm CheckCloudFrontProps is being called", () => { const stack = new cdk.Stack(); expect(() => { @@ -187,12 +181,9 @@ test("throw exception if insertHttpSecurityHeaders and responseHeadersPolicyProp } } }); - }).toThrowError(); + }).toThrowError('responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.'); }); -// -------------------------------------------------------------- -// Test the deployment with existing MediaStore container -// -------------------------------------------------------------- test('Test the deployment with existing MediaStore container', () => { // Initial setup const stack = new Stack(); @@ -325,9 +316,6 @@ test('Test the deployment with existing MediaStore container', () => { expect(cloudFrontToMediaStore.cloudFrontOriginAccessIdentity).toEqual(undefined); }); -// -------------------------------------------------------------- -// Test the deployment with the user provided MediaStore properties -// -------------------------------------------------------------- test('Test the deployment with the user provided MediaStore properties', () => { // Initial setup const stack = new Stack(); @@ -471,9 +459,6 @@ test('Test the deployment with the user provided MediaStore properties', () => { expect(cloudFrontToMediaStore.cloudFrontOriginAccessIdentity).toEqual(undefined); }); -// -------------------------------------------------------------- -// Test the deployment with the user provided CloudFront properties -// -------------------------------------------------------------- test('Test the deployment with the user provided CloudFront properties', () => { // Initial setup const stack = new Stack(); @@ -650,9 +635,6 @@ test('Test the deployment with the user provided CloudFront properties', () => { }); }); -// -------------------------------------------------------------- -// Cloudfront logging bucket with destroy removal policy and auto delete objects -// -------------------------------------------------------------- test('Cloudfront logging bucket with destroy removal policy and auto delete objects', () => { const stack = new Stack(); @@ -681,9 +663,6 @@ test('Cloudfront logging bucket with destroy removal policy and auto delete obje }); }); -// -------------------------------------------------------------- -// Cloudfront logging bucket error providing existing log bucket and logBucketProps -// -------------------------------------------------------------- test('Cloudfront logging bucket error when providing existing log bucket and logBucketProps', () => { const stack = new Stack(); const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {}); @@ -700,4 +679,22 @@ test('Cloudfront logging bucket error when providing existing log bucket and log }; expect(app).toThrowError(); -}); \ No newline at end of file +}); + +test('Confirm CheckMediaStoreProps is called', () => { + const stack = new Stack(); + + const mediaStoreContainer = new mediastore.CfnContainer(stack, 'MyMediaStoreContainer', { + containerName: 'MyMediaStoreContainer' + }); + const props = { + existingMediaStoreContainerObj: mediaStoreContainer, + mediaStoreContainerProps: { containerName: 'test' } + }; + + const app = () => { + new CloudFrontToMediaStore(stack, 'cloudfront-s3', props); + }; + + expect(app).toThrowError('Error - Either provide mediaStoreContainerProps or existingMediaStoreContainerObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.customCloudFrontLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.customCloudFrontLoggingBucket.expected.json index 76821d838..1dda93107 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.customCloudFrontLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.customCloudFrontLoggingBucket.expected.json @@ -421,14 +421,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -465,109 +465,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.default.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.default.expected.json index ac97c2c9b..017e02b08 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.default.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.default.expected.json @@ -421,14 +421,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -465,109 +465,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.existingContainer.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.existingContainer.expected.json index e1188e25c..4685cedc1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.existingContainer.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.existingContainer.expected.json @@ -338,14 +338,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -382,109 +382,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.overrideProperties.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.overrideProperties.expected.json index 9765898cd..b7373e8e3 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.overrideProperties.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.overrideProperties.expected.json @@ -380,14 +380,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -424,109 +424,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.withoutHttpSecurityHeaders.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.withoutHttpSecurityHeaders.expected.json index f78e1bcf4..f32082de5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.withoutHttpSecurityHeaders.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-mediastore/test/integ.withoutHttpSecurityHeaders.expected.json @@ -398,14 +398,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -442,109 +442,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/lib/index.ts index 9e720bb25..45776a697 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/lib/index.ts @@ -64,7 +64,7 @@ export interface CloudFrontToS3Props { * Optional user provided props to provide an originPath that CloudFront appends to the * origin domain name when CloudFront requests content from the origin. * The string should start with a `/`, for example `/production`. - * @dafault = '/' + * @default = '/' */ readonly originPath?: string, /** @@ -111,7 +111,8 @@ export class CloudFrontToS3 extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); + defaults.CheckS3Props(props); + defaults.CheckCloudFrontProps(props); let bucket: s3.IBucket; diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.custom-originPath.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.custom-originPath.expected.json index d3ba2fc04..aa9a6f24b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.custom-originPath.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.custom-originPath.expected.json @@ -585,14 +585,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -629,109 +629,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.custom-security-headers.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.custom-security-headers.expected.json index f9563b6ca..266cdd2a2 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.custom-security-headers.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.custom-security-headers.expected.json @@ -616,14 +616,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -660,109 +660,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.customCloudFrontLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.customCloudFrontLoggingBucket.expected.json index f22102846..5b99a5606 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.customCloudFrontLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.customCloudFrontLoggingBucket.expected.json @@ -584,14 +584,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -628,109 +628,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.customLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.customLoggingBucket.expected.json index 3e433548d..1a5473490 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.customLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.customLoggingBucket.expected.json @@ -647,14 +647,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -691,109 +691,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.existing-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.existing-bucket.expected.json index fad104cc0..6aaa2e8cf 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.existing-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.existing-bucket.expected.json @@ -208,14 +208,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -560,109 +560,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.no-arguments.expected.json index e5b92cc7a..6fdb685d1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.no-arguments.expected.json @@ -471,14 +471,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -515,109 +515,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.no-security-headers.expected.json b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.no-security-headers.expected.json index aa73ded9b..495087c8b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.no-security-headers.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/integ.no-security-headers.expected.json @@ -561,14 +561,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -605,109 +605,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/test.cloudfront-s3.test.ts b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/test.cloudfront-s3.test.ts index c4e1ee100..156986af7 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/test.cloudfront-s3.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cloudfront-s3/test/test.cloudfront-s3.test.ts @@ -143,14 +143,11 @@ test('check properties', () => { const construct: CloudFrontToS3 = deploy(stack); - expect(construct.cloudFrontWebDistribution !== null); - expect(construct.s3Bucket !== null); + expect(construct.cloudFrontWebDistribution).toBeDefined(); + expect(construct.s3Bucket).toBeDefined(); }); -// -------------------------------------------------------------- -// Test bad call with existingBucket and bucketProps -// -------------------------------------------------------------- -test("Test bad call with existingBucket and bucketProps", () => { +test("Confirm CheckS3Props is called", () => { // Stack const stack = new cdk.Stack(); @@ -166,7 +163,7 @@ test("Test bad call with existingBucket and bucketProps", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); }); test("Test existingBucketObj", () => { @@ -176,7 +173,7 @@ test("Test existingBucketObj", () => { existingBucketObj: s3.Bucket.fromBucketName(stack, 'mybucket', 'mybucket') }); // Assertion - expect(construct.cloudFrontWebDistribution !== null); + expect(construct.cloudFrontWebDistribution).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::CloudFront::Distribution", { DistributionConfig: { @@ -249,9 +246,6 @@ test('test cloudfront with custom domain names', () => { }); }); -// -------------------------------------------------------------- -// s3 bucket with bucket, loggingBucket, and auto delete objects -// -------------------------------------------------------------- test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { const stack = new cdk.Stack(); @@ -285,9 +279,6 @@ test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { }); }); -// -------------------------------------------------------------- -// Cloudfront logging bucket with destroy removal policy and auto delete objects -// -------------------------------------------------------------- test('Cloudfront logging bucket with destroy removal policy and auto delete objects', () => { const stack = new cdk.Stack(); @@ -319,9 +310,6 @@ test('Cloudfront logging bucket with destroy removal policy and auto delete obje }); }); -// -------------------------------------------------------------- -// Cloudfront logging bucket error providing existing log bucket and logBucketProps -// -------------------------------------------------------------- test('Cloudfront logging bucket error when providing existing log bucket and logBucketProps', () => { const stack = new cdk.Stack(); const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {}); @@ -341,9 +329,6 @@ test('Cloudfront logging bucket error when providing existing log bucket and log expect(app).toThrowError(); }); -// -------------------------------------------------------------- -// s3 bucket with one content bucket and no logging bucket -// -------------------------------------------------------------- test('s3 bucket with one content bucket and no logging bucket', () => { const stack = new cdk.Stack(); @@ -359,9 +344,6 @@ test('s3 bucket with one content bucket and no logging bucket', () => { expect(construct.s3LoggingBucket).toEqual(undefined); }); -// -------------------------------------------------- -// CloudFront origin path -// -------------------------------------------------- test('CloudFront origin path present when provided', () => { const stack = new cdk.Stack(); @@ -460,3 +442,23 @@ test("throw exception if insertHttpSecurityHeaders and responseHeadersPolicyProp }); }).toThrowError(); }); + +test("Confirm CheckCloudFrontProps is being called", () => { + const stack = new cdk.Stack(); + + expect(() => { + new CloudFrontToS3(stack, "test-cloudfront-apigateway", { + insertHttpSecurityHeaders: true, + responseHeadersPolicyProps: { + securityHeadersBehavior: { + strictTransportSecurity: { + accessControlMaxAge: Duration.seconds(63072), + includeSubdomains: true, + override: false, + preload: true + } + } + } + }); + }).toThrowError('responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/lib/index.ts index efd18bc1f..47a97fec3 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/lib/index.ts @@ -81,7 +81,7 @@ export class CognitoToApiGatewayToLambda extends Construct { */ constructor(scope: Construct, id: string, props: CognitoToApiGatewayToLambdaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckLambdaProps(props); // This Construct requires that the auth type be COGNITO regardless of what is specified in the props if (props.apiGatewayProps) { @@ -98,7 +98,7 @@ export class CognitoToApiGatewayToLambda extends Construct { } if (props.apiGatewayProps && (typeof props.apiGatewayProps.proxy !== 'undefined') && (props.apiGatewayProps.proxy === false)) { - defaults.printWarning('For non-proxy API, addAuthorizers() method must be called after all the resources and methods for API are fuly defined. Not calling addAuthorizers() will result in API methods NOT protected by Cognito.'); + defaults.printWarning('For non-proxy API, addAuthorizers() method must be called after all the resources and methods for API are fully defined. Not calling addAuthorizers() will result in API methods NOT protected by Cognito.'); } this.lambdaFunction = defaults.buildLambdaFunction(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/test/integ.no-arguments.expected.json index d66815d6e..d2b8fd4b5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/test/integ.no-arguments.expected.json @@ -98,18 +98,18 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "testcognitoapigatewaylambdaLambdaFunctionServiceRole943D8510", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testcognitoapigatewaylambdaLambdaFunctionServiceRole943D8510", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -171,10 +171,10 @@ "testcognitoapigatewaylambdaLambdaRestApiDeployment96AFD8CA5d8e3257747e529ac6f9e48e8d20548e": { "Type": "AWS::ApiGateway::Deployment", "Properties": { + "Description": "Automatically created by the RestApi construct", "RestApiId": { "Ref": "testcognitoapigatewaylambdaLambdaRestApi2E272431" - }, - "Description": "Automatically created by the RestApi construct" + } }, "DependsOn": [ "testcognitoapigatewaylambdaLambdaRestApiproxyANY18BA6246", @@ -186,7 +186,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -195,9 +195,6 @@ "testcognitoapigatewaylambdaLambdaRestApiDeploymentStageprod850C17D1": { "Type": "AWS::ApiGateway::Stage", "Properties": { - "RestApiId": { - "Ref": "testcognitoapigatewaylambdaLambdaRestApi2E272431" - }, "AccessLogSetting": { "DestinationArn": { "Fn::GetAtt": [ @@ -218,6 +215,9 @@ "ResourcePath": "/*" } ], + "RestApiId": { + "Ref": "testcognitoapigatewaylambdaLambdaRestApi2E272431" + }, "StageName": "prod", "TracingEnabled": true } @@ -318,17 +318,11 @@ "testcognitoapigatewaylambdaLambdaRestApiproxyANY18BA6246": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Ref": "testcognitoapigatewaylambdaLambdaRestApiproxy23E1DA20" - }, - "RestApiId": { - "Ref": "testcognitoapigatewaylambdaLambdaRestApi2E272431" - }, "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { "Ref": "testcognitoapigatewaylambdaCognitoAuthorizer170CACC9" }, + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -355,6 +349,12 @@ ] ] } + }, + "ResourceId": { + "Ref": "testcognitoapigatewaylambdaLambdaRestApiproxy23E1DA20" + }, + "RestApiId": { + "Ref": "testcognitoapigatewaylambdaLambdaRestApi2E272431" } } }, @@ -439,20 +439,11 @@ "testcognitoapigatewaylambdaLambdaRestApiANY1BCFE40A": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Fn::GetAtt": [ - "testcognitoapigatewaylambdaLambdaRestApi2E272431", - "RootResourceId" - ] - }, - "RestApiId": { - "Ref": "testcognitoapigatewaylambdaLambdaRestApi2E272431" - }, "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { "Ref": "testcognitoapigatewaylambdaCognitoAuthorizer170CACC9" }, + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -479,6 +470,15 @@ ] ] } + }, + "ResourceId": { + "Fn::GetAtt": [ + "testcognitoapigatewaylambdaLambdaRestApi2E272431", + "RootResourceId" + ] + }, + "RestApiId": { + "Ref": "testcognitoapigatewaylambdaLambdaRestApi2E272431" } } }, @@ -608,9 +608,6 @@ "testcognitoapigatewaylambdaCognitoUserPoolClientDA118627": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testcognitoapigatewaylambdaCognitoUserPoolD5E74489" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -628,18 +625,17 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testcognitoapigatewaylambdaCognitoUserPoolD5E74489" + } } }, "testcognitoapigatewaylambdaCognitoAuthorizer170CACC9": { "Type": "AWS::ApiGateway::Authorizer", "Properties": { - "Name": "authorizer", - "RestApiId": { - "Ref": "testcognitoapigatewaylambdaLambdaRestApi2E272431" - }, - "Type": "COGNITO_USER_POOLS", "IdentitySource": "method.request.header.Authorization", + "Name": "authorizer", "ProviderARNs": [ { "Fn::GetAtt": [ @@ -647,7 +643,11 @@ "Arn" ] } - ] + ], + "RestApiId": { + "Ref": "testcognitoapigatewaylambdaLambdaRestApi2E272431" + }, + "Type": "COGNITO_USER_POOLS" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/test/test.cognito-apigateway-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/test/test.cognito-apigateway-lambda.test.ts index 0c9055654..1628f0026 100644 --- a/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/test/test.cognito-apigateway-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-cognito-apigateway-lambda/test/test.cognito-apigateway-lambda.test.ts @@ -89,13 +89,13 @@ test('check properties', () => { const construct: CognitoToApiGatewayToLambda = deployNewFunc(stack); - expect(construct.userPool !== null); - expect(construct.userPoolClient !== null); - expect(construct.apiGateway !== null); - expect(construct.lambdaFunction !== null); - expect(construct.apiGatewayCloudWatchRole !== null); - expect(construct.apiGatewayLogGroup !== null); - expect(construct.apiGatewayAuthorizer !== null); + expect(construct.userPool).toBeDefined(); + expect(construct.userPoolClient).toBeDefined(); + expect(construct.apiGateway).toBeDefined(); + expect(construct.lambdaFunction).toBeDefined(); + expect(construct.apiGatewayCloudWatchRole).toBeDefined(); + expect(construct.apiGatewayLogGroup).toBeDefined(); + expect(construct.apiGatewayAuthorizer).toBeDefined(); }); test('override cognito cognitoUserPoolClientProps', () => { @@ -385,7 +385,7 @@ test('Override apiGatewayProps with proxy = false and add POST method', () => { const r = c.apiGateway.root.addResource('foo'); r.addMethod('POST'); - // Super imporant to call this method to Apply the Cognito Authorizers + // Super important to call this method to Apply the Cognito Authorizers c.addAuthorizers(); const template = Template.fromStack(stack); @@ -439,4 +439,27 @@ test('Override apiGatewayProps with proxy = false and add OPTIONS method', () => template.hasResourceProperties('AWS::ApiGateway::Resource', { PathPart: "foo", }); -}); \ No newline at end of file +}); + +test('Confirm CheckLambdaProps is being called', () => { + const stack = new cdk.Stack(); + const existingLambdaObj = new lambda.Function(stack, 'ExistingLambda', { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: CognitoToApiGatewayToLambdaProps = { + existingLambdaObj, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + } + }; + + const app = () => { + new CognitoToApiGatewayToLambda(stack, 'test-cognito-apigateway-lambda', props); + }; + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/README.md b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/README.md index b23bd82eb..c3805fa70 100755 --- a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/README.md @@ -117,7 +117,7 @@ new DynamoDBStreamsToLambdaToElasticSearchAndKibana(this, "test-dynamodb-stream- |createCloudWatchAlarms?|`boolean`|Whether to create recommended CloudWatch alarms| | existingVpc? | [`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An existing VPC in which to deploy the construct. Providing both this and `vpcProps` is an error.| | deployVpc? |`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| -| vpcProps? |[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the Construct, so any values for those properties supplied here will be overrriden. If `deployVpc?` is not `true` then this property will be ignored. | +| vpcProps? |[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the Construct, so any values for those properties supplied here will be overridden. If `deployVpc?` is not `true` then this property will be ignored. | ## Pattern Properties @@ -172,4 +172,4 @@ Out of the box implementation of the Construct without any override will set the ![Architecture Diagram](architecture.png) *** -© Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. \ No newline at end of file +© Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/lib/index.ts index d2bf5e038..ac6aa517b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/lib/index.ts @@ -24,7 +24,6 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as sqs from 'aws-cdk-lib/aws-sqs'; // Note: To ensure CDKv2 compatibility, keep the import statement for Construct separate import { Construct } from 'constructs'; -import * as defaults from '@aws-solutions-constructs/core'; /** * @summary The properties for the DynamoDBStreamsToLambdaToElastciSearchAndKibana Construct @@ -140,7 +139,7 @@ export class DynamoDBStreamsToLambdaToElasticSearchAndKibana extends Construct { */ constructor(scope: Construct, id: string, props: DynamoDBStreamsToLambdaToElasticSearchAndKibanaProps) { super(scope, id); - defaults.CheckProps(props); + // CheckLambdaProps() is called by aws-lambda-elasticsearch const lambdaToElasticSearchProps: LambdaToElasticSearchAndKibanaProps = { existingLambdaObj: props.existingLambdaObj, diff --git a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/dynamodbstreams-lambda-elasticsearch-kibana.test.ts b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/dynamodbstreams-lambda-elasticsearch-kibana.test.ts index 5ebf9de4e..d273f24f0 100644 --- a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/dynamodbstreams-lambda-elasticsearch-kibana.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/dynamodbstreams-lambda-elasticsearch-kibana.test.ts @@ -58,14 +58,14 @@ test('check properties', () => { const construct: DynamoDBStreamsToLambdaToElasticSearchAndKibana = deployNewFunc(stack); - expect(construct.lambdaFunction !== null); - expect(construct.dynamoTable !== null); - expect(construct.elasticsearchDomain !== null); - expect(construct.elasticsearchRole !== null); - expect(construct.identityPool !== null); - expect(construct.userPool !== null); - expect(construct.userPoolClient !== null); - expect(construct.cloudwatchAlarms !== null); + expect(construct.lambdaFunction).toBeDefined(); + expect(construct.dynamoTable).toBeDefined(); + expect(construct.elasticsearchDomain).toBeDefined(); + expect(construct.elasticsearchRole).toBeDefined(); + expect(construct.identityPool).toBeDefined(); + expect(construct.userPool).toBeDefined(); + expect(construct.userPoolClient).toBeDefined(); + expect(construct.cloudwatchAlarms).toBeDefined(); }); test('check exception for Missing existingObj from props for deploy = false', () => { @@ -226,4 +226,46 @@ test('Test minimal deployment with an existing isolated VPC', () => { template.resourceCountIs("AWS::EC2::VPC", 1); expect(construct.vpc).toBeDefined(); -}); \ No newline at end of file +}); + +test('Confirm CheckVpcProps is being called', () => { + const stack = new cdk.Stack(); + + const app = () => { + new DynamoDBStreamsToLambdaToElasticSearchAndKibana(stack, 'test-construct', { + lambdaFunctionProps: getDefaultTestLambdaProps(), + domainName: "test", + deployVpc: true, + vpcProps: { + vpcName: "existing-vpc-test" + }, + existingVpc: defaults.getTestVpc(stack), + }); + }; + + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm CheckLambdaProps is being called', () => { + const stack = new cdk.Stack(); + const existingLambdaObj = new lambda.Function(stack, 'ExistingLambda', { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: DynamoDBStreamsToLambdaToElasticSearchAndKibanaProps = { + domainName: 'test-name', + existingLambdaObj, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + } + }; + + const app = () => { + new DynamoDBStreamsToLambdaToElasticSearchAndKibana(stack, 'test-apigateway-lambda', props); + }; + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/integ.deploy-with-vpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/integ.deploy-with-vpc.expected.json index 5eab067ed..ff8d022f8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/integ.deploy-with-vpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/integ.deploy-with-vpc.expected.json @@ -172,12 +172,6 @@ }, "S3Key": "92927de5fcc3aea277bddecb845bee318fb502f7375daedbdafb72c0400bc197.zip" }, - "Role": { - "Fn::GetAtt": [ - "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionServiceRoleEC11512B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -190,6 +184,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionServiceRoleEC11512B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -245,9 +245,6 @@ "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionDynamoDBEventSourcedeploywithvpctestddbstreamslambdaeskDynamoDBStreamsToLambdaDynamoTableB7F9F75CD09B2055": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionB70B7296" - }, "BatchSize": 100, "BisectBatchOnFunctionError": true, "DestinationConfig": { @@ -266,6 +263,9 @@ "StreamArn" ] }, + "FunctionName": { + "Ref": "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionB70B7296" + }, "MaximumRecordAgeInSeconds": 86400, "MaximumRetryAttempts": 500, "StartingPosition": "TRIM_HORIZON" @@ -313,9 +313,6 @@ "testddbstreamslambdaeskLambdaToElasticSearchCognitoUserPoolClient25D50E3D": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testddbstreamslambdaeskLambdaToElasticSearchCognitoUserPool97EA2952" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -333,7 +330,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testddbstreamslambdaeskLambdaToElasticSearchCognitoUserPool97EA2952" + } } }, "testddbstreamslambdaeskLambdaToElasticSearchCognitoIdentityPoolFAA4D969": { @@ -692,9 +692,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchStatusRedAlarmAFFE3439": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -705,9 +705,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchStatusYellowAlarm44E1DC4E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -718,9 +718,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchFreeStorageSpaceTooLowAlarm65BF7F2F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -731,9 +731,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchIndexWritesBlockedTooHighAlarmCE3D0C51": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -744,9 +744,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchAutomatedSnapshotFailureTooHighAlarmFD8E066E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -757,9 +757,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchCPUUtilizationTooHighAlarm274094A6": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -770,9 +770,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchJVMMemoryPressureTooHighAlarm2E49D5CC": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -783,9 +783,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchMasterCPUUtilizationTooHighAlarm05E1EBEF": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -796,9 +796,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchMasterJVMMemoryPressureTooHighAlarm1090161B": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -824,9 +824,6 @@ "testddbstreamslambdaeskVpcisolatedSubnet1Subnet3A238B01": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "testddbstreamslambdaeskVpcB583E197" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -843,21 +840,24 @@ "Key": "Name", "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "testddbstreamslambdaeskVpcB583E197" + } } }, "testddbstreamslambdaeskVpcisolatedSubnet1RouteTable27ABBE41": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "testddbstreamslambdaeskVpcB583E197" - }, "Tags": [ { "Key": "Name", "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "testddbstreamslambdaeskVpcB583E197" + } } }, "testddbstreamslambdaeskVpcisolatedSubnet1RouteTableAssociation2E533936": { @@ -874,9 +874,6 @@ "testddbstreamslambdaeskVpcisolatedSubnet2SubnetDE9E844E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "testddbstreamslambdaeskVpcB583E197" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -893,21 +890,24 @@ "Key": "Name", "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "testddbstreamslambdaeskVpcB583E197" + } } }, "testddbstreamslambdaeskVpcisolatedSubnet2RouteTable358580C2": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "testddbstreamslambdaeskVpcB583E197" - }, "Tags": [ { "Key": "Name", "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "testddbstreamslambdaeskVpcB583E197" + } } }, "testddbstreamslambdaeskVpcisolatedSubnet2RouteTableAssociation77A663A5": { @@ -924,9 +924,6 @@ "testddbstreamslambdaeskVpcisolatedSubnet3Subnet3B5285ED": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "testddbstreamslambdaeskVpcB583E197" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -943,21 +940,24 @@ "Key": "Name", "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "testddbstreamslambdaeskVpcB583E197" + } } }, "testddbstreamslambdaeskVpcisolatedSubnet3RouteTable7F8548D9": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "testddbstreamslambdaeskVpcB583E197" - }, "Tags": [ { "Key": "Name", "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "testddbstreamslambdaeskVpcB583E197" + } } }, "testddbstreamslambdaeskVpcisolatedSubnet3RouteTableAssociation77FF5F32": { @@ -989,7 +989,7 @@ "Tags": [ { "Key": "Name", - "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc" + "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc/FlowLog" } ] } @@ -1041,7 +1041,7 @@ "Tags": [ { "Key": "Name", - "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc" + "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc/FlowLog" } ] }, @@ -1061,10 +1061,6 @@ "testddbstreamslambdaeskVpcFlowLogD9278B4C": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "testddbstreamslambdaeskVpcB583E197" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "testddbstreamslambdaeskVpcFlowLogIAMRole8B3A466E", @@ -1075,10 +1071,14 @@ "LogGroupName": { "Ref": "testddbstreamslambdaeskVpcFlowLogLogGroup4DB5270C" }, + "ResourceId": { + "Ref": "testddbstreamslambdaeskVpcB583E197" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc" + "Value": "deploy-with-vpc/test-ddbstreams-lambda-esk/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -1087,19 +1087,19 @@ "testddbstreamslambdaeskDynamoDBStreamsToLambdaDynamoTableDD18004A": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, diff --git a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/integ.no-arguments.expected.json index aee329669..e1a92f7b7 100644 --- a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda-elasticsearch-kibana/test/integ.no-arguments.expected.json @@ -131,12 +131,6 @@ }, "S3Key": "92927de5fcc3aea277bddecb845bee318fb502f7375daedbdafb72c0400bc197.zip" }, - "Role": { - "Fn::GetAtt": [ - "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionServiceRoleEC11512B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -149,6 +143,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionServiceRoleEC11512B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -180,9 +180,6 @@ "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionDynamoDBEventSourcenoargumentstestddbstreamslambdaeskDynamoDBStreamsToLambdaDynamoTable6C5773679DA39002": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionB70B7296" - }, "BatchSize": 100, "BisectBatchOnFunctionError": true, "DestinationConfig": { @@ -201,6 +198,9 @@ "StreamArn" ] }, + "FunctionName": { + "Ref": "testddbstreamslambdaeskLambdaToElasticSearchLambdaFunctionB70B7296" + }, "MaximumRecordAgeInSeconds": 86400, "MaximumRetryAttempts": 500, "StartingPosition": "TRIM_HORIZON" @@ -243,9 +243,6 @@ "testddbstreamslambdaeskLambdaToElasticSearchCognitoUserPoolClient25D50E3D": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testddbstreamslambdaeskLambdaToElasticSearchCognitoUserPool97EA2952" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -263,7 +260,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testddbstreamslambdaeskLambdaToElasticSearchCognitoUserPool97EA2952" + } } }, "testddbstreamslambdaeskLambdaToElasticSearchCognitoIdentityPoolFAA4D969": { @@ -601,9 +601,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchStatusRedAlarmAFFE3439": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -614,9 +614,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchStatusYellowAlarm44E1DC4E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -627,9 +627,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchFreeStorageSpaceTooLowAlarm65BF7F2F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -640,9 +640,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchIndexWritesBlockedTooHighAlarmCE3D0C51": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -653,9 +653,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchAutomatedSnapshotFailureTooHighAlarmFD8E066E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -666,9 +666,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchCPUUtilizationTooHighAlarm274094A6": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -679,9 +679,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchJVMMemoryPressureTooHighAlarm2E49D5CC": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -692,9 +692,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchMasterCPUUtilizationTooHighAlarm05E1EBEF": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -705,9 +705,9 @@ "testddbstreamslambdaeskLambdaToElasticSearchMasterJVMMemoryPressureTooHighAlarm1090161B": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -718,19 +718,19 @@ "testddbstreamslambdaeskDynamoDBStreamsToLambdaDynamoTableDD18004A": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, diff --git a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda/lib/index.ts index af0077d73..d51bbb62e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda/lib/index.ts @@ -82,7 +82,7 @@ export class DynamoDBStreamsToLambda extends Construct { */ constructor(scope: Construct, id: string, props: DynamoDBStreamsToLambdaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckLambdaProps(props); this.lambdaFunction = defaults.buildLambdaFunction(this, { existingLambdaObj: props.existingLambdaObj, diff --git a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda/test/dynamodbstreams-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda/test/dynamodbstreams-lambda.test.ts index 35f54094e..c6922d01a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda/test/dynamodbstreams-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-dynamodbstreams-lambda/test/dynamodbstreams-lambda.test.ts @@ -294,3 +294,27 @@ test('check dynamodb table stream override with ITable', () => { } }); }); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: DynamoDBStreamsToLambdaProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new DynamoDBStreamsToLambda(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/README.md b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/README.md index feef1a2c2..b0ab28d7c 100755 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/README.md @@ -87,7 +87,8 @@ new EventbridgeToKinesisFirehoseToS3(this, "test-eventbridge-firehose-s3", |loggingBucketProps?|[`s3.BucketProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html)|Optional user provided props to override the default props for the S3 Logging Bucket.| |logS3AccessLogs?| boolean|Whether to turn on Access Logging for the S3 bucket. Creates an S3 bucket with associated storage costs for the logs. Enabling Access Logging is a best practice. default - true| -NOTE: `existingLoggingBucketObj` has been deprecated - to specify an existing Log Bucket, use bucketProps.serverAccessLogsBucket +NOTE: `existingLoggingBucketObj` has been deprecated - to specify an existing Log Bucket, use `bucketProps.serverAccessLogsBucket`. + ## Pattern Properties | **Name** | **Type** | **Description** | diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/lib/index.ts index 00e634d20..ed747969a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/lib/index.ts @@ -108,7 +108,8 @@ export class EventbridgeToKinesisFirehoseToS3 extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); + defaults.CheckEventBridgeProps(props); + // CheckS3Props is called by internal aws-kinesisfirehose-s3 construct // Set up the Kinesis Firehose using KinesisFirehoseToS3 construct const firehoseToS3 = new KinesisFirehoseToS3(this, 'KinesisFirehoseToS3', { diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/test/eventbridge-kinesisfirehose-s3.test.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/test/eventbridge-kinesisfirehose-s3.test.ts index d6cd33a6f..908783b5c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/test/eventbridge-kinesisfirehose-s3.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/test/eventbridge-kinesisfirehose-s3.test.ts @@ -18,9 +18,6 @@ import { Template } from 'aws-cdk-lib/assertions'; import { EventbridgeToKinesisFirehoseToS3, EventbridgeToKinesisFirehoseToS3Props } from '../lib'; import * as defaults from '@aws-solutions-constructs/core'; -// -------------------------------------------------------------- -// Test snapshot match with default parameters -// -------------------------------------------------------------- function deployNewStack(stack: cdk.Stack) { const props: EventbridgeToKinesisFirehoseToS3Props = { eventRuleProps: { @@ -31,26 +28,20 @@ function deployNewStack(stack: cdk.Stack) { return new EventbridgeToKinesisFirehoseToS3(stack, 'test-eventbridge-kinesis-firehose-s3-default-parameters', props); } -// -------------------------------------------------------------- -// Test properties -// -------------------------------------------------------------- test('Test properties', () => { const stack = new cdk.Stack(); const construct: EventbridgeToKinesisFirehoseToS3 = deployNewStack(stack); // Assertions - expect(construct.eventsRule !== null); - expect(construct.eventsRole !== null); - expect(construct.kinesisFirehose !== null); - expect(construct.kinesisFirehoseRole !== null); - expect(construct.kinesisFirehoseLogGroup !== null); - expect(construct.s3Bucket !== null); - expect(construct.s3LoggingBucket !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.eventsRole).toBeDefined(); + expect(construct.kinesisFirehose).toBeDefined(); + expect(construct.kinesisFirehoseRole).toBeDefined(); + expect(construct.kinesisFirehoseLogGroup).toBeDefined(); + expect(construct.s3Bucket).toBeDefined(); + expect(construct.s3LoggingBucket).toBeDefined(); }); -// -------------------------------------------------------------- -// Test default server side s3 bucket encryption -// -------------------------------------------------------------- test('Test default server side s3 bucket encryption', () => { const stack = new cdk.Stack(); deployNewStack(stack); @@ -70,9 +61,6 @@ test('Test default server side s3 bucket encryption', () => { }); }); -// -------------------------------------------------------------- -// Test property override -// -------------------------------------------------------------- test('Test property override', () => { const stack = new cdk.Stack(); @@ -120,9 +108,6 @@ test('Test property override', () => { }}); }); -// -------------------------------------------------------------- -// Test bad call with existingBucket and bucketProps -// -------------------------------------------------------------- test("Test bad call with existingBucket and bucketProps", () => { // Stack const stack = new cdk.Stack(); @@ -143,7 +128,7 @@ test("Test bad call with existingBucket and bucketProps", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); }); test('check eventbus property, snapshot & eventbus exists', () => { @@ -159,20 +144,20 @@ test('check eventbus property, snapshot & eventbus exists', () => { }; const construct = new EventbridgeToKinesisFirehoseToS3(stack, 'test-eventbridge-kinesis-firehose-default-parameters', props); - expect(construct.eventsRule !== null); - expect(construct.eventsRole !== null); - expect(construct.kinesisFirehose !== null); - expect(construct.kinesisFirehoseRole !== null); - expect(construct.kinesisFirehoseLogGroup !== null); - expect(construct.s3Bucket !== null); - expect(construct.s3LoggingBucket !== null); - expect(construct.eventBus !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.eventsRole).toBeDefined(); + expect(construct.kinesisFirehose).toBeDefined(); + expect(construct.kinesisFirehoseRole).toBeDefined(); + expect(construct.kinesisFirehoseLogGroup).toBeDefined(); + expect(construct.s3Bucket).toBeDefined(); + expect(construct.s3LoggingBucket).toBeDefined(); + expect(construct.eventBus).toBeDefined(); // Check whether eventbus exists const template = Template.fromStack(stack); template.resourceCountIs('AWS::Events::EventBus', 1); }); -test('check exception while passing existingEventBus & eventBusProps', () => { +test('Confirm CheckEventBridgeProps is being called', () => { const stack = new cdk.Stack(); const props: EventbridgeToKinesisFirehoseToS3Props = { @@ -186,9 +171,9 @@ test('check exception while passing existingEventBus & eventBusProps', () => { }; const app = () => { - new EventbridgeToKinesisFirehoseToS3(stack, 'test-eventbridge-firehose', props); + new EventbridgeToKinesisFirehoseToS3(stack, 'test-eventbridge-firehose-s3', props); }; - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'); }); test('check custom event bus resource with props when deploy:true', () => { @@ -212,9 +197,6 @@ test('check custom event bus resource with props when deploy:true', () => { }); }); -// -------------------------------------------------------------- -// s3 bucket with bucket, loggingBucket, and auto delete objects -// -------------------------------------------------------------- test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { const stack = new cdk.Stack(); @@ -248,9 +230,6 @@ test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { }); }); -// -------------------------------------------------------------- -// s3 bucket with one content bucket and no logging bucket -// -------------------------------------------------------------- test('s3 bucket with one content bucket and no logging bucket', () => { const stack = new cdk.Stack(); @@ -291,3 +270,23 @@ test('Supply an existing logging bucket', () => { template.resourceCountIs("AWS::S3::Bucket", 2); }); + +test('Confirm CheckS3Props is being called', () => { + // For L4 constructs, the call is within the internal L3 constructs + const stack = new cdk.Stack(); + + const props: EventbridgeToKinesisFirehoseToS3Props = { + eventRuleProps: { + eventPattern: { + source: ['solutionsconstructs'] + } + }, + bucketProps: {}, + existingBucketObj: new s3.Bucket(stack, 'test-bucket', {}), + }; + + const app = () => { + new EventbridgeToKinesisFirehoseToS3(stack, 'test-eventbridge-firehose-s3', props); + }; + expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/test/integ.existingLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/test/integ.existingLoggingBucket.expected.json index 1112c6531..8a3494f26 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/test/integ.existingLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisfirehose-s3/test/integ.existingLoggingBucket.expected.json @@ -182,14 +182,14 @@ }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -574,109 +574,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisstreams/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisstreams/lib/index.ts index 032c40f94..3709a4a76 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisstreams/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisstreams/lib/index.ts @@ -78,7 +78,8 @@ export class EventbridgeToKinesisStreams extends Construct { */ constructor(scope: Construct, id: string, props: EventbridgeToKinesisStreamsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckEventBridgeProps(props); + defaults.CheckKinesisStreamProps(props); // Set up the Kinesis Stream this.kinesisStream = defaults.buildKinesisStream(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisstreams/test/eventbridge-kinesisstreams.test.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisstreams/test/eventbridge-kinesisstreams.test.ts index 8ff33ec52..475f78045 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisstreams/test/eventbridge-kinesisstreams.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-kinesisstreams/test/eventbridge-kinesisstreams.test.ts @@ -17,9 +17,6 @@ import * as kinesis from 'aws-cdk-lib/aws-kinesis'; import { Template } from "aws-cdk-lib/assertions"; import {EventbridgeToKinesisStreams, EventbridgeToKinesisStreamsProps} from '../lib'; -// -------------------------------------------------------------- -// Test snapshot match with default parameters -// -------------------------------------------------------------- function deployNewStack(stack: cdk.Stack) { const props: EventbridgeToKinesisStreamsProps = { eventRuleProps: { @@ -30,22 +27,16 @@ function deployNewStack(stack: cdk.Stack) { return new EventbridgeToKinesisStreams(stack, 'test-eventbridge-kinesis-streams-default-parameters', props); } -// -------------------------------------------------------------- -// Test properties -// -------------------------------------------------------------- test('Test properties', () => { const stack = new cdk.Stack(); const construct: EventbridgeToKinesisStreams = deployNewStack(stack); // Assertions - expect(construct.eventsRule !== null); - expect(construct.kinesisStream !== null); - expect(construct.eventsRole !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.kinesisStream).toBeDefined(); + expect(construct.eventsRole).toBeDefined(); }); -// -------------------------------------------------------------- -// Test default AWS managed encryption key property -// -------------------------------------------------------------- test('Test default AWS managed encryption key property', () => { const stack = new cdk.Stack(); deployNewStack(stack); @@ -60,9 +51,6 @@ test('Test default AWS managed encryption key property', () => { }); }); -// -------------------------------------------------------------- -// Test existing resources -// -------------------------------------------------------------- test('Test existing resources', () => { const stack = new cdk.Stack(); @@ -103,10 +91,10 @@ test('check eventbus property, snapshot & eventbus exists', () => { }; const construct = new EventbridgeToKinesisStreams(stack, 'test-eventbridge-kinesis-streams-default-parameters', props); - expect(construct.eventsRule !== null); - expect(construct.kinesisStream !== null); - expect(construct.eventsRole !== null); - expect(construct.eventBus !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.kinesisStream).toBeDefined(); + expect(construct.eventsRole).toBeDefined(); + expect(construct.eventBus).toBeDefined(); // Check whether eventbus exists const template = Template.fromStack(stack); template.resourceCountIs('AWS::Events::EventBus', 1); @@ -128,7 +116,7 @@ test('check exception while passing existingEventBus & eventBusProps', () => { const app = () => { new EventbridgeToKinesisStreams(stack, 'test-eventbridge-kinesisstreams', props); }; - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'); }); test('check custom event bus resource with props when deploy:true', () => { @@ -150,4 +138,23 @@ test('check custom event bus resource with props when deploy:true', () => { template.hasResourceProperties('AWS::Events::EventBus', { Name: `testeventbus` }); -}); \ No newline at end of file +}); + +test('Confirm that CheckKinesisStreamProps is called', () => { + const stack = new cdk.Stack(); + + const props: EventbridgeToKinesisStreamsProps = { + eventRuleProps: { + eventPattern: { + source: ['solutionsconstructs'] + } + }, + existingStreamObj: new kinesis.Stream(stack, 'test', {}), + kinesisStreamProps: {} + }; + + const app = () => { + new EventbridgeToKinesisStreams(stack, 'test-eventbridge-kinesisstreams', props); + }; + expect(app).toThrowError(); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/lib/index.ts index 0594a5da4..c4b12a8c5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/lib/index.ts @@ -69,7 +69,8 @@ export class EventbridgeToLambda extends Construct { */ constructor(scope: Construct, id: string, props: EventbridgeToLambdaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckLambdaProps(props); + defaults.CheckEventBridgeProps(props); this.lambdaFunction = defaults.buildLambdaFunction(this, { existingLambdaObj: props.existingLambdaObj, diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/eventbridge-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/eventbridge-lambda.test.ts index b57b2c0a0..d9699e8fc 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/eventbridge-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/eventbridge-lambda.test.ts @@ -184,8 +184,8 @@ test('check properties', () => { const construct: EventbridgeToLambda = deployNewFunc(stack); - expect(construct.eventsRule !== null); - expect(construct.lambdaFunction !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.lambdaFunction).toBeDefined(); }); test('check exception for Missing existingObj from props', () => { @@ -209,15 +209,15 @@ test('check eventbus property, snapshot & eventbus exists', () => { const construct: EventbridgeToLambda = deployNewEventBus(stack); - expect(construct.eventsRule !== null); - expect(construct.lambdaFunction !== null); - expect(construct.eventBus !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.lambdaFunction).toBeDefined(); + expect(construct.eventBus).toBeDefined(); // Check whether eventbus exists const template = Template.fromStack(stack); template.resourceCountIs('AWS::Events::EventBus', 1); }); -test('check exception while passing existingEventBus & eventBusProps', () => { +test('check custom event bus resource with props when deploy:true', () => { const stack = new cdk.Stack(); const props: EventbridgeToLambdaProps = { @@ -226,22 +226,53 @@ test('check exception while passing existingEventBus & eventBusProps', () => { runtime: lambda.Runtime.NODEJS_16_X, handler: 'index.handler' }, + eventBusProps: { + eventBusName: `testeventbus` + }, eventRuleProps: { eventPattern: { source: ['solutionsconstructs'] } - }, - eventBusProps: { eventBusName: 'test' }, - existingEventBusInterface: new events.EventBus(stack, `test-existing-eventbus`, { eventBusName: 'test' }) + } }; + new EventbridgeToLambda(stack, 'test-new-eventbridge-with-props-lambda', props); + + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::Events::EventBus', { + Name: `testeventbus` + }); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + const props: EventbridgeToLambdaProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + eventRuleProps: { + eventPattern: { + source: ['solutionsconstructs'] + } + }, + existingLambdaObj: lambdaFunction, + }; const app = () => { - new EventbridgeToLambda(stack, 'test-eventbridge-lambda', props); + new EventbridgeToLambda(stack, 'test-construct', props); }; - expect(app).toThrowError(); + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); }); -test('check custom event bus resource with props when deploy:true', () => { +test('Confirm CheckEventBridgeProps is being called', () => { const stack = new cdk.Stack(); const props: EventbridgeToLambdaProps = { @@ -250,19 +281,17 @@ test('check custom event bus resource with props when deploy:true', () => { runtime: lambda.Runtime.NODEJS_16_X, handler: 'index.handler' }, - eventBusProps: { - eventBusName: `testeventbus` - }, eventRuleProps: { eventPattern: { source: ['solutionsconstructs'] } - } + }, + eventBusProps: { eventBusName: 'test' }, + existingEventBusInterface: new events.EventBus(stack, `test-existing-eventbus`, { eventBusName: 'test' }) }; - new EventbridgeToLambda(stack, 'test-new-eventbridge-with-props-lambda', props); - const template = Template.fromStack(stack); - template.hasResourceProperties('AWS::Events::EventBus', { - Name: `testeventbus` - }); -}); \ No newline at end of file + const app = () => { + new EventbridgeToLambda(stack, 'test-eventbridge-lambda', props); + }; + expect(app).toThrowError('Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-existing-eventbus.expected.json b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-existing-eventbus.expected.json index 4117f3456..a3ee4a61f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-existing-eventbus.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-existing-eventbus.expected.json @@ -3,7 +3,7 @@ "existingeventbusA5B80487": { "Type": "AWS::Events::EventBus", "Properties": { - "Name": "test" + "Name": "test-existing-lambda" } }, "testeventbridgelambdaLambdaFunctionServiceRole6D02CEEE": { @@ -104,18 +104,18 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "testeventbridgelambdaLambdaFunctionServiceRole6D02CEEE", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testeventbridgelambdaLambdaFunctionServiceRole6D02CEEE", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-existing-eventbus.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-existing-eventbus.ts index 6289de86e..18126b108 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-existing-eventbus.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-existing-eventbus.ts @@ -21,7 +21,7 @@ import { generateIntegStackName } from '@aws-solutions-constructs/core'; const app = new App(); const stack = new Stack(app, generateIntegStackName(__filename)); -const existingEventBus = new events.EventBus(stack, `existing-event-bus`, { eventBusName: 'test' }); +const existingEventBus = new events.EventBus(stack, `existing-event-bus`, { eventBusName: 'test-existing-lambda' }); const props: EventbridgeToLambdaProps = { lambdaFunctionProps: { diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-new-eventbus.expected.json b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-new-eventbus.expected.json index bdf10e99d..0090e1e2d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-new-eventbus.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-new-eventbus.expected.json @@ -98,18 +98,18 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "testeventbridgelambdaLambdaFunctionServiceRole6D02CEEE", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testeventbridgelambdaLambdaFunctionServiceRole6D02CEEE", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -157,17 +157,17 @@ } } }, - "testeventbridgelambdatest2F604440": { + "testeventbridgelambdatestnewlambdaA726ECBB": { "Type": "AWS::Events::EventBus", "Properties": { - "Name": "test" + "Name": "test-new-lambda" } }, "testeventbridgelambdaEventsRule7DB0954D": { "Type": "AWS::Events::Rule", "Properties": { "EventBusName": { - "Ref": "testeventbridgelambdatest2F604440" + "Ref": "testeventbridgelambdatestnewlambdaA726ECBB" }, "EventPattern": { "source": [ diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-new-eventbus.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-new-eventbus.ts index f1af26381..adf01d17c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-new-eventbus.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-new-eventbus.ts @@ -26,7 +26,7 @@ const props: EventbridgeToLambdaProps = { runtime: lambda.Runtime.NODEJS_16_X, handler: 'index.handler' }, - eventBusProps: { eventBusName: 'test' }, + eventBusProps: { eventBusName: 'test-new-lambda' }, eventRuleProps: { eventPattern: { source: ['solutionsconstructs'] diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-no-argument.expected.json b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-no-argument.expected.json index 42bbbcb11..f5018b3b4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-no-argument.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-lambda/test/integ.eventbridge-no-argument.expected.json @@ -98,18 +98,18 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "testeventbridgelambdaLambdaFunctionServiceRole6D02CEEE", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testeventbridgelambdaLambdaFunctionServiceRole6D02CEEE", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-sns/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-sns/lib/index.ts index 4f4c50a05..16f117634 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-sns/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-sns/lib/index.ts @@ -87,7 +87,8 @@ export class EventbridgeToSns extends Construct { */ constructor(scope: Construct, id: string, props: EventbridgeToSnsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckSnsProps(props); + defaults.CheckEventBridgeProps(props); let enableEncryptionParam = props.enableEncryptionWithCustomerManagedKey; if (props.enableEncryptionWithCustomerManagedKey === undefined || diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-sns/test/eventbridge-sns-topic.test.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-sns/test/eventbridge-sns-topic.test.ts index 9c42d25e8..7e967141a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-sns/test/eventbridge-sns-topic.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-sns/test/eventbridge-sns-topic.test.ts @@ -169,9 +169,9 @@ test('check properties', () => { const stack = new cdk.Stack(); const construct: EventbridgeToSns = deployNewStack(stack); - expect(construct.eventsRule !== null); - expect(construct.snsTopic !== null); - expect(construct.encryptionKey !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.snsTopic).toBeDefined(); + expect(construct.encryptionKey).toBeDefined(); }); test('check the sns topic properties', () => { @@ -224,17 +224,17 @@ test('check eventbus property, snapshot & eventbus exists', () => { const construct: EventbridgeToSns = deployStackWithNewEventBus(stack); - expect(construct.eventsRule !== null); - expect(construct.snsTopic !== null); - expect(construct.encryptionKey !== null); - expect(construct.eventBus !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.snsTopic).toBeDefined(); + expect(construct.encryptionKey).toBeDefined(); + expect(construct.eventBus).toBeDefined(); // Check whether eventbus exists const template = Template.fromStack(stack); template.resourceCountIs('AWS::Events::EventBus', 1); }); -test('check exception while passing existingEventBus & eventBusProps', () => { +test('Confirm CheckEventBridgeProps is being called', () => { const stack = new cdk.Stack(); const props: EventbridgeToSnsProps = { @@ -250,7 +250,7 @@ test('check exception while passing existingEventBus & eventBusProps', () => { const app = () => { new EventbridgeToSns(stack, 'test-eventbridge-sns', props); }; - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'); }); test('check custom event bus resource with props when deploy:true', () => { @@ -390,4 +390,24 @@ test('Properties correctly set when unencrypted existing topic is provided', () expect(testConstruct.snsTopic).toBeDefined(); expect(testConstruct.encryptionKey).not.toBeDefined(); +}); + +test('Confirm CheckSnsProps is being called', () => { + const stack = new cdk.Stack(); + const existingTopicObj = new sns.Topic(stack, 'Topic', { + topicName: 'existing-topic-name' + }); + + const props: EventbridgeToSnsProps = { + existingTopicObj, + topicProps: {}, + eventRuleProps: { + schedule: events.Schedule.rate(cdk.Duration.minutes(5)) + } + }; + const app = () => { + new EventbridgeToSns(stack, 'test', props); + }; + + expect(app).toThrowError("Error - Either provide topicProps or existingTopicObj, but not both.\n"); }); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-sqs/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-sqs/lib/index.ts index 9d9aae2a8..835884662 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-sqs/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-sqs/lib/index.ts @@ -116,7 +116,8 @@ export class EventbridgeToSqs extends Construct { */ constructor(scope: Construct, id: string, props: EventbridgeToSqsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckSqsProps(props); + defaults.CheckEventBridgeProps(props); // Setup the dead letter queue, if applicable this.deadLetterQueue = defaults.buildDeadLetterQueue(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-sqs/test/eventbridge-sqs-queue.test.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-sqs/test/eventbridge-sqs-queue.test.ts index c34701aa8..f8a7a79cc 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-sqs/test/eventbridge-sqs-queue.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-sqs/test/eventbridge-sqs-queue.test.ts @@ -14,6 +14,7 @@ import * as cdk from 'aws-cdk-lib'; import { EventbridgeToSqs, EventbridgeToSqsProps } from '../lib'; import * as events from "aws-cdk-lib/aws-events"; +import * as sqs from "aws-cdk-lib/aws-sqs"; import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; @@ -277,28 +278,28 @@ test('check properties', () => { const stack = new cdk.Stack(); const construct: EventbridgeToSqs = deployNewStack(stack); - expect(construct.eventsRule !== null); - expect(construct.sqsQueue !== null); - expect(construct.encryptionKey !== null); - expect(construct.deadLetterQueue !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.sqsQueue).toBeDefined(); + expect(construct.encryptionKey).toBeDefined(); + expect(construct.deadLetterQueue).toBeDefined(); }); test('check eventbus property, snapshot & eventbus exists', () => { const stack = new cdk.Stack(); const construct: EventbridgeToSqs = deployStackWithNewEventBus(stack); - expect(construct.eventsRule !== null); - expect(construct.sqsQueue !== null); - expect(construct.encryptionKey !== null); - expect(construct.deadLetterQueue !== null); - expect(construct.eventBus !== null); + expect(construct.eventsRule).toBeDefined(); + expect(construct.sqsQueue).toBeDefined(); + expect(construct.encryptionKey).toBeDefined(); + expect(construct.deadLetterQueue).toBeDefined(); + expect(construct.eventBus).toBeDefined(); // Check whether eventbus exists const template = Template.fromStack(stack); template.resourceCountIs('AWS::Events::EventBus', 1); }); -test('check exception while passing existingEventBus & eventBusProps', () => { +test('Confirm CheckEventBridgeProps is being called', () => { const stack = new cdk.Stack(); const props: EventbridgeToSqsProps = { @@ -314,7 +315,7 @@ test('check exception while passing existingEventBus & eventBusProps', () => { const app = () => { new EventbridgeToSqs(stack, 'test-eventbridge-sqs', props); }; - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'); }); test('check custom event bus resource with props when deploy:true', () => { @@ -535,4 +536,26 @@ test('Queue purging flag grants correct permissions', () => { } ] }); -}); \ No newline at end of file +}); + +test('check that CheckSqsProps is being called', () => { + const stack = new cdk.Stack(); + + const props: EventbridgeToSqsProps = { + eventRuleProps: { + eventPattern: { + source: ['solutionsconstructs'] + } + }, + eventBusProps: { eventBusName: 'test' }, + queueProps: { + removalPolicy: cdk.RemovalPolicy.DESTROY, + }, + existingQueueObj: new sqs.Queue(stack, 'test', {}) + }; + + const app = () => { + new EventbridgeToSqs(stack, 'test-eventbridge-sqs', props); + }; + expect(app).toThrowError("Error - Either provide queueProps or existingQueueObj, but not both.\n"); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/lib/index.ts index 01b91451b..86a4acca8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/lib/index.ts @@ -79,7 +79,7 @@ export class EventbridgeToStepfunctions extends Construct { */ constructor(scope: Construct, id: string, props: EventbridgeToStepfunctionsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckEventBridgeProps(props); const buildStateMachineResponse = defaults.buildStateMachine(this, props.stateMachineProps, props.logGroupProps); diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/eventbridge-stepfunctions.test.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/eventbridge-stepfunctions.test.ts index 6c6eb9c2c..2ef7c76d0 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/eventbridge-stepfunctions.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/eventbridge-stepfunctions.test.ts @@ -106,10 +106,10 @@ test('check properties', () => { const construct: EventbridgeToStepfunctions = deployNewStateMachine(stack); - expect(construct.cloudwatchAlarms !== null); - expect(construct.stateMachine !== null); - expect(construct.eventsRule !== null); - expect(construct.stateMachineLogGroup !== null); + expect(construct.cloudwatchAlarms).toBeDefined(); + expect(construct.stateMachine).toBeDefined(); + expect(construct.eventsRule).toBeDefined(); + expect(construct.stateMachineLogGroup).toBeDefined(); }); test('check properties with no CW Alarms', () => { @@ -128,10 +128,10 @@ test('check properties with no CW Alarms', () => { const construct: EventbridgeToStepfunctions = new EventbridgeToStepfunctions(stack, 'test-eventbridge-stepfunctions', props); - expect(construct.cloudwatchAlarms === null); - expect(construct.stateMachine !== null); - expect(construct.eventsRule !== null); - expect(construct.stateMachineLogGroup !== null); + expect(construct.cloudwatchAlarms).not.toBeDefined(); + expect(construct.stateMachine).toBeDefined(); + expect(construct.eventsRule).toBeDefined(); + expect(construct.stateMachineLogGroup).toBeDefined(); }); test('check eventbus property, snapshot & eventbus exists', () => { @@ -139,18 +139,18 @@ test('check eventbus property, snapshot & eventbus exists', () => { const construct: EventbridgeToStepfunctions = deployNewStateMachineAndEventBus(stack); - expect(construct.cloudwatchAlarms !== null); - expect(construct.stateMachine !== null); - expect(construct.eventsRule !== null); - expect(construct.stateMachineLogGroup !== null); - expect(construct.eventBus !== null); + expect(construct.cloudwatchAlarms).toBeDefined(); + expect(construct.stateMachine).toBeDefined(); + expect(construct.eventsRule).toBeDefined(); + expect(construct.stateMachineLogGroup).toBeDefined(); + expect(construct.eventBus).toBeDefined(); // Check whether eventbus exists const template = Template.fromStack(stack); template.resourceCountIs('AWS::Events::EventBus', 1); }); -test('check exception while passing existingEventBus & eventBusProps', () => { +test('Confirm CheckEventBridgeProps is being called', () => { const stack = new cdk.Stack(); const startState = new sfn.Pass(stack, 'StartState'); @@ -170,7 +170,7 @@ test('check exception while passing existingEventBus & eventBusProps', () => { const app = () => { new EventbridgeToStepfunctions(stack, 'test-eventbridge-stepfunctions', props); }; - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'); }); test('check custom event bus resource with props when deploy:true', () => { diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-existing-eventbus.expected.json b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-existing-eventbus.expected.json index 6bcf0a409..dee9dbace 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-existing-eventbus.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-existing-eventbus.expected.json @@ -98,18 +98,18 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -141,7 +141,7 @@ "existingeventbusA5B80487": { "Type": "AWS::Events::EventBus", "Properties": { - "Name": "test" + "Name": "test-existing" } }, "testeventbridgestepfunctionsneweventbusconstructStateMachineLogGroup6DC6AD59": { @@ -285,17 +285,11 @@ "testeventbridgestepfunctionsneweventbusconstructStateMachine5B0C5609": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "testeventbridgestepfunctionsneweventbusconstructStateMachineRole88F30AE1", - "Arn" - ] - }, "DefinitionString": { "Fn::Join": [ "", [ - "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"Next\":\"LambdaTask\"},\"LambdaTask\":{\"End\":true,\"Retry\":[{\"ErrorEquals\":[\"Lambda.ServiceException\",\"Lambda.AWSLambdaException\",\"Lambda.SdkClientException\"],\"IntervalSeconds\":2,\"MaxAttempts\":6,\"BackoffRate\":2}],\"Type\":\"Task\",\"Resource\":\"arn:", + "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"Next\":\"LambdaTask\"},\"LambdaTask\":{\"End\":true,\"Retry\":[{\"ErrorEquals\":[\"Lambda.ClientExecutionTimeoutException\",\"Lambda.ServiceException\",\"Lambda.AWSLambdaException\",\"Lambda.SdkClientException\"],\"IntervalSeconds\":2,\"MaxAttempts\":6,\"BackoffRate\":2}],\"Type\":\"Task\",\"Resource\":\"arn:", { "Ref": "AWS::Partition" }, @@ -324,6 +318,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "testeventbridgestepfunctionsneweventbusconstructStateMachineRole88F30AE1", + "Arn" + ] } }, "DependsOn": [ @@ -404,9 +404,8 @@ "testeventbridgestepfunctionsneweventbusconstructExecutionFailedAlarmF5234856": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -415,6 +414,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -425,9 +425,8 @@ "testeventbridgestepfunctionsneweventbusconstructExecutionThrottledAlarm08AFD5C8": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -436,6 +435,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -446,9 +446,8 @@ "testeventbridgestepfunctionsneweventbusconstructExecutionAbortedAlarmAA68F975": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -457,6 +456,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -497,6 +497,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -530,6 +533,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-existing-eventbus.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-existing-eventbus.ts index b71b9f83a..d4f52042f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-existing-eventbus.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-existing-eventbus.ts @@ -37,7 +37,7 @@ const submitJob = new tasks.LambdaInvoke(stack, 'LambdaTask', { const startState = new stepfunctions.Pass(stack, 'StartState'); startState.next(submitJob); -const existingEventBus = new EventBus(stack, `existing-event-bus`, { eventBusName: 'test'}); +const existingEventBus = new EventBus(stack, `existing-event-bus`, { eventBusName: 'test-existing'}); const props: EventbridgeToStepfunctionsProps = { stateMachineProps: { definition: startState, diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-new-eventbus.expected.json b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-new-eventbus.expected.json index f1e000cdf..82b3ca7cd 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-new-eventbus.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-new-eventbus.expected.json @@ -98,18 +98,18 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -279,17 +279,11 @@ "testeventbridgestepfunctionsneweventbusconstructStateMachine5B0C5609": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "testeventbridgestepfunctionsneweventbusconstructStateMachineRole88F30AE1", - "Arn" - ] - }, "DefinitionString": { "Fn::Join": [ "", [ - "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"Next\":\"LambdaTask\"},\"LambdaTask\":{\"End\":true,\"Retry\":[{\"ErrorEquals\":[\"Lambda.ServiceException\",\"Lambda.AWSLambdaException\",\"Lambda.SdkClientException\"],\"IntervalSeconds\":2,\"MaxAttempts\":6,\"BackoffRate\":2}],\"Type\":\"Task\",\"Resource\":\"arn:", + "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"Next\":\"LambdaTask\"},\"LambdaTask\":{\"End\":true,\"Retry\":[{\"ErrorEquals\":[\"Lambda.ClientExecutionTimeoutException\",\"Lambda.ServiceException\",\"Lambda.AWSLambdaException\",\"Lambda.SdkClientException\"],\"IntervalSeconds\":2,\"MaxAttempts\":6,\"BackoffRate\":2}],\"Type\":\"Task\",\"Resource\":\"arn:", { "Ref": "AWS::Partition" }, @@ -318,6 +312,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "testeventbridgestepfunctionsneweventbusconstructStateMachineRole88F30AE1", + "Arn" + ] } }, "DependsOn": [ @@ -367,17 +367,17 @@ ] } }, - "testeventbridgestepfunctionsneweventbusconstructtestE4F3554B": { + "testeventbridgestepfunctionsneweventbusconstructtestnewA01E6B5C": { "Type": "AWS::Events::EventBus", "Properties": { - "Name": "test" + "Name": "test-new" } }, "testeventbridgestepfunctionsneweventbusconstructEventsRule471B9F20": { "Type": "AWS::Events::Rule", "Properties": { "EventBusName": { - "Ref": "testeventbridgestepfunctionsneweventbusconstructtestE4F3554B" + "Ref": "testeventbridgestepfunctionsneweventbusconstructtestnewA01E6B5C" }, "EventPattern": { "source": [ @@ -404,9 +404,8 @@ "testeventbridgestepfunctionsneweventbusconstructExecutionFailedAlarmF5234856": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -415,6 +414,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -425,9 +425,8 @@ "testeventbridgestepfunctionsneweventbusconstructExecutionThrottledAlarm08AFD5C8": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -436,6 +435,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -446,9 +446,8 @@ "testeventbridgestepfunctionsneweventbusconstructExecutionAbortedAlarmAA68F975": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -457,6 +456,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -497,6 +497,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -530,6 +533,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-new-eventbus.ts b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-new-eventbus.ts index 275fc178f..6a1b5614a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-new-eventbus.ts +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-new-eventbus.ts @@ -46,7 +46,7 @@ const props: EventbridgeToStepfunctionsProps = { source: ['solutionsconstructs'] } }, - eventBusProps: { eventBusName: 'test' }, + eventBusProps: { eventBusName: 'test-new' }, logGroupProps: { removalPolicy: RemovalPolicy.DESTROY, logGroupName: "integ-test-new-eventbus" diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-no-argument.expected.json b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-no-argument.expected.json index bb8778950..2511b0adc 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-no-argument.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-no-argument.expected.json @@ -135,12 +135,6 @@ "testeventbridgestepfunctionsconstructStateMachine08688697": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "testeventbridgestepfunctionsconstructStateMachineRoleED595422", - "Arn" - ] - }, "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", "LoggingConfiguration": { "Destinations": [ @@ -156,6 +150,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "testeventbridgestepfunctionsconstructStateMachineRoleED595422", + "Arn" + ] } }, "DependsOn": [ @@ -229,9 +229,8 @@ "testeventbridgestepfunctionsconstructExecutionFailedAlarm57DF694C": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -240,6 +239,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -250,9 +250,8 @@ "testeventbridgestepfunctionsconstructExecutionThrottledAlarmE43E1426": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -261,6 +260,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -271,9 +271,8 @@ "testeventbridgestepfunctionsconstructExecutionAbortedAlarmAACA66A8": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -282,6 +281,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -322,6 +322,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -355,6 +358,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-with-lambda.expected.json b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-with-lambda.expected.json index b97edd5c9..21d73496a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-with-lambda.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-eventbridge-stepfunctions/test/integ.eventbridge-stepfunctions-with-lambda.expected.json @@ -98,18 +98,18 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -279,17 +279,11 @@ "testeventbridgestepfunctionsandlambdaconstructStateMachineACD2232F": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "testeventbridgestepfunctionsandlambdaconstructStateMachineRoleD7589F39", - "Arn" - ] - }, "DefinitionString": { "Fn::Join": [ "", [ - "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"Next\":\"LambdaTask\"},\"LambdaTask\":{\"End\":true,\"Retry\":[{\"ErrorEquals\":[\"Lambda.ServiceException\",\"Lambda.AWSLambdaException\",\"Lambda.SdkClientException\"],\"IntervalSeconds\":2,\"MaxAttempts\":6,\"BackoffRate\":2}],\"Type\":\"Task\",\"Resource\":\"arn:", + "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"Next\":\"LambdaTask\"},\"LambdaTask\":{\"End\":true,\"Retry\":[{\"ErrorEquals\":[\"Lambda.ClientExecutionTimeoutException\",\"Lambda.ServiceException\",\"Lambda.AWSLambdaException\",\"Lambda.SdkClientException\"],\"IntervalSeconds\":2,\"MaxAttempts\":6,\"BackoffRate\":2}],\"Type\":\"Task\",\"Resource\":\"arn:", { "Ref": "AWS::Partition" }, @@ -318,6 +312,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "testeventbridgestepfunctionsandlambdaconstructStateMachineRoleD7589F39", + "Arn" + ] } }, "DependsOn": [ @@ -391,9 +391,8 @@ "testeventbridgestepfunctionsandlambdaconstructExecutionFailedAlarm61E476BC": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -402,6 +401,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -412,9 +412,8 @@ "testeventbridgestepfunctionsandlambdaconstructExecutionThrottledAlarm70141701": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -423,6 +422,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -433,9 +433,8 @@ "testeventbridgestepfunctionsandlambdaconstructExecutionAbortedAlarm8E79E87E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -444,6 +443,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -484,6 +484,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -517,6 +520,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/lib/index.ts index b254086ef..60ef5c9c4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/lib/index.ts @@ -85,7 +85,7 @@ export interface FargateToDynamoDBProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -140,8 +140,9 @@ export class FargateToDynamoDB extends Construct { constructor(scope: Construct, id: string, props: FargateToDynamoDBProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckDynamoDBProps(props); + defaults.CheckVpcProps(props); // Other permissions for constructs are accepted as arrays, turning tablePermissions into // an array to use the same validation function. diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/fargate-dynamodb.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/fargate-dynamodb.test.ts index 5324cd6fb..6a89c20b1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/fargate-dynamodb.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/fargate-dynamodb.test.ts @@ -14,7 +14,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToDynamoDB } from "../lib"; +import { FargateToDynamoDB, FargateToDynamoDBProps } from "../lib"; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; @@ -46,11 +46,11 @@ test('New service/new table, public API, new VPC', () => { tablePermissions: 'ReadWrite' }); - expect(construct.vpc !== null); - expect(construct.service !== null); - expect(construct.container !== null); - expect(construct.dynamoTable !== null); - expect(construct.dynamoTableInterface !== null); + expect(construct.vpc).toBeDefined(); + expect(construct.service).toBeDefined(); + expect(construct.container).toBeDefined(); + expect(construct.dynamoTable).toBeDefined(); + expect(construct.dynamoTableInterface).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::ECS::Service", { @@ -669,4 +669,81 @@ test('test error invalid table permission', () => { }; expect(app).toThrowError('Invalid tablePermission submitted - REED'); -}); \ No newline at end of file +}); + +test('test that DDB input args are getting checked', () => { + const stack = new cdk.Stack(); + const publicApi = false; + const serviceName = 'custom-name'; + const tableName = 'custom-table-name'; + + const existingVpc = defaults.getTestVpc(stack, publicApi); + + const createFargateServiceResponse = defaults.CreateFargateService(stack, 'test', { + constructVpc: existingVpc, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clientFargateServiceProps: { + serviceName + } + }); + + const existingTable = new dynamodb.Table(stack, 'MyTablet', { + tableName, + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING + } + }); + + const app = () => { + new FargateToDynamoDB(stack, 'test-construct', { + publicApi, + existingFargateServiceObject: createFargateServiceResponse.service, + existingContainerDefinitionObject: createFargateServiceResponse.containerDefinition, + existingVpc, + existingTableInterface: existingTable, + dynamoTableProps: { + tableName, + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING + }, + }, + }); + }; + + expect(app).toThrowError('Error - Either provide existingTableInterface or dynamoTableProps, but not both.\n'); +}); + +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const clusterName = "custom-cluster-name"; + const containerName = "custom-container-name"; + const serviceName = "custom-service-name"; + const familyName = "custom-family-name"; + + const props: FargateToDynamoDBProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + dynamoTableProps: { + tableName: 'fake-name', + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING + }, + }, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToDynamoDB(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/integ.existing-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/integ.existing-resources.expected.json index 4b99550a6..d02e765af 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/integ.existing-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/integ.existing-resources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,21 +657,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,12 +753,6 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" - } - }, - "VpcDDB49FBEC5F": { - "Type": "AWS::EC2::VPCEndpoint", - "Properties": { "ServiceName": { "Fn::Join": [ "", @@ -782,13 +761,19 @@ { "Ref": "AWS::Region" }, - ".dynamodb" + ".s3" ] ] }, + "VpcEndpointType": "Gateway", "VpcId": { "Ref": "Vpc8378EB38" - }, + } + } + }, + "VpcDDB49FBEC5F": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -809,25 +794,40 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".dynamodb" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "DynamoTableB2B22E15": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, @@ -1104,6 +1104,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1138,7 +1143,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/integ.new-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/integ.new-resources.expected.json index d64258e2f..3b243e331 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/integ.new-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/integ.new-resources.expected.json @@ -4,19 +4,19 @@ "testconstructDynamoTable67BDAFC5": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, @@ -45,9 +45,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -64,7 +61,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -80,15 +80,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -105,12 +105,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -132,15 +132,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -156,9 +156,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -175,7 +172,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -191,15 +191,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -216,12 +216,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -243,15 +243,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -267,9 +267,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -286,7 +283,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -302,15 +302,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -327,12 +327,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -354,15 +354,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -378,9 +378,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -397,21 +394,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -428,21 +428,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -459,21 +456,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -490,21 +490,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -521,21 +518,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -552,12 +552,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -575,11 +575,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -601,7 +601,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] } @@ -653,7 +653,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] }, @@ -673,11 +673,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -688,32 +683,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcDDB49FBEC5F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".dynamodb" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -734,16 +719,27 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".dynamodb" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -753,6 +749,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -764,16 +761,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -783,6 +779,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -794,27 +791,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -835,7 +820,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newresourcesECRAPIsecuritygroupE52BAE3F": { @@ -1104,6 +1104,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1138,7 +1143,11 @@ "TaskDefinition": { "Ref": "testconstructtaskdef8BD1F9E4" } - } + }, + "DependsOn": [ + "testconstructtaskdefTaskRoleDefaultPolicyF34A1535", + "testconstructtaskdefTaskRoleC60414C4" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/lib/index.ts index 06b577b7f..498b58249 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/lib/index.ts @@ -90,7 +90,7 @@ export interface FargateToEventbridgeProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -132,8 +132,9 @@ export class FargateToEventbridge extends Construct { constructor(scope: Construct, id: string, props: FargateToEventbridgeProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckVpcProps(props); + defaults.CheckEventBridgeProps(props); this.vpc = defaults.buildVpc(scope, { existingVpc: props.existingVpc, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/fargate-eventbridge.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/fargate-eventbridge.test.ts index 780dca7ff..e8789f9d4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/fargate-eventbridge.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/fargate-eventbridge.test.ts @@ -14,7 +14,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToEventbridge } from "../lib"; +import { FargateToEventbridge, FargateToEventbridgeProps } from "../lib"; import * as events from 'aws-cdk-lib/aws-events'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; @@ -372,4 +372,49 @@ function createFargateConstructWithNewResources(stack: cdk.Stack, publicApi: boo eventBusName: 'custom-name' } }); -} \ No newline at end of file +} + +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + + const props: FargateToEventbridgeProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + eventBusProps: { + eventBusName: 'custom-name' + }, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToEventbridge(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm CheckEventBridgeProps is being called', () => { + const stack = new cdk.Stack(); + + const props: FargateToEventbridgeProps = { + publicApi: true, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + eventBusProps: { eventBusName: 'test' }, + existingEventBusInterface: new events.EventBus(stack, `test-existing-eventbus`, { eventBusName: 'test' }) + }; + + const app = () => { + new FargateToEventbridge(stack, 'test-fargate-eventbridge', props); + }; + expect(app).toThrowError('Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/integ.existing-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/integ.existing-resources.expected.json index 0183470bc..befd1b89b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/integ.existing-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/integ.existing-resources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,21 +657,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,16 +753,27 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcCLOUDWATCHEVENTS1A0DAFBF": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.events", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -787,6 +783,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.events", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -798,7 +795,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "existingresourcesECRAPIsecuritygroup78294485": { @@ -1040,6 +1040,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1074,7 +1079,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] }, "existingeventbusA5B80487": { "Type": "AWS::Events::EventBus", diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/integ.new-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/integ.new-resources.expected.json index b7f47b52e..15a6c4295 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/integ.new-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-eventbridge/test/integ.new-resources.expected.json @@ -25,9 +25,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -44,7 +41,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -60,15 +60,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -85,12 +85,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -112,15 +112,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -136,9 +136,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -155,7 +152,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -171,15 +171,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -196,12 +196,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -223,15 +223,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -247,9 +247,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -266,7 +263,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -282,15 +282,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -307,12 +307,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -334,15 +334,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -358,9 +358,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -377,21 +374,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -408,21 +408,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -439,21 +436,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -470,21 +470,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -501,21 +498,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -532,12 +532,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -555,11 +555,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -581,7 +581,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] } @@ -633,7 +633,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] }, @@ -653,11 +653,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -668,21 +663,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcCLOUDWATCHEVENTS1A0DAFBF": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.events", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -692,6 +688,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.events", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -703,16 +700,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -722,6 +718,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -733,16 +730,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -752,6 +748,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -763,27 +760,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -804,7 +789,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newresourcesCLOUDWATCHEVENTSsecuritygroupC0F12F92": { @@ -1104,6 +1104,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1138,7 +1143,11 @@ "TaskDefinition": { "Ref": "testconstructtaskdef8BD1F9E4" } - } + }, + "DependsOn": [ + "testconstructtaskdefTaskRoleDefaultPolicyF34A1535", + "testconstructtaskdefTaskRoleC60414C4" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/lib/index.ts index 42cee3e2b..c1df8bea4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/lib/index.ts @@ -89,7 +89,7 @@ export interface FargateToKinesisFirehoseProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -125,8 +125,8 @@ export class FargateToKinesisFirehose extends Construct { constructor(scope: Construct, id: string, props: FargateToKinesisFirehoseProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckVpcProps(props); if (!props.existingKinesisFirehose.deliveryStreamName) { throw new Error('existingKinesisFirehose must have a defined deliveryStreamName'); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/aws-fargate-kinesisfirehose.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/aws-fargate-kinesisfirehose.test.ts index 3c35374d4..274d9fb6c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/aws-fargate-kinesisfirehose.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/aws-fargate-kinesisfirehose.test.ts @@ -13,7 +13,7 @@ import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToKinesisFirehose } from "../lib"; +import { FargateToKinesisFirehose, FargateToKinesisFirehoseProps } from "../lib"; import * as ecs from 'aws-cdk-lib/aws-ecs'; import { Match, Template } from "aws-cdk-lib/assertions"; import { GetTestFirehoseDestination } from './test-helper'; @@ -39,10 +39,10 @@ test('New service/new bucket, public API, new VPC', () => { existingKinesisFirehose: destination.kinesisFirehose }); - expect(construct.vpc !== null); - expect(construct.service !== null); - expect(construct.container !== null); - expect(construct.kinesisFirehose !== null); + expect(construct.vpc).toBeDefined(); + expect(construct.service).toBeDefined(); + expect(construct.container).toBeDefined(); + expect(construct.kinesisFirehose).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::ECS::Service", { @@ -711,3 +711,31 @@ test('Test fail if existingFirehose does not have a stream name', () => { expect(app).toThrowError(/existingKinesisFirehose must have a defined deliveryStreamName/); }); + +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const clusterName = "custom-cluster-name"; + const containerName = "custom-container-name"; + const serviceName = "custom-service-name"; + const familyName = "custom-family-name"; + const destination = GetTestFirehoseDestination(stack, 'test-destination'); + + const props: FargateToKinesisFirehoseProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + existingKinesisFirehose: destination.kinesisFirehose, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToKinesisFirehose(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.existingFargateService.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.existingFargateService.expected.json index 08a24d410..5f1f86256 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.existingFargateService.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.existingFargateService.expected.json @@ -18,9 +18,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -37,7 +34,10 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -53,15 +53,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -78,12 +78,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -105,15 +105,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -129,9 +129,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -148,7 +145,10 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -164,15 +164,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -189,12 +189,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -216,15 +216,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -240,9 +240,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -259,7 +256,10 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -275,15 +275,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -300,12 +300,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -327,15 +327,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -351,9 +351,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -370,21 +367,24 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -401,21 +401,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -432,21 +429,24 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -463,21 +463,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -494,21 +491,24 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -525,12 +525,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -548,11 +548,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -574,7 +574,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingFargateService/Vpc" + "Value": "existingFargateService/Vpc/FlowLog" } ] } @@ -626,7 +626,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingFargateService/Vpc" + "Value": "existingFargateService/Vpc/FlowLog" } ] }, @@ -646,10 +646,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -660,10 +656,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existingFargateService/Vpc" + "Value": "existingFargateService/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -672,6 +672,15 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingFargateServiceECRAPIsecuritygroup5EE2643E", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -684,18 +693,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingFargateServiceECRAPIsecuritygroup5EE2643E", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -707,12 +704,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingFargateServiceECRDKRsecuritygroup41F182BE", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -725,18 +734,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingFargateServiceECRDKRsecuritygroup41F182BE", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -748,27 +745,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -789,12 +774,6 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" - } - }, - "VpcKINESISFIREHOSE4115B5D1": { - "Type": "AWS::EC2::VPCEndpoint", - "Properties": { "ServiceName": { "Fn::Join": [ "", @@ -803,13 +782,19 @@ { "Ref": "AWS::Region" }, - ".kinesis-firehose" + ".s3" ] ] }, + "VpcEndpointType": "Gateway", "VpcId": { "Ref": "Vpc8378EB38" - }, + } + } + }, + "VpcKINESISFIREHOSE4115B5D1": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -819,6 +804,18 @@ ] } ], + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".kinesis-firehose" + ] + ] + }, "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -830,7 +827,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "destinationfirehoseS3LoggingBucket19A32AC0": { @@ -1383,18 +1383,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -1672,6 +1672,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1706,7 +1711,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] }, "existingFargateServiceKINESISFIREHOSEsecuritygroup9CDC51DB": { "Type": "AWS::EC2::SecurityGroup", @@ -1767,109 +1776,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.existingVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.existingVpc.expected.json index 8289c2e55..dd8a62f26 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.existingVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.existingVpc.expected.json @@ -18,9 +18,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -37,7 +34,10 @@ "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -53,15 +53,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -78,12 +78,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -105,15 +105,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -129,9 +129,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -148,7 +145,10 @@ "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -164,15 +164,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -189,12 +189,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -216,15 +216,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -240,9 +240,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -259,7 +256,10 @@ "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -275,15 +275,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -300,12 +300,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -327,15 +327,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -351,9 +351,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -370,21 +367,24 @@ "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -401,21 +401,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -432,21 +429,24 @@ "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -463,21 +463,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -494,21 +491,24 @@ "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -525,12 +525,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -548,11 +548,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -574,7 +574,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingVpc/Vpc" + "Value": "existingVpc/Vpc/FlowLog" } ] } @@ -626,7 +626,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingVpc/Vpc" + "Value": "existingVpc/Vpc/FlowLog" } ] }, @@ -646,10 +646,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -660,10 +656,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existingVpc/Vpc" + "Value": "existingVpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -672,6 +672,15 @@ "VpcKINESISFIREHOSE4115B5D1": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingVpcKINESISFIREHOSEsecuritygroupCC06079B", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -684,18 +693,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingVpcKINESISFIREHOSEsecuritygroupCC06079B", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -707,12 +704,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingVpcECRAPIsecuritygroupB3E4A376", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -725,18 +734,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingVpcECRAPIsecuritygroupB3E4A376", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -748,12 +745,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingVpcECRDKRsecuritygroup0500FAE6", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -766,18 +775,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingVpcECRDKRsecuritygroup0500FAE6", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -789,27 +786,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -830,7 +815,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "destinationfirehoseS3LoggingBucket19A32AC0": { @@ -1383,18 +1383,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -1730,6 +1730,11 @@ "Ref": "testfargatekinesisstreamsclusterEA5A2AD7" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1764,110 +1769,11 @@ "TaskDefinition": { "Ref": "testfargatekinesisstreamstaskdef402FE0B3" } - } - } - }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } + "DependsOn": [ + "testfargatekinesisstreamstaskdefTaskRoleDefaultPolicyAE7EF3E4", + "testfargatekinesisstreamstaskdefTaskRole9811F3BE" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.fargateServiceFromProps.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.fargateServiceFromProps.expected.json index 1dcc7d488..45d796abc 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.fargateServiceFromProps.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.fargateServiceFromProps.expected.json @@ -550,18 +550,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -615,9 +615,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -634,7 +631,10 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -650,15 +650,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -675,12 +675,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -702,15 +702,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -726,9 +726,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -745,7 +742,10 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -761,15 +761,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -786,12 +786,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -813,15 +813,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -837,9 +837,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -856,7 +853,10 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -872,15 +872,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -897,12 +897,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -924,15 +924,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -948,9 +948,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -967,21 +964,24 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -998,21 +998,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -1029,21 +1026,24 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -1060,21 +1060,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -1091,21 +1088,24 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -1122,12 +1122,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -1145,11 +1145,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -1171,7 +1171,7 @@ "Tags": [ { "Key": "Name", - "Value": "fargateServiceFromProps/Vpc" + "Value": "fargateServiceFromProps/Vpc/FlowLog" } ] } @@ -1223,7 +1223,7 @@ "Tags": [ { "Key": "Name", - "Value": "fargateServiceFromProps/Vpc" + "Value": "fargateServiceFromProps/Vpc/FlowLog" } ] }, @@ -1243,10 +1243,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1257,10 +1253,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "fargateServiceFromProps/Vpc" + "Value": "fargateServiceFromProps/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -1269,6 +1269,15 @@ "VpcKINESISFIREHOSE4115B5D1": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "fargateServiceFromPropsKINESISFIREHOSEsecuritygroupC0011304", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -1281,18 +1290,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "fargateServiceFromPropsKINESISFIREHOSEsecuritygroupC0011304", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1304,12 +1301,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "fargateServiceFromPropsECRAPIsecuritygroup5784F80B", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -1322,18 +1331,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "fargateServiceFromPropsECRAPIsecuritygroup5784F80B", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1345,12 +1342,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "fargateServiceFromPropsECRDKRsecuritygroup9E1C301F", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -1363,18 +1372,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "fargateServiceFromPropsECRDKRsecuritygroup9E1C301F", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1386,27 +1383,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -1427,7 +1412,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "fargateServiceFromPropsKINESISFIREHOSEsecuritygroupC0011304": { @@ -1730,6 +1730,11 @@ "Ref": "testfargatekinesisstreamsclusterEA5A2AD7" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1765,110 +1770,11 @@ "TaskDefinition": { "Ref": "testfargatekinesisstreamstaskdef402FE0B3" } - } - } - }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } + "DependsOn": [ + "testfargatekinesisstreamstaskdefTaskRoleDefaultPolicyAE7EF3E4", + "testfargatekinesisstreamstaskdefTaskRole9811F3BE" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.noArguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.noArguments.expected.json index 9383c2a97..a9acca727 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.noArguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.noArguments.expected.json @@ -546,18 +546,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "40aa87cdf43c4095cec18bc443965f22ab2f8c1ace47e482a0ba4e35d83b0cc9.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -611,9 +611,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -630,7 +627,10 @@ "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -646,15 +646,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -671,12 +671,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -698,15 +698,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -722,9 +722,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -741,7 +738,10 @@ "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -757,15 +757,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -782,12 +782,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -809,15 +809,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -833,9 +833,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -852,7 +849,10 @@ "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -868,15 +868,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -893,12 +893,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -920,15 +920,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -944,9 +944,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -963,21 +960,24 @@ "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -994,21 +994,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -1025,21 +1022,24 @@ "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -1056,21 +1056,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -1087,21 +1084,24 @@ "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -1118,12 +1118,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -1141,11 +1141,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -1167,7 +1167,7 @@ "Tags": [ { "Key": "Name", - "Value": "noArguments/Vpc" + "Value": "noArguments/Vpc/FlowLog" } ] } @@ -1219,7 +1219,7 @@ "Tags": [ { "Key": "Name", - "Value": "noArguments/Vpc" + "Value": "noArguments/Vpc/FlowLog" } ] }, @@ -1239,10 +1239,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1253,10 +1249,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "noArguments/Vpc" + "Value": "noArguments/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -1265,10 +1265,6 @@ "VpcKINESISFIREHOSE4115B5D1": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.kinesis-firehose", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -1278,6 +1274,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.kinesis-firehose", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1289,16 +1286,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -1308,6 +1304,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1319,16 +1316,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -1338,6 +1334,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1349,27 +1346,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -1390,7 +1375,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "noArgumentsKINESISFIREHOSEsecuritygroupBE0C0999": { @@ -1693,6 +1693,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1727,7 +1732,11 @@ "TaskDefinition": { "Ref": "testconstructtaskdef8BD1F9E4" } - } + }, + "DependsOn": [ + "testconstructtaskdefTaskRoleDefaultPolicyF34A1535", + "testconstructtaskdefTaskRoleC60414C4" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.vpcFromprops.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.vpcFromprops.expected.json index 9e9e1b4a9..1c7b97b8e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.vpcFromprops.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisfirehose/test/integ.vpcFromprops.expected.json @@ -550,18 +550,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -615,9 +615,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.100.0.0/19", "MapPublicIpOnLaunch": true, @@ -634,7 +631,10 @@ "Key": "Name", "Value": "vpcFromprops/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -650,15 +650,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromprops/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -675,12 +675,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -702,15 +702,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -726,9 +726,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.100.32.0/19", "MapPublicIpOnLaunch": true, @@ -745,7 +742,10 @@ "Key": "Name", "Value": "vpcFromprops/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -761,15 +761,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromprops/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -786,12 +786,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -813,15 +813,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -837,9 +837,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.100.64.0/19", "MapPublicIpOnLaunch": true, @@ -856,7 +853,10 @@ "Key": "Name", "Value": "vpcFromprops/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -872,15 +872,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromprops/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -897,12 +897,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -924,15 +924,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -948,9 +948,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.100.96.0/19", "MapPublicIpOnLaunch": false, @@ -967,21 +964,24 @@ "Key": "Name", "Value": "vpcFromprops/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromprops/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -998,21 +998,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.100.128.0/19", "MapPublicIpOnLaunch": false, @@ -1029,21 +1026,24 @@ "Key": "Name", "Value": "vpcFromprops/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromprops/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -1060,21 +1060,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.100.160.0/19", "MapPublicIpOnLaunch": false, @@ -1091,21 +1088,24 @@ "Key": "Name", "Value": "vpcFromprops/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromprops/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -1122,12 +1122,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -1145,11 +1145,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -1171,7 +1171,7 @@ "Tags": [ { "Key": "Name", - "Value": "vpcFromprops/Vpc" + "Value": "vpcFromprops/Vpc/FlowLog" } ] } @@ -1223,7 +1223,7 @@ "Tags": [ { "Key": "Name", - "Value": "vpcFromprops/Vpc" + "Value": "vpcFromprops/Vpc/FlowLog" } ] }, @@ -1243,10 +1243,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1257,10 +1253,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "vpcFromprops/Vpc" + "Value": "vpcFromprops/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -1269,6 +1269,15 @@ "VpcKINESISFIREHOSE4115B5D1": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "vpcFrompropsKINESISFIREHOSEsecuritygroup537BDD19", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -1281,18 +1290,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "vpcFrompropsKINESISFIREHOSEsecuritygroup537BDD19", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1304,12 +1301,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "vpcFrompropsECRAPIsecuritygroupB070D1AB", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -1322,18 +1331,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "vpcFrompropsECRAPIsecuritygroupB070D1AB", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1345,12 +1342,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "vpcFrompropsECRDKRsecuritygroup4D8AFEF5", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -1363,18 +1372,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "vpcFrompropsECRDKRsecuritygroup4D8AFEF5", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1386,27 +1383,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -1427,7 +1412,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "vpcFrompropsKINESISFIREHOSEsecuritygroup537BDD19": { @@ -1730,6 +1730,11 @@ "Ref": "testfargatekinesisstreamsclusterEA5A2AD7" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1764,110 +1769,11 @@ "TaskDefinition": { "Ref": "testfargatekinesisstreamstaskdef402FE0B3" } - } - } - }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } + "DependsOn": [ + "testfargatekinesisstreamstaskdefTaskRoleDefaultPolicyAE7EF3E4", + "testfargatekinesisstreamstaskdefTaskRole9811F3BE" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/lib/index.ts index b87cdb3a4..a71abdc57 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/lib/index.ts @@ -150,8 +150,9 @@ export class FargateToKinesisStreams extends Construct { */ constructor(scope: Construct, id: string, props: FargateToKinesisStreamsProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckVpcProps(props); + defaults.CheckKinesisStreamProps(props); // Setup the VPC this.vpc = defaults.buildVpc(scope, { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/fargate-kinesisstreams.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/fargate-kinesisstreams.test.ts index ea17271b0..5ae9df5b6 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/fargate-kinesisstreams.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/fargate-kinesisstreams.test.ts @@ -11,7 +11,7 @@ * and limitations under the License. */ -import { FargateToKinesisStreams } from "../lib"; +import { FargateToKinesisStreams, FargateToKinesisStreamsProps } from "../lib"; import * as cdk from "aws-cdk-lib"; import * as kinesis from 'aws-cdk-lib/aws-kinesis'; import * as defaults from '@aws-solutions-constructs/core'; @@ -596,4 +596,57 @@ test('Construct uses existingFargateServiceObject when provided', () => { template.hasResourceProperties("AWS::ECS::Service", { ServiceName: 'my-service', }); -}); \ No newline at end of file +}); + +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const clusterName = "custom-cluster-name"; + const containerName = "custom-container-name"; + const serviceName = "custom-service-name"; + const familyName = "custom-family-name"; + + const props: FargateToKinesisStreamsProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToKinesisStreams(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm that CheckKinesisStreamsProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const clusterName = "custom-cluster-name"; + const containerName = "custom-container-name"; + const serviceName = "custom-service-name"; + const familyName = "custom-family-name"; + + const props: FargateToKinesisStreamsProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + vpcProps: { }, + existingStreamObj: new kinesis.Stream(stack, 'test', {}), + kinesisStreamProps: {} + }; + + const app = () => { + new FargateToKinesisStreams(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingFargateService.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingFargateService.expected.json index 810cc8994..94ad4f26a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingFargateService.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingFargateService.expected.json @@ -18,9 +18,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -37,7 +34,10 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -53,15 +53,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -78,12 +78,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -105,15 +105,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -129,9 +129,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -148,7 +145,10 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -164,15 +164,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -189,12 +189,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -216,15 +216,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -240,9 +240,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -259,7 +256,10 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -275,15 +275,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -300,12 +300,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -327,15 +327,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -351,9 +351,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -370,21 +367,24 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -401,21 +401,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -432,21 +429,24 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -463,21 +463,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -494,21 +491,24 @@ "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingFargateService/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -525,12 +525,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -548,11 +548,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -574,7 +574,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingFargateService/Vpc" + "Value": "existingFargateService/Vpc/FlowLog" } ] } @@ -626,7 +626,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingFargateService/Vpc" + "Value": "existingFargateService/Vpc/FlowLog" } ] }, @@ -646,10 +646,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -660,10 +656,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existingFargateService/Vpc" + "Value": "existingFargateService/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -672,6 +672,15 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingFargateServiceECRAPIsecuritygroup5EE2643E", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -684,18 +693,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingFargateServiceECRAPIsecuritygroup5EE2643E", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -707,12 +704,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingFargateServiceECRDKRsecuritygroup41F182BE", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -725,18 +734,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingFargateServiceECRDKRsecuritygroup41F182BE", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -748,27 +745,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -789,12 +774,6 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" - } - }, - "VpcKINESISSTREAMSC07D91B5": { - "Type": "AWS::EC2::VPCEndpoint", - "Properties": { "ServiceName": { "Fn::Join": [ "", @@ -803,13 +782,19 @@ { "Ref": "AWS::Region" }, - ".kinesis-streams" + ".s3" ] ] }, + "VpcEndpointType": "Gateway", "VpcId": { "Ref": "Vpc8378EB38" - }, + } + } + }, + "VpcKINESISSTREAMSC07D91B5": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -819,6 +804,18 @@ ] } ], + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".kinesis-streams" + ] + ] + }, "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -830,7 +827,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "existingFargateServiceECRAPIsecuritygroup5EE2643E": { @@ -1076,6 +1076,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1110,7 +1115,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] }, "testfargatekinesisstreamsKinesisStreamD31BD614": { "Type": "AWS::Kinesis::Stream", @@ -1126,9 +1135,9 @@ "testfargatekinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarm60755E90": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -1139,9 +1148,9 @@ "testfargatekinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarmDE16A9F2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingStream.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingStream.expected.json index c11f84f5e..28cff9b56 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingStream.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingStream.expected.json @@ -16,9 +16,9 @@ "testfargatekinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarm60755E90": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -29,9 +29,9 @@ "testfargatekinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarmDE16A9F2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -57,9 +57,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -76,7 +73,10 @@ "Key": "Name", "Value": "existingStream/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -92,15 +92,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingStream/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -117,12 +117,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -144,15 +144,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -168,9 +168,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -187,7 +184,10 @@ "Key": "Name", "Value": "existingStream/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -203,15 +203,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingStream/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -228,12 +228,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -255,15 +255,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -279,9 +279,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -298,7 +295,10 @@ "Key": "Name", "Value": "existingStream/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -314,15 +314,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingStream/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -339,12 +339,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -366,15 +366,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -390,9 +390,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -409,21 +406,24 @@ "Key": "Name", "Value": "existingStream/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingStream/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -440,21 +440,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -471,21 +468,24 @@ "Key": "Name", "Value": "existingStream/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingStream/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -502,21 +502,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -533,21 +530,24 @@ "Key": "Name", "Value": "existingStream/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingStream/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -564,12 +564,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -587,11 +587,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -613,7 +613,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingStream/Vpc" + "Value": "existingStream/Vpc/FlowLog" } ] } @@ -665,7 +665,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingStream/Vpc" + "Value": "existingStream/Vpc/FlowLog" } ] }, @@ -685,10 +685,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -699,10 +695,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existingStream/Vpc" + "Value": "existingStream/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -711,6 +711,15 @@ "VpcKINESISSTREAMSC07D91B5": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingStreamKINESISSTREAMSsecuritygroup14C04A5F", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -723,18 +732,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingStreamKINESISSTREAMSsecuritygroup14C04A5F", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -746,12 +743,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingStreamECRAPIsecuritygroup4E9C019E", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -764,18 +773,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingStreamECRAPIsecuritygroup4E9C019E", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -787,12 +784,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingStreamECRDKRsecuritygroup5C8931AB", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -805,18 +814,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingStreamECRDKRsecuritygroup5C8931AB", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -828,27 +825,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -869,7 +854,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "existingStreamKINESISSTREAMSsecuritygroup14C04A5F": { @@ -1173,6 +1173,11 @@ "Ref": "testfargatekinesisstreamsclusterEA5A2AD7" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1207,7 +1212,11 @@ "TaskDefinition": { "Ref": "testfargatekinesisstreamstaskdef402FE0B3" } - } + }, + "DependsOn": [ + "testfargatekinesisstreamstaskdefTaskRoleDefaultPolicyAE7EF3E4", + "testfargatekinesisstreamstaskdefTaskRole9811F3BE" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingVpc.expected.json index bc14d2b5a..b5492ad94 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.existingVpc.expected.json @@ -18,9 +18,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -37,7 +34,10 @@ "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -53,15 +53,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -78,12 +78,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -105,15 +105,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -129,9 +129,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -148,7 +145,10 @@ "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -164,15 +164,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -189,12 +189,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -216,15 +216,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -240,9 +240,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -259,7 +256,10 @@ "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -275,15 +275,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -300,12 +300,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -327,15 +327,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -351,9 +351,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -370,21 +367,24 @@ "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -401,21 +401,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -432,21 +429,24 @@ "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -463,21 +463,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -494,21 +491,24 @@ "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -525,12 +525,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -548,11 +548,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -574,7 +574,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingVpc/Vpc" + "Value": "existingVpc/Vpc/FlowLog" } ] } @@ -626,7 +626,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingVpc/Vpc" + "Value": "existingVpc/Vpc/FlowLog" } ] }, @@ -646,10 +646,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -660,10 +656,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existingVpc/Vpc" + "Value": "existingVpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -672,6 +672,15 @@ "VpcKINESISSTREAMSC07D91B5": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingVpcKINESISSTREAMSsecuritygroupDE0E9DB9", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -684,18 +693,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingVpcKINESISSTREAMSsecuritygroupDE0E9DB9", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -707,12 +704,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingVpcECRAPIsecuritygroupB3E4A376", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -725,18 +734,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingVpcECRAPIsecuritygroupB3E4A376", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -748,12 +745,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingVpcECRDKRsecuritygroup0500FAE6", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -766,18 +775,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingVpcECRDKRsecuritygroup0500FAE6", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -789,27 +786,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -830,7 +815,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testfargatekinesisstreamsKinesisStreamD31BD614": { @@ -847,9 +847,9 @@ "testfargatekinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarm60755E90": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -860,9 +860,9 @@ "testfargatekinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarmDE16A9F2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -1171,6 +1171,11 @@ "Ref": "testfargatekinesisstreamsclusterEA5A2AD7" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1205,7 +1210,11 @@ "TaskDefinition": { "Ref": "testfargatekinesisstreamstaskdef402FE0B3" } - } + }, + "DependsOn": [ + "testfargatekinesisstreamstaskdefTaskRoleDefaultPolicyAE7EF3E4", + "testfargatekinesisstreamstaskdefTaskRole9811F3BE" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.fargateServiceFromProps.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.fargateServiceFromProps.expected.json index b24e7d147..c5d5c91b5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.fargateServiceFromProps.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.fargateServiceFromProps.expected.json @@ -14,9 +14,9 @@ "testfargatekinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarm60755E90": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -27,9 +27,9 @@ "testfargatekinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarmDE16A9F2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -55,9 +55,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -74,7 +71,10 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -90,15 +90,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -115,12 +115,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -142,15 +142,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -166,9 +166,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -185,7 +182,10 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -201,15 +201,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -226,12 +226,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -253,15 +253,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -277,9 +277,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -296,7 +293,10 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -312,15 +312,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -337,12 +337,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -364,15 +364,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -388,9 +388,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -407,21 +404,24 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -438,21 +438,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -469,21 +466,24 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -500,21 +500,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -531,21 +528,24 @@ "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "fargateServiceFromProps/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -562,12 +562,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -585,11 +585,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -611,7 +611,7 @@ "Tags": [ { "Key": "Name", - "Value": "fargateServiceFromProps/Vpc" + "Value": "fargateServiceFromProps/Vpc/FlowLog" } ] } @@ -663,7 +663,7 @@ "Tags": [ { "Key": "Name", - "Value": "fargateServiceFromProps/Vpc" + "Value": "fargateServiceFromProps/Vpc/FlowLog" } ] }, @@ -683,10 +683,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -697,10 +693,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "fargateServiceFromProps/Vpc" + "Value": "fargateServiceFromProps/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -709,6 +709,15 @@ "VpcKINESISSTREAMSC07D91B5": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "fargateServiceFromPropsKINESISSTREAMSsecuritygroup6FD7F225", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -721,18 +730,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "fargateServiceFromPropsKINESISSTREAMSsecuritygroup6FD7F225", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -744,12 +741,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "fargateServiceFromPropsECRAPIsecuritygroup5784F80B", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -762,18 +771,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "fargateServiceFromPropsECRAPIsecuritygroup5784F80B", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -785,12 +782,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "fargateServiceFromPropsECRDKRsecuritygroup9E1C301F", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -803,18 +812,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "fargateServiceFromPropsECRDKRsecuritygroup9E1C301F", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -826,27 +823,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -867,7 +852,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "fargateServiceFromPropsKINESISSTREAMSsecuritygroup6FD7F225": { @@ -1171,6 +1171,11 @@ "Ref": "testfargatekinesisstreamsclusterEA5A2AD7" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1206,7 +1211,11 @@ "TaskDefinition": { "Ref": "testfargatekinesisstreamstaskdef402FE0B3" } - } + }, + "DependsOn": [ + "testfargatekinesisstreamstaskdefTaskRoleDefaultPolicyAE7EF3E4", + "testfargatekinesisstreamstaskdefTaskRole9811F3BE" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.noArguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.noArguments.expected.json index 62dd5c4b3..6b84aee7b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.noArguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.noArguments.expected.json @@ -14,9 +14,9 @@ "testfargatekinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarm60755E90": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -27,9 +27,9 @@ "testfargatekinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarmDE16A9F2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -55,9 +55,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -74,7 +71,10 @@ "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -90,15 +90,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -115,12 +115,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -142,15 +142,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -166,9 +166,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -185,7 +182,10 @@ "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -201,15 +201,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -226,12 +226,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -253,15 +253,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -277,9 +277,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -296,7 +293,10 @@ "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -312,15 +312,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -337,12 +337,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -364,15 +364,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -388,9 +388,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -407,21 +404,24 @@ "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -438,21 +438,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -469,21 +466,24 @@ "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -500,21 +500,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -531,21 +528,24 @@ "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "noArguments/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -562,12 +562,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -585,11 +585,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -611,7 +611,7 @@ "Tags": [ { "Key": "Name", - "Value": "noArguments/Vpc" + "Value": "noArguments/Vpc/FlowLog" } ] } @@ -663,7 +663,7 @@ "Tags": [ { "Key": "Name", - "Value": "noArguments/Vpc" + "Value": "noArguments/Vpc/FlowLog" } ] }, @@ -683,10 +683,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -697,10 +693,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "noArguments/Vpc" + "Value": "noArguments/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -709,6 +709,15 @@ "VpcKINESISSTREAMSC07D91B5": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "noArgumentsKINESISSTREAMSsecuritygroupA5FDBE79", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -721,18 +730,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "noArgumentsKINESISSTREAMSsecuritygroupA5FDBE79", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -744,12 +741,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "noArgumentsECRAPIsecuritygroup70B67825", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -762,18 +771,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "noArgumentsECRAPIsecuritygroup70B67825", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -785,12 +782,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "noArgumentsECRDKRsecuritygroup881C3744", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -803,18 +812,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "noArgumentsECRDKRsecuritygroup881C3744", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -826,27 +823,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -867,7 +852,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "noArgumentsKINESISSTREAMSsecuritygroupA5FDBE79": { @@ -1171,6 +1171,11 @@ "Ref": "testfargatekinesisstreamsclusterEA5A2AD7" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1205,7 +1210,11 @@ "TaskDefinition": { "Ref": "testfargatekinesisstreamstaskdef402FE0B3" } - } + }, + "DependsOn": [ + "testfargatekinesisstreamstaskdefTaskRoleDefaultPolicyAE7EF3E4", + "testfargatekinesisstreamstaskdefTaskRole9811F3BE" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.streamFromProps.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.streamFromProps.expected.json index 58bee13d3..1e6781fb8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.streamFromProps.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.streamFromProps.expected.json @@ -16,9 +16,9 @@ "testfargatekinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarm60755E90": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -29,9 +29,9 @@ "testfargatekinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarmDE16A9F2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -57,9 +57,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -76,7 +73,10 @@ "Key": "Name", "Value": "streamFromProps/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -92,15 +92,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "streamFromProps/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -117,12 +117,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -144,15 +144,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -168,9 +168,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -187,7 +184,10 @@ "Key": "Name", "Value": "streamFromProps/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -203,15 +203,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "streamFromProps/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -228,12 +228,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -255,15 +255,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -279,9 +279,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -298,7 +295,10 @@ "Key": "Name", "Value": "streamFromProps/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -314,15 +314,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "streamFromProps/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -339,12 +339,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -366,15 +366,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -390,9 +390,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -409,21 +406,24 @@ "Key": "Name", "Value": "streamFromProps/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "streamFromProps/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -440,21 +440,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -471,21 +468,24 @@ "Key": "Name", "Value": "streamFromProps/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "streamFromProps/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -502,21 +502,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -533,21 +530,24 @@ "Key": "Name", "Value": "streamFromProps/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "streamFromProps/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -564,12 +564,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -587,11 +587,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -613,7 +613,7 @@ "Tags": [ { "Key": "Name", - "Value": "streamFromProps/Vpc" + "Value": "streamFromProps/Vpc/FlowLog" } ] } @@ -665,7 +665,7 @@ "Tags": [ { "Key": "Name", - "Value": "streamFromProps/Vpc" + "Value": "streamFromProps/Vpc/FlowLog" } ] }, @@ -685,10 +685,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -699,10 +695,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "streamFromProps/Vpc" + "Value": "streamFromProps/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -711,6 +711,15 @@ "VpcKINESISSTREAMSC07D91B5": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "streamFromPropsKINESISSTREAMSsecuritygroup68986EDF", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -723,18 +732,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "streamFromPropsKINESISSTREAMSsecuritygroup68986EDF", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -746,12 +743,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "streamFromPropsECRAPIsecuritygroupFDB580C0", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -764,18 +773,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "streamFromPropsECRAPIsecuritygroupFDB580C0", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -787,12 +784,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "streamFromPropsECRDKRsecuritygroupEB1BC2F0", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -805,18 +814,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "streamFromPropsECRDKRsecuritygroupEB1BC2F0", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -828,27 +825,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -869,7 +854,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "streamFromPropsKINESISSTREAMSsecuritygroup68986EDF": { @@ -1173,6 +1173,11 @@ "Ref": "testfargatekinesisstreamsclusterEA5A2AD7" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1207,7 +1212,11 @@ "TaskDefinition": { "Ref": "testfargatekinesisstreamstaskdef402FE0B3" } - } + }, + "DependsOn": [ + "testfargatekinesisstreamstaskdefTaskRoleDefaultPolicyAE7EF3E4", + "testfargatekinesisstreamstaskdefTaskRole9811F3BE" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.vpcFromProps.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.vpcFromProps.expected.json index d12c25b61..9532f7b9d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.vpcFromProps.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-kinesisstreams/test/integ.vpcFromProps.expected.json @@ -14,9 +14,9 @@ "testfargatekinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarm60755E90": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -27,9 +27,9 @@ "testfargatekinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarmDE16A9F2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -55,9 +55,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.100.0.0/19", "MapPublicIpOnLaunch": true, @@ -74,7 +71,10 @@ "Key": "Name", "Value": "vpcFromProps/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -90,15 +90,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromProps/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -115,12 +115,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -142,15 +142,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -166,9 +166,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.100.32.0/19", "MapPublicIpOnLaunch": true, @@ -185,7 +182,10 @@ "Key": "Name", "Value": "vpcFromProps/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -201,15 +201,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromProps/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -226,12 +226,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -253,15 +253,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -277,9 +277,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.100.64.0/19", "MapPublicIpOnLaunch": true, @@ -296,7 +293,10 @@ "Key": "Name", "Value": "vpcFromProps/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -312,15 +312,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromProps/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -337,12 +337,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -364,15 +364,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -388,9 +388,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.100.96.0/19", "MapPublicIpOnLaunch": false, @@ -407,21 +404,24 @@ "Key": "Name", "Value": "vpcFromProps/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromProps/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -438,21 +438,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.100.128.0/19", "MapPublicIpOnLaunch": false, @@ -469,21 +466,24 @@ "Key": "Name", "Value": "vpcFromProps/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromProps/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -500,21 +500,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.100.160.0/19", "MapPublicIpOnLaunch": false, @@ -531,21 +528,24 @@ "Key": "Name", "Value": "vpcFromProps/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpcFromProps/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -562,12 +562,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -585,11 +585,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -611,7 +611,7 @@ "Tags": [ { "Key": "Name", - "Value": "vpcFromProps/Vpc" + "Value": "vpcFromProps/Vpc/FlowLog" } ] } @@ -663,7 +663,7 @@ "Tags": [ { "Key": "Name", - "Value": "vpcFromProps/Vpc" + "Value": "vpcFromProps/Vpc/FlowLog" } ] }, @@ -683,10 +683,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -697,10 +693,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "vpcFromProps/Vpc" + "Value": "vpcFromProps/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -709,6 +709,15 @@ "VpcKINESISSTREAMSC07D91B5": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "vpcFromPropsKINESISSTREAMSsecuritygroupB4A9EE00", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -721,18 +730,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "vpcFromPropsKINESISSTREAMSsecuritygroupB4A9EE00", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -744,12 +741,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "vpcFromPropsECRAPIsecuritygroup5AF6C0C4", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -762,18 +771,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "vpcFromPropsECRAPIsecuritygroup5AF6C0C4", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -785,12 +782,24 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "vpcFromPropsECRDKRsecuritygroup822718EC", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -803,18 +812,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "vpcFromPropsECRDKRsecuritygroup822718EC", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -826,27 +823,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -867,7 +852,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "vpcFromPropsKINESISSTREAMSsecuritygroupB4A9EE00": { @@ -1171,6 +1171,11 @@ "Ref": "testfargatekinesisstreamsclusterEA5A2AD7" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1205,7 +1210,11 @@ "TaskDefinition": { "Ref": "testfargatekinesisstreamstaskdef402FE0B3" } - } + }, + "DependsOn": [ + "testfargatekinesisstreamstaskdefTaskRoleDefaultPolicyAE7EF3E4", + "testfargatekinesisstreamstaskdefTaskRole9811F3BE" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/lib/index.ts index e38b9a469..439c81380 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/lib/index.ts @@ -86,7 +86,7 @@ export interface FargateToOpenSearchProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -145,8 +145,9 @@ export class FargateToOpenSearch extends Construct { constructor(scope: Construct, id: string, props: FargateToOpenSearchProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckVpcProps(props); + defaults.CheckOpenSearchProps(props); this.vpc = defaults.buildVpc(scope, { existingVpc: props.existingVpc, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/fargate-opensearch.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/fargate-opensearch.test.ts index 277a64796..e7d7aea5e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/fargate-opensearch.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/fargate-opensearch.test.ts @@ -14,7 +14,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToOpenSearch } from "../lib"; +import { FargateToOpenSearch, FargateToOpenSearchProps } from "../lib"; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; @@ -50,7 +50,7 @@ test('Test domain and cognito domain name', () => { clusterProps: { clusterName: CLUSTER_NAME }, containerDefinitionProps: { CONTAINER_NAME }, fargateTaskDefinitionProps: { family: FAMILY_NAME }, - fargateServiceProps: { servieName: SERVICE_NAME }, + fargateServiceProps: { serviceName: SERVICE_NAME }, openSearchDomainName: DOMAIN_NAME, cognitoDomainName: COGNITO_DOMAIN_NAME }); @@ -71,15 +71,15 @@ test('Check construct properties', () => { const construct = deployStackWithNewResources(stack, publicApi); - expect(construct.vpc !== null); - expect(construct.service !== null); - expect(construct.container !== null); - expect(construct.userPool !== null); - expect(construct.userPoolClient !== null); - expect(construct.identityPool !== null); - expect(construct.openSearchDomain !== null); - expect(construct.openSearchRole !== null); - expect(construct.cloudWatchAlarms !== null); + expect(construct.vpc).toBeDefined(); + expect(construct.service).toBeDefined(); + expect(construct.container).toBeDefined(); + expect(construct.userPool).toBeDefined(); + expect(construct.userPoolClient).toBeDefined(); + expect(construct.identityPool).toBeDefined(); + expect(construct.openSearchDomain).toBeDefined(); + expect(construct.openSearchRole).toBeDefined(); + expect(construct.cloudWatchAlarms).toBeDefined(); }); test('Test cognito dashboard role IAM policy', () => { @@ -720,7 +720,7 @@ test('Existing service/new domain, private API, existing VPC', () => { template.resourceCountIs('AWS::OpenSearchService::Domain', 1); }); -test('Check error for using OpenSearch VPC prop parameter', () => { +test('Confirm CheckOpenSearchProps is called', () => { const stack = new cdk.Stack(); const publicApi = false; @@ -737,3 +737,31 @@ test('Check error for using OpenSearch VPC prop parameter', () => { expect(app).toThrowError("Error - Define VPC using construct parameters not the OpenSearch Service props"); }); + +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const clusterName = "custom-cluster-name"; + const containerName = "custom-container-name"; + const serviceName = "custom-service-name"; + const familyName = "custom-family-name"; + + const props: FargateToOpenSearchProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + openSearchDomainName: DOMAIN_NAME, + cognitoDomainName: COGNITO_DOMAIN_NAME, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToOpenSearch(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/integ.existing-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/integ.existing-resources.expected.json index 7fcf875da..4e43f850b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/integ.existing-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/integ.existing-resources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] }, @@ -647,10 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -661,10 +657,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -673,10 +673,6 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,7 +753,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "existingresourcesECRAPIsecuritygroup78294485": { @@ -987,6 +987,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1021,7 +1026,10 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleB2DEF113" + ] }, "testconstructCognitoUserPoolA4991355": { "Type": "AWS::Cognito::UserPool", @@ -1060,9 +1068,6 @@ "testconstructCognitoUserPoolClient36ACF012": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testconstructCognitoUserPoolA4991355" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -1080,7 +1085,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testconstructCognitoUserPoolA4991355" + } } }, "testconstructCognitoIdentityPool51EFD08D": { @@ -1431,9 +1439,9 @@ "testconstructStatusRedAlarmFBEA96DF": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -1444,9 +1452,9 @@ "testconstructStatusYellowAlarm3B8C3640": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -1457,9 +1465,9 @@ "testconstructFreeStorageSpaceTooLowAlarm08294658": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -1470,9 +1478,9 @@ "testconstructIndexWritesBlockedTooHighAlarm06094A18": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -1483,9 +1491,9 @@ "testconstructAutomatedSnapshotFailureTooHighAlarm29E550A3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -1496,9 +1504,9 @@ "testconstructCPUUtilizationTooHighAlarmD32179B7": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -1509,9 +1517,9 @@ "testconstructJVMMemoryPressureTooHighAlarmFD4175A0": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -1522,9 +1530,9 @@ "testconstructMasterCPUUtilizationTooHighAlarmAA50D0A7": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -1535,9 +1543,9 @@ "testconstructMasterJVMMemoryPressureTooHighAlarm5AE37D64": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/integ.new-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/integ.new-resources.expected.json index d29d2ac1d..1887e8c57 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/integ.new-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-opensearch/test/integ.new-resources.expected.json @@ -38,9 +38,6 @@ "testconstructCognitoUserPoolClient36ACF012": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testconstructCognitoUserPoolA4991355" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -58,7 +55,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testconstructCognitoUserPoolA4991355" + } } }, "testconstructCognitoIdentityPool51EFD08D": { @@ -409,9 +409,9 @@ "testconstructStatusRedAlarmFBEA96DF": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -422,9 +422,9 @@ "testconstructStatusYellowAlarm3B8C3640": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -435,9 +435,9 @@ "testconstructFreeStorageSpaceTooLowAlarm08294658": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -448,9 +448,9 @@ "testconstructIndexWritesBlockedTooHighAlarm06094A18": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -461,9 +461,9 @@ "testconstructAutomatedSnapshotFailureTooHighAlarm29E550A3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -474,9 +474,9 @@ "testconstructCPUUtilizationTooHighAlarmD32179B7": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -487,9 +487,9 @@ "testconstructJVMMemoryPressureTooHighAlarmFD4175A0": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -500,9 +500,9 @@ "testconstructMasterCPUUtilizationTooHighAlarmAA50D0A7": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -513,9 +513,9 @@ "testconstructMasterJVMMemoryPressureTooHighAlarm5AE37D64": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -541,9 +541,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -560,7 +557,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -576,15 +576,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -601,12 +601,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -628,15 +628,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -652,9 +652,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -671,7 +668,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -687,15 +687,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -712,12 +712,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -739,15 +739,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -763,9 +763,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -782,7 +779,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -798,15 +798,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -823,12 +823,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -850,15 +850,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -874,9 +874,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -893,21 +890,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -924,21 +924,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -955,21 +952,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -986,21 +986,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -1017,21 +1014,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -1048,12 +1048,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -1071,11 +1071,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -1097,7 +1097,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] } @@ -1149,7 +1149,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] }, @@ -1169,10 +1169,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1183,10 +1179,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -1195,10 +1195,6 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -1208,6 +1204,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1219,16 +1216,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -1238,6 +1234,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1249,27 +1246,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -1290,7 +1275,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newresourcesECRAPIsecuritygroupE52BAE3F": { @@ -1509,6 +1509,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1543,7 +1548,10 @@ "TaskDefinition": { "Ref": "testconstructtaskdef8BD1F9E4" } - } + }, + "DependsOn": [ + "testconstructtaskdefTaskRoleC60414C4" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-s3/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-s3/lib/index.ts index b852ccd5b..d04dbf50d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-s3/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-s3/lib/index.ts @@ -86,7 +86,7 @@ export interface FargateToS3Props { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -161,8 +161,9 @@ export class FargateToS3 extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckS3Props(props); + defaults.CheckVpcProps(props); if (props.bucketPermissions) { defaults.CheckListValues(['Delete', 'Read', 'Write'], props.bucketPermissions, 'bucket permission'); @@ -239,10 +240,14 @@ export class FargateToS3 extends Construct { } // Add environment variables - const bucketArnEnvironmentVariableName = props.bucketArnEnvironmentVariableName || 'S3_BUCKET_ARN'; + const bucketArnEnvironmentVariableName = this.SetStringWithDefault(props.bucketArnEnvironmentVariableName, 'S3_BUCKET_ARN'); this.container.addEnvironment(bucketArnEnvironmentVariableName, this.s3BucketInterface.bucketArn); - const bucketEnvironmentVariableName = props.bucketEnvironmentVariableName || 'S3_BUCKET_NAME'; + const bucketEnvironmentVariableName = this.SetStringWithDefault(props.bucketEnvironmentVariableName, 'S3_BUCKET_NAME'); this.container.addEnvironment(bucketEnvironmentVariableName, this.s3BucketInterface.bucketName); } + + private SetStringWithDefault(value: string | undefined, defaultValue: string) { + return value || defaultValue; + } } diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/fargate-s3.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/fargate-s3.test.ts index a88b2c016..e82eaafb3 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/fargate-s3.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/fargate-s3.test.ts @@ -14,7 +14,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToS3 } from "../lib"; +import { FargateToS3, FargateToS3Props } from "../lib"; import * as s3 from 'aws-cdk-lib/aws-s3'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; @@ -42,11 +42,11 @@ test('New service/new bucket, public API, new VPC', () => { bucketPermissions: ['Delete', 'Read', 'Write'] }); - expect(construct.vpc !== null); - expect(construct.service !== null); - expect(construct.container !== null); - expect(construct.s3Bucket !== null); - expect(construct.s3BucketInterface !== null); + expect(construct.vpc).toBeDefined(); + expect(construct.service).toBeDefined(); + expect(construct.container).toBeDefined(); + expect(construct.s3Bucket).toBeDefined(); + expect(construct.s3BucketInterface).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::ECS::Service", { @@ -700,3 +700,59 @@ test('Existing service/existing bucket, private API, existing VPC', () => { template.resourceCountIs('AWS::ECS::Service', 1); template.resourceCountIs('AWS::S3::Bucket', 1); }); + +test('New service/new bucket, public API, new VPC', () => { + // An environment with region is required to enable logging on an ALB + const stack = new cdk.Stack(); + const publicApi = true; + const clusterName = "custom-cluster-name"; + const containerName = "custom-container-name"; + const serviceName = "custom-service-name"; + const bucketName = "custom-bucket-name"; + const familyName = "family-name"; + + const props = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + vpcProps: { ipAddresses: ec2.IpAddresses.cidr('172.0.0.0/16') }, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + bucketProps: { bucketName }, + existingBucketObj: new s3.Bucket(stack, 'test-bucket', {}), + logS3AccessLogs: false, + bucketPermissions: ['Delete', 'Read', 'Write'] + }; + const app = () => { + new FargateToS3(stack, 'test-one', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); +}); + +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const clusterName = "custom-cluster-name"; + const containerName = "custom-container-name"; + const serviceName = "custom-service-name"; + const familyName = "custom-family-name"; + + const props: FargateToS3Props = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToS3(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/integ.existing-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/integ.existing-resources.expected.json index 9f38728ad..60e51ad86 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/integ.existing-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/integ.existing-resources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] }, @@ -647,10 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -661,10 +657,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -673,10 +673,6 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,7 +753,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "scrapBucketB11863B7": { @@ -913,18 +913,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -1276,6 +1276,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1310,7 +1315,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/integ.new-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/integ.new-resources.expected.json index 33929811a..df29641ff 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/integ.new-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-s3/test/integ.new-resources.expected.json @@ -290,9 +290,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -309,7 +306,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -325,15 +325,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -350,12 +350,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -377,15 +377,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -401,9 +401,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -420,7 +417,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -436,15 +436,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -461,12 +461,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -488,15 +488,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -512,9 +512,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -531,7 +528,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -547,15 +547,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -572,12 +572,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -599,15 +599,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -623,9 +623,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -642,21 +639,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -673,21 +673,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -704,21 +701,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -735,21 +735,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -766,21 +763,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -797,12 +797,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -820,11 +820,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -846,7 +846,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] } @@ -898,7 +898,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] }, @@ -918,10 +918,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -932,10 +928,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -944,21 +944,6 @@ "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -979,16 +964,27 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -998,6 +994,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1009,16 +1006,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -1028,6 +1024,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1039,7 +1036,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newresourcesECRAPIsecuritygroupE52BAE3F": { @@ -1313,6 +1313,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1347,7 +1352,11 @@ "TaskDefinition": { "Ref": "testconstructtaskdef8BD1F9E4" } - } + }, + "DependsOn": [ + "testconstructtaskdefTaskRoleDefaultPolicyF34A1535", + "testconstructtaskdefTaskRoleC60414C4" + ] }, "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { "Type": "AWS::IAM::Role", @@ -1378,18 +1387,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/lib/index.ts index 4b93937cc..4c03f206e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/lib/index.ts @@ -85,7 +85,7 @@ export interface FargateToSecretsmanagerProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -134,8 +134,9 @@ export class FargateToSecretsmanager extends Construct { constructor(scope: Construct, id: string, props: FargateToSecretsmanagerProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckVpcProps(props); + defaults.CheckSecretsManagerProps(props); // Other permissions for constructs are accepted as arrays, turning grantWriteAccess into // an array to use the same validation function. diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/fargate-secretsmanager.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/fargate-secretsmanager.test.ts index d1d2dd005..1cb79f5d5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/fargate-secretsmanager.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/fargate-secretsmanager.test.ts @@ -14,8 +14,9 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToSecretsmanager } from "../lib"; +import { FargateToSecretsmanager, FargateToSecretsmanagerProps } from "../lib"; import * as ecs from 'aws-cdk-lib/aws-ecs'; +import * as secrets from 'aws-cdk-lib/aws-secretsmanager'; import { buildSecretsManagerSecret } from '@aws-solutions-constructs/core'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; @@ -44,10 +45,10 @@ test('New service/new secret, public API, new VPC', () => { }, }); - expect(construct.vpc !== null); - expect(construct.service !== null); - expect(construct.container !== null); - expect(construct.secret !== null); + expect(construct.vpc).toBeDefined(); + expect(construct.service).toBeDefined(); + expect(construct.container).toBeDefined(); + expect(construct.secret).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::ECS::Service", { @@ -637,4 +638,54 @@ test('Test error invalid secret permission', () => { }; expect(app).toThrowError('Invalid grantWriteAccess submitted - REED'); -}); \ No newline at end of file +}); + +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + + const props: FargateToSecretsmanagerProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + secretProps: { + secretName + }, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToSecretsmanager(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm that CheckSecretsManagerProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + + const props: FargateToSecretsmanagerProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + secretProps: { + secretName + }, + existingSecretObj: new secrets.Secret(stack, 'test', {}), + vpcProps: { }, + }; + + const app = () => { + new FargateToSecretsmanager(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide secretProps or existingSecretObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/integ.existing-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/integ.existing-resources.expected.json index e715fe90d..9355051e6 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/integ.existing-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/integ.existing-resources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,21 +657,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,16 +753,27 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcSECRETSMANAGERF52907C2": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.secretsmanager", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -787,6 +783,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.secretsmanager", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -798,7 +795,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "secret4DA88516": { @@ -1058,6 +1058,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1092,7 +1097,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] }, "existingresourcesSECRETSMANAGERsecuritygroup8010FC5B": { "Type": "AWS::EC2::SecurityGroup", diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/integ.new-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/integ.new-resources.expected.json index a447faa0c..f893bb048 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/integ.new-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-secretsmanager/test/integ.new-resources.expected.json @@ -37,9 +37,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -56,7 +53,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -72,15 +72,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -97,12 +97,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -124,15 +124,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -148,9 +148,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -167,7 +164,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -183,15 +183,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -208,12 +208,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -235,15 +235,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -259,9 +259,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -278,7 +275,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -294,15 +294,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -319,12 +319,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -346,15 +346,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -370,9 +370,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -389,21 +386,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -420,21 +420,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -451,21 +448,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -482,21 +482,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -513,21 +510,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -544,12 +544,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -567,11 +567,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -593,7 +593,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] } @@ -645,7 +645,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] }, @@ -665,11 +665,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -680,21 +675,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSECRETSMANAGERF52907C2": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.secretsmanager", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -704,6 +700,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.secretsmanager", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -715,16 +712,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -734,6 +730,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -745,16 +742,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -764,6 +760,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -775,27 +772,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -816,7 +801,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newresourcesSECRETSMANAGERsecuritygroupD22DA6BC": { @@ -1126,6 +1126,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1160,7 +1165,11 @@ "TaskDefinition": { "Ref": "testconstructtaskdef8BD1F9E4" } - } + }, + "DependsOn": [ + "testconstructtaskdefTaskRoleDefaultPolicyF34A1535", + "testconstructtaskdefTaskRoleC60414C4" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/lib/index.ts index 5db6f1ce9..ccae9849c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/lib/index.ts @@ -86,7 +86,7 @@ export interface FargateToSnsProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -153,8 +153,9 @@ export class FargateToSns extends Construct { constructor(scope: Construct, id: string, props: FargateToSnsProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckSnsProps(props); + defaults.CheckVpcProps(props); this.vpc = defaults.buildVpc(scope, { existingVpc: props.existingVpc, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/fargate-sns.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/fargate-sns.test.ts index 3684666ae..a556cccee 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/fargate-sns.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/fargate-sns.test.ts @@ -14,7 +14,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToSns } from "../lib"; +import { FargateToSns, FargateToSnsProps } from "../lib"; import * as kms from 'aws-cdk-lib/aws-kms'; import * as sns from 'aws-cdk-lib/aws-sns'; import * as ecs from 'aws-cdk-lib/aws-ecs'; @@ -415,7 +415,7 @@ test('Topic is encrypted with imported CMK when set on topicProps.masterKey prop }); }); -test('Topic is encrypted with provided encrytionKeyProps', () => { +test('Topic is encrypted with provided encryptionKeyProps', () => { const stack = new cdk.Stack(undefined, undefined, { env: { account: "123456789012", region: 'us-east-1' }, }); @@ -496,4 +496,60 @@ test('Topic is encrypted with customer managed KMS Key when enable encryption fl ] }, }); -}); \ No newline at end of file +}); + +test('Confirm CheckSnsProps is being called', () => { + // An environment with region is required to enable logging on an ALB + const stack = new cdk.Stack(undefined, undefined, { + env: { account: "123456789012", region: 'us-east-1' }, + }); + const publicApi = false; + const topicName = 'custom-topic-name'; + + const existingVpc = defaults.getTestVpc(stack, publicApi); + + const existingTopic = new sns.Topic(stack, 'MyTopic', { + topicName + }); + + const app = () => { + new FargateToSns(stack, 'test-construct', { + publicApi, + existingVpc, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + existingTopicObject: existingTopic, + topicProps: { + topicName: 'topic-name' + }, + }); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide topicProps or existingTopicObj, but not both.\n/); +}); + +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const clusterName = "custom-cluster-name"; + const containerName = "custom-container-name"; + const serviceName = "custom-service-name"; + const familyName = "custom-family-name"; + + const props: FargateToSnsProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToSns(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.existing-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.existing-resources.expected.json index fb0c00d29..1f5c9d097 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.existing-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.existing-resources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,21 +657,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,16 +753,27 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcSNS5B664381": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.sns", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -787,6 +783,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.sns", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -798,7 +795,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testtopicB3D54793": { @@ -808,7 +808,7 @@ "rules_to_suppress": [ { "id": "W47", - "reason": "Stub topic for placehoder in Integration test" + "reason": "Stub topic for placeholder in Integration test" } ] } @@ -1059,6 +1059,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1093,7 +1098,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] }, "existingresourcesSNSsecuritygroup2696BE98": { "Type": "AWS::EC2::SecurityGroup", diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.existing-resources.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.existing-resources.ts index 96e96a46d..7c3946a6d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.existing-resources.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.existing-resources.ts @@ -27,7 +27,7 @@ stack.templateOptions.description = 'Integration Test with existing VPC, Service const existingVpc = getTestVpc(stack); const existingTopic = new sns.Topic(stack, 'test-topic', {}); -addCfnSuppressRules(existingTopic, [ { id: "W47", reason: "Stub topic for placehoder in Integration test" } ]); +addCfnSuppressRules(existingTopic, [ { id: "W47", reason: "Stub topic for placeholder in Integration test" } ]); const image = ecs.ContainerImage.fromRegistry('nginx'); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.new-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.new-resources.expected.json index bfc2f4231..ee0a2e6b2 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.new-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/integ.new-resources.expected.json @@ -124,9 +124,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -143,7 +140,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -159,15 +159,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -184,12 +184,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -211,15 +211,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -235,9 +235,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -254,7 +251,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -270,15 +270,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -295,12 +295,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -322,15 +322,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -346,9 +346,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -365,7 +362,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -381,15 +381,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -406,12 +406,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -433,15 +433,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -457,9 +457,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -476,21 +473,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -507,21 +507,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -538,21 +535,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -569,21 +569,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -600,21 +597,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -631,12 +631,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -654,11 +654,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -680,7 +680,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] } @@ -732,7 +732,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] }, @@ -752,11 +752,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -767,21 +762,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSNS5B664381": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.sns", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -791,6 +787,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.sns", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -802,16 +799,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -821,6 +817,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -832,16 +829,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -851,6 +847,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -862,27 +859,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -903,7 +888,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newresourcesSNSsecuritygroup4422F7B8": { @@ -1209,6 +1209,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1243,7 +1248,11 @@ "TaskDefinition": { "Ref": "testconstructtaskdef8BD1F9E4" } - } + }, + "DependsOn": [ + "testconstructtaskdefTaskRoleDefaultPolicyF34A1535", + "testconstructtaskdefTaskRoleC60414C4" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/lib/index.ts index 28cb40a7b..992b91b97 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/lib/index.ts @@ -86,7 +86,7 @@ export interface FargateToSqsProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -178,8 +178,9 @@ export class FargateToSqs extends Construct { constructor(scope: Construct, id: string, props: FargateToSqsProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckSqsProps(props); + defaults.CheckVpcProps(props); if (props.queuePermissions) { defaults.CheckListValues(['Read', 'Write'], props.queuePermissions, 'queue permission'); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/fargate-sqs.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/fargate-sqs.test.ts index 092c50666..caa8f921c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/fargate-sqs.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/fargate-sqs.test.ts @@ -14,7 +14,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToSqs } from "../lib"; +import { FargateToSqs, FargateToSqsProps } from "../lib"; import * as kms from 'aws-cdk-lib/aws-kms'; import * as sqs from 'aws-cdk-lib/aws-sqs'; import * as ecs from 'aws-cdk-lib/aws-ecs'; @@ -58,11 +58,11 @@ test('New service/new queue, dlq, public API, new VPC', () => { PlatformVersion: ecs.FargatePlatformVersion.LATEST, }); - expect(construct.vpc !== null); - expect(construct.service !== null); - expect(construct.container !== null); - expect(construct.sqsQueue !== null); - expect(construct.deadLetterQueue !== null); + expect(construct.vpc).toBeDefined(); + expect(construct.service).toBeDefined(); + expect(construct.container).toBeDefined(); + expect(construct.sqsQueue).toBeDefined(); + expect(construct.deadLetterQueue).toBeDefined(); template.hasResourceProperties("AWS::ECS::Service", { ServiceName: serviceName @@ -552,7 +552,7 @@ test('Queue is encrypted with imported CMK when set on queueProps.encryptionMast }); }); -test('Queue is encrypted with provided encrytionKeyProps', () => { +test('Queue is encrypted with provided encryptionKeyProps', () => { const stack = new cdk.Stack(undefined, undefined, { env: { account: "123456789012", region: 'us-east-1' }, }); @@ -581,7 +581,7 @@ test('Queue is encrypted with provided encrytionKeyProps', () => { }); }); -test('Queue is encrypted with SQS-managed KMS key when no other encryption propreties are set', () => { +test('Queue is encrypted with SQS-managed KMS key when no other encryption properties are set', () => { const stack = new cdk.Stack(undefined, undefined, { env: { account: "123456789012", region: 'us-east-1' }, }); @@ -617,4 +617,53 @@ test('Queue is encrypted with customer managed KMS Key when enable encryption fl ] } }); -}); \ No newline at end of file +}); + +test('Confirm CheckSqsProps is called', () => { + + // An environment with region is required to enable logging on an ALB + const stack = new cdk.Stack(); + const publicApi = false; + + const props = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + vpcProps: { ipAddresses: ec2.IpAddresses.cidr('172.0.0.0/16') }, + deployDeadLetterQueue: false, + queueProps: { + removalPolicy: cdk.RemovalPolicy.DESTROY, + }, + existingQueueObj: new sqs.Queue(stack, 'test', {}) + }; + + const app = () => { + new FargateToSqs(stack, 'test-fargate-sqs', props); + }; + expect(app).toThrowError("Error - Either provide queueProps or existingQueueObj, but not both.\n"); +}); + +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const clusterName = "custom-cluster-name"; + const containerName = "custom-container-name"; + const serviceName = "custom-service-name"; + const familyName = "custom-family-name"; + + const props: FargateToSqsProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToSqs(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/integ.existing-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/integ.existing-resources.expected.json index 3983feb0d..3e6aae42c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/integ.existing-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/integ.existing-resources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,21 +657,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,16 +753,27 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcSQSDF166A88": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.sqs", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -787,6 +783,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.sqs", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -798,7 +795,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testqueueA58C838B": { @@ -1078,6 +1078,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1112,7 +1117,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] }, "existingresourcesSQSsecuritygroup0C9178B2": { "Type": "AWS::EC2::SecurityGroup", diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/integ.new-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/integ.new-resources.expected.json index d8a901ff8..b2fe8831d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/integ.new-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sqs/test/integ.new-resources.expected.json @@ -99,9 +99,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -118,7 +115,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -134,15 +134,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -159,12 +159,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -186,15 +186,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -210,9 +210,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -229,7 +226,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -245,15 +245,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -270,12 +270,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -297,15 +297,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -321,9 +321,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -340,7 +337,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -356,15 +356,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -381,12 +381,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -408,15 +408,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -432,9 +432,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -451,21 +448,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -482,21 +482,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -513,21 +510,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -544,21 +544,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -575,21 +572,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -606,12 +606,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -629,11 +629,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -655,7 +655,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] } @@ -707,7 +707,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] }, @@ -727,11 +727,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -742,21 +737,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSQSDF166A88": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.sqs", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -766,6 +762,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.sqs", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -777,16 +774,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -796,6 +792,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -807,16 +804,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -826,6 +822,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -837,27 +834,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -878,7 +863,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newresourcesSQSsecuritygroup1D95FDB1": { @@ -1191,6 +1191,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1225,7 +1230,11 @@ "TaskDefinition": { "Ref": "testconstructtaskdef8BD1F9E4" } - } + }, + "DependsOn": [ + "testconstructtaskdefTaskRoleDefaultPolicyF34A1535", + "testconstructtaskdefTaskRoleC60414C4" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/lib/index.ts index 69474adac..39a1fe36e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/lib/index.ts @@ -85,7 +85,7 @@ export interface FargateToSsmstringparameterProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -133,8 +133,8 @@ export class FargateToSsmstringparameter extends Construct { constructor(scope: Construct, id: string, props: FargateToSsmstringparameterProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckVpcProps(props); // Other permissions for constructs are accepted as arrays, turning stringParameterPermissions into // an array to use the same validation function. diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/fargate-ssmstringparameter.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/fargate-ssmstringparameter.test.ts index 09ad54249..55fbb5dcc 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/fargate-ssmstringparameter.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/fargate-ssmstringparameter.test.ts @@ -14,7 +14,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToSsmstringparameter } from "../lib"; +import { FargateToSsmstringparameter, FargateToSsmstringparameterProps } from "../lib"; import * as ssm from 'aws-cdk-lib/aws-ssm'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; @@ -47,10 +47,10 @@ test('New service/new parameter store, public API, new VPC', () => { }, }); - expect(construct.vpc !== null); - expect(construct.service !== null); - expect(construct.container !== null); - expect(construct.stringParameter !== null); + expect(construct.vpc).toBeDefined(); + expect(construct.service).toBeDefined(); + expect(construct.container).toBeDefined(); + expect(construct.stringParameter).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::ECS::Service", { @@ -810,6 +810,32 @@ test('Test error no existing object or prop provided', () => { expect(app).toThrowError('existingStringParameterObj or stringParameterProps needs to be provided.'); }); +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + + const props: FargateToSsmstringparameterProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + stringParameterProps: { + parameterName, + stringValue + }, + existingVpc: defaults.getTestVpc(stack), + vpcProps: { }, + }; + + const app = () => { + new FargateToSsmstringparameter(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + function createSsmParameterStore(stack: cdk.Stack) { return new ssm.StringParameter(stack, 'Parameter', { allowedPattern, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/integ.existing-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/integ.existing-resources.expected.json index dffa1b1c6..a02651ced 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/integ.existing-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/integ.existing-resources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,21 +657,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-resources/Vpc" + "Value": "existing-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,16 +753,27 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcSSM173B3B5B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ssm", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -787,6 +783,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ssm", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -798,17 +795,20 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "Parameter9E1B4FBA": { "Type": "AWS::SSM::Parameter", "Properties": { - "Type": "String", - "Value": "Foo", "AllowedPattern": ".*", "Description": "The value Foo", - "Name": "FooParameter" + "Name": "FooParameter", + "Type": "String", + "Value": "Foo" } }, "existingresourcesECRAPIsecuritygroup78294485": { @@ -1091,6 +1091,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1125,7 +1130,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] }, "existingresourcesSSMsecuritygroup5CE82B38": { "Type": "AWS::EC2::SecurityGroup", diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/integ.new-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/integ.new-resources.expected.json index 57b7aa520..8b5a629be 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/integ.new-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-ssmstringparameter/test/integ.new-resources.expected.json @@ -4,9 +4,9 @@ "testconstructstringParameter4A9E7765": { "Type": "AWS::SSM::Parameter", "Properties": { + "Name": "FooParameter", "Type": "String", - "Value": "Foo", - "Name": "FooParameter" + "Value": "Foo" } }, "Vpc8378EB38": { @@ -27,9 +27,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -46,7 +43,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -62,15 +62,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -87,12 +87,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -114,15 +114,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -138,9 +138,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -157,7 +154,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -173,15 +173,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -198,12 +198,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -225,15 +225,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -249,9 +249,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -268,7 +265,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -284,15 +284,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -309,12 +309,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -336,15 +336,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -360,9 +360,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -379,21 +376,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -410,21 +410,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -441,21 +438,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -472,21 +472,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -503,21 +500,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -534,12 +534,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -557,11 +557,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -583,7 +583,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] } @@ -635,7 +635,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] }, @@ -655,11 +655,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -670,21 +665,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSSM173B3B5B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ssm", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -694,6 +690,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ssm", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -705,16 +702,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -724,6 +720,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -735,16 +732,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -754,6 +750,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -765,27 +762,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -806,7 +791,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newresourcesSSMsecuritygroupBA8A3B0D": { @@ -1124,6 +1124,11 @@ "Ref": "testconstructcluster7B6231C5" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1158,7 +1163,11 @@ "TaskDefinition": { "Ref": "testconstructtaskdef8BD1F9E4" } - } + }, + "DependsOn": [ + "testconstructtaskdefTaskRoleDefaultPolicyF34A1535", + "testconstructtaskdefTaskRoleC60414C4" + ] } }, "Parameters": { diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/lib/index.ts index 056c3f2d1..cbe37a755 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/lib/index.ts @@ -88,7 +88,7 @@ export interface FargateToStepfunctionsProps { /** * A Fargate Service already instantiated (probably by another Solutions Construct). If * this is specified, then no props defining a new service can be provided, including: - * existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps, + * existingImageObject, ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, * ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value * is provided, then existingContainerDefinitionObject must be provided as well. * @@ -138,8 +138,8 @@ export class FargateToStepfunctions extends Construct { constructor(scope: Construct, id: string, props: FargateToStepfunctionsProps) { super(scope, id); - defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckVpcProps(props); this.vpc = defaults.buildVpc(scope, { existingVpc: props.existingVpc, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/fargate-stepfunctions.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/fargate-stepfunctions.test.ts index 66910d5da..6b065aa35 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/fargate-stepfunctions.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/fargate-stepfunctions.test.ts @@ -13,7 +13,7 @@ import * as defaults from '@aws-solutions-constructs/core'; import * as cdk from "aws-cdk-lib"; -import { FargateToStepfunctions } from "../lib"; +import { FargateToStepfunctions, FargateToStepfunctionsProps } from "../lib"; import * as stepfunctions from 'aws-cdk-lib/aws-stepfunctions'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; @@ -309,6 +309,30 @@ test('Check for custom log group props', () => { }); }); +test('Confirm that CheckVpcProps was called', () => { + const stack = new cdk.Stack(); + const publicApi = true; + + const props: FargateToStepfunctionsProps = { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + stateMachineProps: testStateMachineProps(stack), + existingVpc: defaults.getTestVpc(stack), + vpcProps: { ipAddresses: ec2.IpAddresses.cidr(testCidr) }, + }; + + const app = () => { + new FargateToStepfunctions(stack, 'test-construct', props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + function createFargateConstructWithNewResources(stack: cdk.Stack, publicApi: boolean) { return new FargateToStepfunctions(stack, 'test-construct', { publicApi, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.expected.json index f8b2fa26e..b220c2404 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-resources/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ] }, @@ -647,10 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -661,10 +657,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-resources/Vpc" + "Value": "new-resources/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -673,10 +673,6 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,16 +753,27 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcSTEPFUNCTIONS550F8CB6": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.states", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -787,6 +783,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.states", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -798,7 +795,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newresourcesECRAPIsecuritygroupE52BAE3F": { @@ -1037,6 +1037,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1071,7 +1076,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] }, "testconstructStateMachineLogGroup2EB4F48B": { "Type": "AWS::Logs::LogGroup", @@ -1200,12 +1209,6 @@ "testconstructStateMachine3333AAA9": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "testconstructStateMachineRoleA396E5D3", - "Arn" - ] - }, "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", "LoggingConfiguration": { "Destinations": [ @@ -1221,6 +1224,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "testconstructStateMachineRoleA396E5D3", + "Arn" + ] } }, "DependsOn": [ @@ -1233,9 +1242,8 @@ "testconstructExecutionFailedAlarmE9CEA29E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -1244,6 +1252,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -1254,9 +1263,8 @@ "testconstructExecutionThrottledAlarmEE993A2A": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -1265,6 +1273,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -1275,9 +1284,8 @@ "testconstructExecutionAbortedAlarm2BC3DDB8": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -1286,6 +1294,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.expected.json b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.expected.json index 8da9fc9df..2d6f8627b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "no-cloudwatch-alarms/Vpc" + "Value": "no-cloudwatch-alarms/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "no-cloudwatch-alarms/Vpc" + "Value": "no-cloudwatch-alarms/Vpc/FlowLog" } ] }, @@ -647,10 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -661,10 +657,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "no-cloudwatch-alarms/Vpc" + "Value": "no-cloudwatch-alarms/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -673,10 +673,6 @@ "VpcECRAPI9A3B6A2B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.api", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -686,6 +682,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.api", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -697,16 +694,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcECRDKR604E039F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -716,6 +712,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -727,27 +724,15 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -768,16 +753,27 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcSTEPFUNCTIONS550F8CB6": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": "com.amazonaws.us-east-1.states", - "VpcId": { - "Ref": "Vpc8378EB38" - }, "PrivateDnsEnabled": true, "SecurityGroupIds": [ { @@ -787,6 +783,7 @@ ] } ], + "ServiceName": "com.amazonaws.us-east-1.states", "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -798,7 +795,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "nocloudwatchalarmsECRAPIsecuritygroupA72029F8": { @@ -1037,6 +1037,11 @@ "Ref": "testclusterDF8B0D19" }, "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, "MaximumPercent": 150, "MinimumHealthyPercent": 75 }, @@ -1071,7 +1076,11 @@ "TaskDefinition": { "Ref": "testtaskdefF924AD58" } - } + }, + "DependsOn": [ + "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "testtaskdefTaskRoleB2DEF113" + ] }, "testconstructStateMachineLogGroup2EB4F48B": { "Type": "AWS::Logs::LogGroup", @@ -1180,12 +1189,6 @@ "testconstructStateMachine3333AAA9": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "testconstructStateMachineRoleA396E5D3", - "Arn" - ] - }, "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", "LoggingConfiguration": { "Destinations": [ @@ -1201,6 +1204,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "testconstructStateMachineRoleA396E5D3", + "Arn" + ] } }, "DependsOn": [ diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-kinesisfirehose-s3/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-iot-kinesisfirehose-s3/lib/index.ts index 97431270c..27e288be1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-kinesisfirehose-s3/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-kinesisfirehose-s3/lib/index.ts @@ -19,7 +19,6 @@ import * as logs from 'aws-cdk-lib/aws-logs'; // Note: To ensure CDKv2 compatibility, keep the import statement for Construct separate import { Construct } from 'constructs'; import * as defaults from '@aws-solutions-constructs/core'; -import { overrideProps } from '@aws-solutions-constructs/core'; import { KinesisFirehoseToS3 } from '@aws-solutions-constructs/aws-kinesisfirehose-s3'; /** @@ -96,8 +95,6 @@ export class IotToKinesisFirehoseToS3 extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); - const firehoseToS3 = new KinesisFirehoseToS3(this, 'KinesisFirehoseToS3', { kinesisFirehoseProps: props.kinesisFirehoseProps, existingBucketObj: props.existingBucketObj, @@ -134,7 +131,7 @@ export class IotToKinesisFirehoseToS3 extends Construct { roleArn: this.iotActionsRole.roleArn } }]); - const iotTopicProps = overrideProps(defaultIotTopicProps, props.iotTopicRuleProps, true); + const iotTopicProps = defaults.overrideProps(defaultIotTopicProps, props.iotTopicRuleProps, true); // Create the IoT topic rule this.iotTopicRule = new iot.CfnTopicRule(this, 'IotTopic', iotTopicProps); diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-kinesisfirehose-s3/test/test.iot-kinesisfirehose-s3.test.ts b/source/patterns/@aws-solutions-constructs/aws-iot-kinesisfirehose-s3/test/test.iot-kinesisfirehose-s3.test.ts index d9bb4f85a..b8f6352e4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-kinesisfirehose-s3/test/test.iot-kinesisfirehose-s3.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-kinesisfirehose-s3/test/test.iot-kinesisfirehose-s3.test.ts @@ -111,26 +111,25 @@ test('check firehose and s3 overrides', () => { IntervalInSeconds: 600, SizeInMBs: 55 } - }}); + } + }); }); + test('check properties', () => { const stack = new cdk.Stack(); const construct: IotToKinesisFirehoseToS3 = deploy(stack); - expect(construct.iotTopicRule !== null); - expect(construct.kinesisFirehose !== null); - expect(construct.s3Bucket !== null); - expect(construct.iotActionsRole !== null); - expect(construct.kinesisFirehoseRole !== null); - expect(construct.kinesisFirehoseLogGroup !== null); - expect(construct.s3LoggingBucket !== null); + expect(construct.iotTopicRule).toBeDefined(); + expect(construct.kinesisFirehose).toBeDefined(); + expect(construct.s3Bucket).toBeDefined(); + expect(construct.iotActionsRole).toBeDefined(); + expect(construct.kinesisFirehoseRole).toBeDefined(); + expect(construct.kinesisFirehoseLogGroup).toBeDefined(); + expect(construct.s3LoggingBucket).toBeDefined(); }); -// -------------------------------------------------------------- -// Test bad call with existingBucket and bucketProps -// -------------------------------------------------------------- -test("Test bad call with existingBucket and bucketProps", () => { +test("Confirm CheckS3Props is being called", () => { // Stack const stack = new cdk.Stack(); @@ -154,12 +153,9 @@ test("Test bad call with existingBucket and bucketProps", () => { }); }; // Assertion - expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); + expect(app).toThrowError("Error - Either provide bucketProps or existingBucketObj, but not both.\n"); }); -// -------------------------------------------------------------- -// s3 bucket with bucket, loggingBucket, and auto delete objects -// -------------------------------------------------------------- test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { const stack = new cdk.Stack(); @@ -197,9 +193,6 @@ test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { }); }); -// -------------------------------------------------------------- -// Test bad call with logS3AccessLogs as false and bucketProps -// -------------------------------------------------------------- test("Test bad call with logS3AccessLogs as false and bucketProps", () => { // Stack const stack = new cdk.Stack(); @@ -225,9 +218,6 @@ test("Test bad call with logS3AccessLogs as false and bucketProps", () => { expect(app).toThrowError('Error - If logS3AccessLogs is false, supplying loggingBucketProps or existingLoggingBucketObj is invalid.\n'); }); -// -------------------------------------------------------------- -// s3 bucket with one content bucket and no logging bucket -// -------------------------------------------------------------- test('s3 bucket with one content bucket and no logging bucket', () => { const stack = new cdk.Stack(); diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-kinesisstreams/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-iot-kinesisstreams/lib/index.ts index ffb17e44e..6c27d29fd 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-kinesisstreams/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-kinesisstreams/lib/index.ts @@ -65,7 +65,7 @@ export class IotToKinesisStreams extends Construct { */ constructor(scope: Construct, id: string, props: IotToKinesisStreamsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckKinesisStreamProps(props); // Set up the Kinesis Stream this.kinesisStream = defaults.buildKinesisStream(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-kinesisstreams/test/test.iot-kinesisstreams.test.ts b/source/patterns/@aws-solutions-constructs/aws-iot-kinesisstreams/test/test.iot-kinesisstreams.test.ts index 66134bc27..daecaa05b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-kinesisstreams/test/test.iot-kinesisstreams.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-kinesisstreams/test/test.iot-kinesisstreams.test.ts @@ -210,7 +210,7 @@ test('check existing action in topic rule props', () => { template.resourceCountIs('AWS::Kinesis::Stream', 2); }); -test('check name confict', () => { +test('check name confect', () => { const stack = new cdk.Stack(); const props: IotToKinesisStreamsProps = { @@ -241,7 +241,7 @@ test('check construct chaining', () => { template.resourceCountIs('AWS::Kinesis::Stream', 1); }); -test('check error when stream props and existing stream is supplied', () => { +test('Confirm call to CheckKinesisStreamProps', () => { const stack = new cdk.Stack(); const existingKinesisStream = new kinesis.Stream(stack, `existing-stream`, {}); @@ -254,5 +254,5 @@ test('check error when stream props and existing stream is supplied', () => { const app = () => { new IotToKinesisStreams(stack, 'test-iot-kinesisstreams', props); }; - expect(app).toThrowError(); -}); \ No newline at end of file + expect(app).toThrowError('Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/README.md b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/README.md index 7c988d6d3..df66209e9 100755 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/README.md @@ -121,7 +121,7 @@ new IotToLambdaToDynamoDB(this, "test-iot-lambda-dynamodb-stack", new IotToLambd |existingTableObj?|[`dynamodb.Table`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html)|Existing instance of DynamoDB table object, providing both this and `dynamoTableProps` will cause an error.| |tableEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the name of the DynamoDB table. Default: DDB_TABLE_NAME | |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and a Gateway Endpoint will be created in the VPC for Amazon DynamoDB. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| ## Pattern Properties @@ -158,4 +158,4 @@ Out of the box implementation of the Construct without any override will set the ![Architecture Diagram](architecture.png) *** -© Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. \ No newline at end of file +© Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/lib/index.ts index 7426ed2a2..d35dbe0fa 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/lib/index.ts @@ -94,7 +94,6 @@ export class IotToLambdaToDynamoDB extends Construct { */ constructor(scope: Construct, id: string, props: IotToLambdaToDynamoDBProps) { super(scope, id); - defaults.CheckProps(props); // Other permissions for constructs are accepted as arrays, turning tablePermissions into // an array to use the same validation function. diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/integ.iot-lambda-dynamodb.expected.json b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/integ.iot-lambda-dynamodb.expected.json index c0e6aca1f..60fbe3fb2 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/integ.iot-lambda-dynamodb.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/integ.iot-lambda-dynamodb.expected.json @@ -126,12 +126,6 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "testiotlambdadynamodbstackLambdaToDynamoDBLambdaFunctionServiceRole31915E05", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -141,6 +135,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testiotlambdadynamodbstackLambdaToDynamoDBLambdaFunctionServiceRole31915E05", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -191,19 +191,19 @@ "testiotlambdadynamodbstackLambdaToDynamoDBDynamoTableE17E5733": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/integ.with-vpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/integ.with-vpc.expected.json index acab0fcdd..5b46748dc 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/integ.with-vpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/integ.with-vpc.expected.json @@ -167,12 +167,6 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "testiotlambdadynamodbstackLambdaToDynamoDBLambdaFunctionServiceRole31915E05", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -182,6 +176,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testiotlambdadynamodbstackLambdaToDynamoDBLambdaFunctionServiceRole31915E05", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -261,19 +261,19 @@ "testiotlambdadynamodbstackLambdaToDynamoDBDynamoTableE17E5733": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, @@ -302,9 +302,6 @@ "testiotlambdadynamodbstackVpcisolatedSubnet1Subnet3AB7ADA5": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "testiotlambdadynamodbstackVpc1986A4BB" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -321,21 +318,24 @@ "Key": "Name", "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "testiotlambdadynamodbstackVpc1986A4BB" + } } }, "testiotlambdadynamodbstackVpcisolatedSubnet1RouteTableE28AAAB5": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "testiotlambdadynamodbstackVpc1986A4BB" - }, "Tags": [ { "Key": "Name", "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "testiotlambdadynamodbstackVpc1986A4BB" + } } }, "testiotlambdadynamodbstackVpcisolatedSubnet1RouteTableAssociationFAA18521": { @@ -352,9 +352,6 @@ "testiotlambdadynamodbstackVpcisolatedSubnet2SubnetBDEE1FAE": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "testiotlambdadynamodbstackVpc1986A4BB" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "testiotlambdadynamodbstackVpc1986A4BB" + } } }, "testiotlambdadynamodbstackVpcisolatedSubnet2RouteTableAF607A65": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "testiotlambdadynamodbstackVpc1986A4BB" - }, "Tags": [ { "Key": "Name", "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "testiotlambdadynamodbstackVpc1986A4BB" + } } }, "testiotlambdadynamodbstackVpcisolatedSubnet2RouteTableAssociation80ECEB84": { @@ -402,9 +402,6 @@ "testiotlambdadynamodbstackVpcisolatedSubnet3Subnet5D41F483": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "testiotlambdadynamodbstackVpc1986A4BB" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -421,21 +418,24 @@ "Key": "Name", "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "testiotlambdadynamodbstackVpc1986A4BB" + } } }, "testiotlambdadynamodbstackVpcisolatedSubnet3RouteTableE56B664A": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "testiotlambdadynamodbstackVpc1986A4BB" - }, "Tags": [ { "Key": "Name", "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "testiotlambdadynamodbstackVpc1986A4BB" + } } }, "testiotlambdadynamodbstackVpcisolatedSubnet3RouteTableAssociationF06E774F": { @@ -467,7 +467,7 @@ "Tags": [ { "Key": "Name", - "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc" + "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc/FlowLog" } ] } @@ -519,7 +519,7 @@ "Tags": [ { "Key": "Name", - "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc" + "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc/FlowLog" } ] }, @@ -539,10 +539,6 @@ "testiotlambdadynamodbstackVpcFlowLogC88B17DB": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "testiotlambdadynamodbstackVpc1986A4BB" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "testiotlambdadynamodbstackVpcFlowLogIAMRole84CD262B", @@ -553,10 +549,14 @@ "LogGroupName": { "Ref": "testiotlambdadynamodbstackVpcFlowLogLogGroup0BA54CDB" }, + "ResourceId": { + "Ref": "testiotlambdadynamodbstackVpc1986A4BB" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc" + "Value": "with-vpc/test-iot-lambda-dynamodb-stack/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -565,6 +565,17 @@ "testiotlambdadynamodbstackVpcDDBD215AB1B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "RouteTableIds": [ + { + "Ref": "testiotlambdadynamodbstackVpcisolatedSubnet1RouteTableE28AAAB5" + }, + { + "Ref": "testiotlambdadynamodbstackVpcisolatedSubnet2RouteTableAF607A65" + }, + { + "Ref": "testiotlambdadynamodbstackVpcisolatedSubnet3RouteTableE56B664A" + } + ], "ServiceName": { "Fn::Join": [ "", @@ -577,21 +588,10 @@ ] ] }, + "VpcEndpointType": "Gateway", "VpcId": { "Ref": "testiotlambdadynamodbstackVpc1986A4BB" - }, - "RouteTableIds": [ - { - "Ref": "testiotlambdadynamodbstackVpcisolatedSubnet1RouteTableE28AAAB5" - }, - { - "Ref": "testiotlambdadynamodbstackVpcisolatedSubnet2RouteTableAF607A65" - }, - { - "Ref": "testiotlambdadynamodbstackVpcisolatedSubnet3RouteTableE56B664A" - } - ], - "VpcEndpointType": "Gateway" + } } }, "testiotlambdadynamodbstackIotToLambdaIotTopic74F5E3BB": { diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/iot-lambda-dynamodb.test.ts b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/iot-lambda-dynamodb.test.ts index 5a2aca4f6..e571342db 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/iot-lambda-dynamodb.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/iot-lambda-dynamodb.test.ts @@ -366,9 +366,6 @@ test('check lambda function custom environment variable', () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC without vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC without vpcProps", () => { // Stack const stack = new cdk.Stack(); @@ -425,9 +422,6 @@ test("Test minimal deployment that deploys a VPC without vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC w/vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC w/vpcProps", () => { // Stack const stack = new cdk.Stack(); @@ -490,9 +484,6 @@ test("Test minimal deployment that deploys a VPC w/vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC", () => { // Stack const stack = new cdk.Stack(); @@ -544,16 +535,12 @@ test("Test minimal deployment with an existing VPC", () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC and existing Lambda function not in a VPC -// -// buildLambdaFunction should throw an error if the Lambda function is not -// attached to a VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC and existing Lambda function not in a VPC", () => { // Stack const stack = new cdk.Stack(); + // buildLambdaFunction should throw an error if the Lambda function is not + // attached to a VPC const testLambdaFunction = new lambda.Function(stack, 'test-lambda', { runtime: lambda.Runtime.NODEJS_16_X, handler: "index.handler", @@ -584,10 +571,7 @@ test("Test minimal deployment with an existing VPC and existing Lambda function }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { +test("Confirm CheckVpcProps is called", () => { // Stack const stack = new cdk.Stack(); @@ -614,5 +598,83 @@ test("Test bad call with existingVpc and deployVpc", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm CheckLambdaProps is being called', () => { + const stack = new cdk.Stack(); + const existingLambdaObj = new lambda.Function(stack, 'ExistingLambda', { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: IotToLambdaToDynamoDBProps = { + iotTopicRuleProps: { + topicRulePayload: { + ruleDisabled: false, + description: "Processing of DTC messages from the AWS Connected Vehicle Solution.", + sql: "SELECT * FROM 'connectedcar/dtc/#'", + actions: [] + } + }, + existingLambdaObj, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + } + }; + + const app = () => { + new IotToLambdaToDynamoDB(stack, 'test-iot-lambda-ddb', props); + }; + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); }); + +// NOTE: existingTableObj was omitted from the interface for this construct, +// so this test cannot be run. Leaving it here so it can be used if/when existingTableObj +// is added to the interface +// +// test("Confirm CheckDynamoDBProps is getting called", () => { +// const stack = new cdk.Stack(); +// const tableName = 'table-name'; + +// const existingTable = new dynamodb.Table(stack, 'MyTablet', { +// tableName, +// partitionKey: { +// name: 'id', +// type: dynamodb.AttributeType.STRING +// } +// }); + +// const props: IotToLambdaToDynamoDBProps = { +// lambdaFunctionProps: { +// code: lambda.Code.fromAsset(`${__dirname}/lambda`), +// runtime: lambda.Runtime.NODEJS_16_X, +// handler: 'index.handler' +// }, +// iotTopicRuleProps: { +// topicRulePayload: { +// ruleDisabled: false, +// description: "Processing of DTC messages from the AWS Connected Vehicle Solution.", +// sql: "SELECT * FROM 'connectedcar/dtc/#'", +// actions: [] +// } +// }, +// existingTableObj: existingTable, +// dynamoTableProps: { +// tableName, +// partitionKey: { +// name: 'id', +// type: dynamodb.AttributeType.STRING +// }, +// }, +// }; + +// const app = () => { +// new IotToLambdaToDynamoDB(stack, 'test-iot-lambda-dynamodb-stack', props); +// }; + +// expect(app).toThrowError('Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'); +// }); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-iot-lambda/lib/index.ts index 16f4a1d7b..42b2b727d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda/lib/index.ts @@ -57,7 +57,7 @@ export class IotToLambda extends Construct { */ constructor(scope: Construct, id: string, props: IotToLambdaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckLambdaProps(props); this.lambdaFunction = defaults.buildLambdaFunction(this, { existingLambdaObj: props.existingLambdaObj, diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/integ.iot-lambda-new-func.expected.json b/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/integ.iot-lambda-new-func.expected.json index 42fd24970..1966d0657 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/integ.iot-lambda-new-func.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/integ.iot-lambda-new-func.expected.json @@ -98,18 +98,18 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "testiotlambdaintegrationLambdaFunctionServiceRole27C3EE41", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testiotlambdaintegrationLambdaFunctionServiceRole27C3EE41", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/integ.iot-lambda-use-existing-func.expected.json b/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/integ.iot-lambda-use-existing-func.expected.json index 9026e8587..ae6e70b8a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/integ.iot-lambda-use-existing-func.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/integ.iot-lambda-use-existing-func.expected.json @@ -98,18 +98,18 @@ }, "S3Key": "42a35bbf0dec9ef0ac5b0dde87e71a1b8929e8d2d178dd09ccfb2c928ec0198c.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/iot-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/iot-lambda.test.ts index 2752a632e..05a6e84c6 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/iot-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda/test/iot-lambda.test.ts @@ -271,8 +271,8 @@ test('check properties', () => { const construct: IotToLambda = deployNewFunc(stack); - expect(construct.iotTopicRule !== null); - expect(construct.lambdaFunction !== null); + expect(construct.iotTopicRule).toBeDefined(); + expect(construct.lambdaFunction).toBeDefined(); }); test('check exception for Missing existingObj from props for deploy = false', () => { @@ -315,4 +315,36 @@ test('check deploy = true and no prop', () => { } catch (e) { expect(e).toBeInstanceOf(Error); } -}); \ No newline at end of file +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: IotToLambdaProps = { + iotTopicRuleProps: { + topicRulePayload: { + ruleDisabled: false, + description: "Processing of DTC messages from the AWS Connected Vehicle Solution.", + sql: "SELECT * FROM 'connectedcar/dtc/#'", + actions: [] + } + }, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new IotToLambda(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-s3/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-iot-s3/lib/index.ts index 5afb9a05c..232e67009 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-s3/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-s3/lib/index.ts @@ -82,7 +82,7 @@ export class IotToS3 extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); + defaults.CheckS3Props(props); // Setup S3 Bucket if (!props.existingBucketInterface) { diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/integ.iot-s3-existing-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/integ.iot-s3-existing-bucket.expected.json index 8f8b07b38..423e55a0f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/integ.iot-s3-existing-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/integ.iot-s3-existing-bucket.expected.json @@ -142,18 +142,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -283,109 +283,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/integ.iot-s3-new-encrypted-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/integ.iot-s3-new-encrypted-bucket.expected.json index 95a67bf11..c447bea63 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/integ.iot-s3-new-encrypted-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/integ.iot-s3-new-encrypted-bucket.expected.json @@ -3,6 +3,7 @@ "existingKeyB52D6AF1": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -30,8 +31,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/iot-s3.test.ts b/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/iot-s3.test.ts index b14708f12..ac95bcb04 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/iot-s3.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-s3/test/iot-s3.test.ts @@ -76,7 +76,7 @@ test('check for default props', () => { expect(construct.iotTopicRule).toBeDefined(); }); -test('check for overriden props', () => { +test('check for overridden props', () => { const stack = new cdk.Stack(); const props: IotToS3Props = { iotTopicRuleProps: { @@ -325,4 +325,26 @@ test('check for chaining of resource', () => { const template = Template.fromStack(stack); template.resourceCountIs('AWS::IoT::TopicRule', 2); template.resourceCountIs('AWS::S3::Bucket', 2); -}); \ No newline at end of file +}); + +test('Confirm CHeckS3Props is being called', () => { + const stack = new cdk.Stack(); + + const props: IotToS3Props = { + iotTopicRuleProps: { + topicRulePayload: { + ruleDisabled: false, + description: "process solutions constructs messages", + sql: "SELECT * FROM 'solutions/constructs'", + actions: [] + } + }, + bucketProps: {}, + existingBucketInterface: new s3.Bucket(stack, 'test-bucket', {}), + }; + const app = () => { + new IotToS3(stack, 'test-iot-s3-integration', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-sqs/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-iot-sqs/lib/index.ts index 13a46e435..e75e16eb9 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-sqs/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-sqs/lib/index.ts @@ -102,7 +102,7 @@ export class IotToSqs extends Construct { */ constructor(scope: Construct, id: string, props: IotToSqsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckSqsProps(props); // Setup the dead letter queue, if applicable this.deadLetterQueue = defaults.buildDeadLetterQueue(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-sqs/test/iot-sqs.test.ts b/source/patterns/@aws-solutions-constructs/aws-iot-sqs/test/iot-sqs.test.ts index c4d6cb3f8..201465b17 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-sqs/test/iot-sqs.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-sqs/test/iot-sqs.test.ts @@ -12,16 +12,13 @@ */ // Imports -import { Stack } from "aws-cdk-lib"; +import { Stack, RemovalPolicy } from "aws-cdk-lib"; import { IotToSqs, IotToSqsProps } from "../lib"; import { Template } from 'aws-cdk-lib/assertions'; import * as sqs from 'aws-cdk-lib/aws-sqs'; import * as kms from 'aws-cdk-lib/aws-kms'; import * as defaults from '@aws-solutions-constructs/core'; -// -------------------------------------------------------------- -// Pattern deployment with default props -// -------------------------------------------------------------- test('Pattern deployment with default props', () => { // Initial Setup const stack = new Stack(); @@ -81,9 +78,6 @@ test('Pattern deployment with default props', () => { }); }); -// -------------------------------------------------------------- -// Testing with existing SQS Queue -// -------------------------------------------------------------- test('Pattern deployment with existing queue', () => { // Initial Setup const stack = new Stack(); @@ -112,9 +106,6 @@ test('Pattern deployment with existing queue', () => { }); }); -// -------------------------------------------------------------- -// Testing with passing queue and dead letter queue props -// -------------------------------------------------------------- test('Pattern deployment with queue and dead letter queue props', () => { // Initial Setup const stack = new Stack(); @@ -158,9 +149,6 @@ test('Pattern deployment with queue and dead letter queue props', () => { }); }); -// -------------------------------------------------------------- -// Testing with dead letter queue turned off -// -------------------------------------------------------------- test('Pattern deployment with dead letter queue turned off', () => { // Initial Setup const stack = new Stack(); @@ -193,9 +181,6 @@ test('Pattern deployment with dead letter queue turned off', () => { }); }); -// -------------------------------------------------------------- -// Testing with custom maxReceiveCount -// -------------------------------------------------------------- test('Pattern deployment with custom maxReceiveCount', () => { // Initial Setup const stack = new Stack(); @@ -236,9 +221,6 @@ test('Pattern deployment with custom maxReceiveCount', () => { }); }); -// -------------------------------------------------------------- -// Testing without creating a KMS key -// -------------------------------------------------------------- test('Pattern deployment without creating a KMS key', () => { // Initial Setup const stack = new Stack(); @@ -293,9 +275,6 @@ test('Pattern deployment without creating a KMS key', () => { template.resourceCountIs("AWS::KMS::Key", 0); }); -// -------------------------------------------------------------- -// Testing with existing KMS key -// -------------------------------------------------------------- test('Pattern deployment with existing KMS key', () => { // Initial Setup const stack = new Stack(); @@ -362,9 +341,6 @@ test('Pattern deployment with existing KMS key', () => { }); }); -// --------------------------------------------------------------- -// Testing with existing KMS key on queueProps.encryptionMasterKey -// --------------------------------------------------------------- test('Pattern deployment with existing KMS key', () => { // Initial Setup const stack = new Stack(); @@ -433,9 +409,6 @@ test('Pattern deployment with existing KMS key', () => { }); }); -// -------------------------------------------------------------- -// Testing with passing KMS key props -// -------------------------------------------------------------- test('Pattern deployment passing KMS key props', () => { // Initial Setup const stack = new Stack(); @@ -510,9 +483,6 @@ test('Pattern deployment passing KMS key props', () => { }); }); -// -------------------------------------------------------------- -// Testing with passing a FIFO queue (not supported by IoT) -// -------------------------------------------------------------- test('Pattern deployment with passing a FIFO queue (not supported by IoT)', () => { // Initial Setup const stack = new Stack(); @@ -542,3 +512,27 @@ test('Pattern deployment with passing a FIFO queue (not supported by IoT)', () = expect(err.message).toBe('The IoT SQS action doesn\'t support Amazon SQS FIFO (First-In-First-Out) queues'); } }); + +test('Confirm CheckSqsProps is being called', () => { + // Initial Setup + const stack = new Stack(); + const props: IotToSqsProps = { + iotTopicRuleProps: { + topicRulePayload: { + ruleDisabled: false, + description: "Processing messages from IoT devices or factory machines", + sql: "SELECT * FROM 'test/topic/#'", + actions: [] + } + }, + queueProps: { + removalPolicy: RemovalPolicy.DESTROY, + }, + existingQueueObj: new sqs.Queue(stack, 'test', {}) + }; + + const app = () => { + new IotToSqs(stack, 'test-iot-sqs', props); + }; + expect(app).toThrowError("Error - Either provide queueProps or existingQueueObj, but not both.\n"); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3-and-kinesisanalytics/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3-and-kinesisanalytics/lib/index.ts index 8798c43e8..7c144a724 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3-and-kinesisanalytics/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3-and-kinesisanalytics/lib/index.ts @@ -98,8 +98,6 @@ export class KinesisFirehoseToAnalyticsAndS3 extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); - // Setup the kinesisfirehose-s3 pattern const kinesisFirehoseToS3Props: KinesisFirehoseToS3Props = { kinesisFirehoseProps: props.kinesisFirehoseProps, diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3-and-kinesisanalytics/test/kinesisfirehose-s3-and-kinesisanalytics.test.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3-and-kinesisanalytics/test/kinesisfirehose-s3-and-kinesisanalytics.test.ts index c172d05b1..89adcdd84 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3-and-kinesisanalytics/test/kinesisfirehose-s3-and-kinesisanalytics.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3-and-kinesisanalytics/test/kinesisfirehose-s3-and-kinesisanalytics.test.ts @@ -47,12 +47,12 @@ test('Test properties', () => { }; const app = new KinesisFirehoseToAnalyticsAndS3(stack, 'test-kinesis-firehose-kinesis-analytics', props); // Assertions - expect(app.kinesisAnalytics !== null); - expect(app.kinesisFirehose !== null); - expect(app.kinesisFirehoseRole !== null); - expect(app.kinesisFirehoseLogGroup !== null); - expect(app.s3Bucket !== null); - expect(app.s3LoggingBucket !== null); + expect(app.kinesisAnalytics).toBeDefined(); + expect(app.kinesisFirehose).toBeDefined(); + expect(app.kinesisFirehoseRole).toBeDefined(); + expect(app.kinesisFirehoseLogGroup).toBeDefined(); + expect(app.s3Bucket).toBeDefined(); + expect(app.s3LoggingBucket).toBeDefined(); }); // -------------------------------------------------------------- @@ -106,7 +106,7 @@ test('test kinesisFirehose override ', () => { // -------------------------------------------------------------- // Test bad call with existingBucket and bucketProps // -------------------------------------------------------------- -test("Test bad call with existingBucket and bucketProps", () => { +test("Confirm CheckS3Props is being called", () => { // Stack const stack = new Stack(); @@ -122,7 +122,7 @@ test("Test bad call with existingBucket and bucketProps", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError("Error - Either provide bucketProps or existingBucketObj, but not both.\n"); }); // -------------------------------------------------------------- diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/lib/index.ts index 9f01075f4..0fb36c413 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/lib/index.ts @@ -94,7 +94,7 @@ export class KinesisFirehoseToS3 extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); + defaults.CheckS3Props(props); const firehoseId = 'KinesisFirehose'; @@ -173,7 +173,7 @@ export class KinesisFirehoseToS3 extends Construct { "alias/aws/s3" ); - // We need a stream name to set an enviroment variable, as this is an L1 construct + // We need a stream name to set an environment variable, as this is an L1 construct // accessing the name as a token doesn't work for environment variable contents, so // we take explicit control of the stream name (but will be overridden by a client provided name) const deliveryStreamName = defaults.generateName(this, firehoseId); @@ -188,7 +188,7 @@ export class KinesisFirehoseToS3 extends Construct { deliveryStreamName ); - // if the client didn't explicity say it was a Kinesis client, then turn on encryption + // if the client didn't explicitly say it was a Kinesis client, then turn on encryption if (!props.kinesisFirehoseProps || !props.kinesisFirehoseProps.deliveryStreamType || props.kinesisFirehoseProps.deliveryStreamType !== 'KinesisStreamAsSource' diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/integ.pre-existing-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/integ.pre-existing-bucket.expected.json index 293bda90e..ffb38796f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/integ.pre-existing-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/integ.pre-existing-bucket.expected.json @@ -143,18 +143,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -398,109 +398,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/integ.pre-existing-logging-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/integ.pre-existing-logging-bucket.expected.json index 1d092a359..cd3ca176d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/integ.pre-existing-logging-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/integ.pre-existing-logging-bucket.expected.json @@ -179,18 +179,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -567,109 +567,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/kinesisfirehose-s3.test.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/kinesisfirehose-s3.test.ts index 53ec03ff2..f1eb0b435 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/kinesisfirehose-s3.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisfirehose-s3/test/kinesisfirehose-s3.test.ts @@ -194,10 +194,7 @@ test('check for no SSE encryption for KinesisFirehoseToS3', () => { }); }); -// -------------------------------------------------------------- -// Test bad call with existingBucket and bucketProps -// -------------------------------------------------------------- -test("Test bad call with existingBucket and bucketProps", () => { +test("Confirm that CheckS3Props is being called", () => { // Stack const stack = new cdk.Stack(); @@ -213,12 +210,9 @@ test("Test bad call with existingBucket and bucketProps", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError("Error - Either provide bucketProps or existingBucketObj, but not both.\n"); }); -// -------------------------------------------------------------- -// s3 bucket with bucket, loggingBucket, and auto delete objects -// -------------------------------------------------------------- test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { const stack = new cdk.Stack(); @@ -251,9 +245,6 @@ test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { }); }); -// -------------------------------------------------------------- -// Test bad call with existingLoggingBucketObj and loggingBucketProps -// -------------------------------------------------------------- test("Test bad call with existingLoggingBucketObj and loggingBucketProps", () => { // Stack const stack = new cdk.Stack(); @@ -273,9 +264,6 @@ test("Test bad call with existingLoggingBucketObj and loggingBucketProps", () => expect(app).toThrowError('Error - Either provide existingLoggingBucketObj or loggingBucketProps, but not both.\n'); }); -// -------------------------------------------------------------- -// Test bad call with logS3AccessLogs as false and bucketProps -// -------------------------------------------------------------- test("Test bad call with logS3AccessLogs as false and bucketProps", () => { // Stack const stack = new cdk.Stack(); @@ -293,9 +281,6 @@ test("Test bad call with logS3AccessLogs as false and bucketProps", () => { expect(app).toThrowError('Error - If logS3AccessLogs is false, supplying loggingBucketProps or existingLoggingBucketObj is invalid.\n'); }); -// -------------------------------------------------------------- -// s3 bucket with one content bucket and no logging bucket -// -------------------------------------------------------------- test('s3 bucket with one content bucket and no logging bucket', () => { const stack = new cdk.Stack(); diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/README.md b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/README.md index 4332e90df..9ba008d1d 100755 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/README.md @@ -86,9 +86,9 @@ const customEtlJob = new KinesisstreamsToGluejob(this, "CustomETL", { | tableProps? | [`CfnTableProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_glue.TableProps.html) | User provided AWS Glue Table props to override default props used to create a Glue Table. | | existingDatabase? | [`CfnDatabase`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_glue.CfnDatabase.html) | Existing instance of AWS Glue Database. If this is set, then databaseProps is ignored. | | databaseProps? | [`CfnDatabaseProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_glue.CfnDatabaseProps.html) | User provided Glue Database Props to override the default props used to create the Glue Database. | -| outputDataStore? | [`SinkDataStoreProps`](#sinkdatastoreprops) | User provided properties for S3 bucket that stores Glue Job output. Current datastore types suported is only S3. | +| outputDataStore? | [`SinkDataStoreProps`](#sinkdatastoreprops) | User provided properties for S3 bucket that stores Glue Job output. Current datastore types supported is only S3. | |createCloudWatchAlarms?|`boolean`|Whether to create recommended CloudWatch alarms for Kinesis Data Stream. Default value is set to `true`.| -| etlCodeAsset? | [s3assets.Asset](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html) | User provided instance of the Asset class that represents the ETL code on the local filesytem | +| etlCodeAsset? | [s3assets.Asset](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html) | User provided instance of the Asset class that represents the ETL code on the local filesystem | ### SinkDataStoreProps diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/lib/index.ts index 90322f731..29cfeaf23 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/lib/index.ts @@ -107,7 +107,7 @@ export interface KinesisstreamsToGluejobProps { /** * The props for the Glue database that the construct should use to create. If @database is set * then this property is ignored. If none of @database and @databaseprops is provided, the - * construct will define a GlueDatabase resoruce. + * construct will define a GlueDatabase resource. */ readonly databaseProps?: glue.CfnDatabaseProps; /** @@ -152,8 +152,8 @@ export class KinesisstreamsToGluejob extends Construct { public readonly database: glue.CfnDatabase; public readonly table: glue.CfnTable; /** - * This property is only set if the Glue Job is created by the construct. If an exisiting Glue Job - * configuraton is supplied, the construct does not create an S3 bucket and hence the @outputBucket + * This property is only set if the Glue Job is created by the construct. If an existing Glue Job + * configuration is supplied, the construct does not create an S3 bucket and hence the @outputBucket * property is undefined */ public readonly outputBucket?: [Bucket, (Bucket | undefined)?]; @@ -173,29 +173,8 @@ export class KinesisstreamsToGluejob extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); - - // custom props check - if (props.existingGlueJob && props.glueJobProps) { - throw Error("Either existingGlueJob instance or glueJobProps should be set, but found both"); - } - - if (!props.existingGlueJob) { - if (!props.glueJobProps.command.scriptLocation && !props.etlCodeAsset) { - throw Error('Either one of CfnJob.JobCommandProperty.scriptLocation or KinesisstreamsToGluejobProps.etlCodeAsset has ' + - 'to be provided. If the ETL Job code file exists in a local filesystem, please set ' + - 'KinesisstreamsToGluejobProps.etlCodeAsset. If the ETL Job is available in an S3 bucket, set the ' + - 'CfnJob.JobCommandProperty.scriptLocation property'); - } - - if (!props.etlCodeAsset) { - const s3Url: string = props.glueJobProps.command.scriptLocation; - const found = s3Url.match(/^s3:\/\/\S+\/\S+/g); - if (!(found && found.length > 0 && found[0].length === s3Url.length)) { - throw Error("Invalid S3 URL provided"); - } - } - } + defaults.CheckGlueProps(props); + defaults.CheckKinesisStreamProps(props); this.kinesisStream = defaults.buildKinesisStream(this, { existingStreamObj: props.existingStreamObj, @@ -204,10 +183,6 @@ export class KinesisstreamsToGluejob extends Construct { this.database = props.existingDatabase !== undefined ? props.existingDatabase : defaults.createGlueDatabase(scope, props.databaseProps); - if (props.fieldSchema === undefined && props.existingTable === undefined && props.tableProps === undefined) { - throw Error("Either fieldSchema or table property has to be set, both cannot be optional"); - } - if (props.existingTable !== undefined) { this.table = props.existingTable; } else { diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.code-asset-job.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.code-asset-job.expected.json index f7039123d..81b1bf65b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.code-asset-job.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.code-asset-job.expected.json @@ -107,7 +107,7 @@ ], "Version": "2012-10-17" }, - "Description": "Service role that Glue custom ETL jobs will assume for exeuction" + "Description": "Service role that Glue custom ETL jobs will assume for execution" } }, "testkinesisstreamslambdaJobRoleDefaultPolicy943FFA49": { @@ -422,12 +422,6 @@ "Fn::Sub": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/fbf0b12f00bc09401fb04a361c549193f18f6fa7df4d304c5bfab7ace478b340.py" } }, - "Role": { - "Fn::GetAtt": [ - "testkinesisstreamslambdaJobRole42199B9C", - "Arn" - ] - }, "DefaultArguments": { "--enable-metrics": true, "--enable-continuous-cloudwatch-log": true, @@ -452,6 +446,12 @@ }, "GlueVersion": "2.0", "NumberOfWorkers": 2, + "Role": { + "Fn::GetAtt": [ + "testkinesisstreamslambdaJobRole42199B9C", + "Arn" + ] + }, "SecurityConfiguration": "ETLJobSecurityConfig", "WorkerType": "G.1X" } @@ -459,9 +459,9 @@ "testkinesisstreamslambdaKinesisStreamGetRecordsIteratorAgeAlarmFB74C363": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -472,9 +472,9 @@ "testkinesisstreamslambdaKinesisStreamReadProvisionedThroughputExceededAlarm5ABF4346": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.existing-job.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.existing-job.expected.json index 6910e303d..d49931286 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.existing-job.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.existing-job.expected.json @@ -95,9 +95,9 @@ "testkinesisstreamslambdaKinesisStreamGetRecordsIteratorAgeAlarmFB74C363": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -108,9 +108,9 @@ "testkinesisstreamslambdaKinesisStreamReadProvisionedThroughputExceededAlarm5ABF4346": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.no-arguments.expected.json index b11db6096..c3e70887b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.no-arguments.expected.json @@ -107,7 +107,7 @@ ], "Version": "2012-10-17" }, - "Description": "Service role that Glue custom ETL jobs will assume for exeuction" + "Description": "Service role that Glue custom ETL jobs will assume for execution" } }, "testkinesisstreamslambdaJobRoleDefaultPolicy943FFA49": { @@ -413,12 +413,6 @@ "PythonVersion": "3", "ScriptLocation": "s3://fakelocation/fakefile.py" }, - "Role": { - "Fn::GetAtt": [ - "testkinesisstreamslambdaJobRole42199B9C", - "Arn" - ] - }, "DefaultArguments": { "--enable-metrics": true, "--enable-continuous-cloudwatch-log": true, @@ -443,6 +437,12 @@ }, "GlueVersion": "2.0", "NumberOfWorkers": 2, + "Role": { + "Fn::GetAtt": [ + "testkinesisstreamslambdaJobRole42199B9C", + "Arn" + ] + }, "SecurityConfiguration": "ETLJobSecurityConfig", "WorkerType": "G.1X" } @@ -450,9 +450,9 @@ "testkinesisstreamslambdaKinesisStreamGetRecordsIteratorAgeAlarmFB74C363": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -463,9 +463,9 @@ "testkinesisstreamslambdaKinesisStreamReadProvisionedThroughputExceededAlarm5ABF4346": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/kinesisstream-gluejob.test.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/kinesisstream-gluejob.test.ts index e45c954bf..5e0f4a5f4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/kinesisstream-gluejob.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/kinesisstream-gluejob.test.ts @@ -74,7 +74,7 @@ test('Pattern minimal deployment', () => { }], Version: "2012-10-17", }, - Description: "Service role that Glue custom ETL jobs will assume for exeuction", + Description: "Service role that Glue custom ETL jobs will assume for execution", }, Type: "AWS::IAM::Role" }); @@ -880,3 +880,42 @@ test('Check properties when output bucket is provided', () => { expect(construct.outputBucket![0]).toBeDefined(); expect(construct.outputBucket![1]).not.toBeDefined(); }); + +test('Confirm call to CheckKinesisStreamProps', () => { + // Initial Setup + const stack = new Stack(); + + const props: KinesisstreamsToGluejobProps = { + glueJobProps: { + command: { + name: 'glueetl', + pythonVersion: '3', + scriptLocation: 's3://fakebucket/fakefolder/fakefolder/fakefile.py' + } + }, + fieldSchema: [{ + name: "id", + type: "int", + comment: "Identifier for the record" + }, { + name: "name", + type: "string", + comment: "The name of the record" + }, { + name: "type", + type: "string", + comment: "The type of the record" + }, { + name: "numericvalue", + type: "int", + comment: "Some value associated with the record" + }], + existingStreamObj: new Stream(stack, 'test', {}), + kinesisStreamProps: {} + }; + const app = () => { + new KinesisstreamsToGluejob(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/lib/index.ts index d71a2bc79..21ce087da 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/lib/index.ts @@ -117,7 +117,8 @@ export class KinesisStreamsToKinesisFirehoseToS3 extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); + defaults.CheckKinesisStreamProps(props); + // CheckS3Props() is called by the internal aws-kinesisfirehose-s3 construct // Setup the Kinesis Stream this.kinesisStream = defaults.buildKinesisStream(this, { @@ -142,7 +143,7 @@ export class KinesisStreamsToKinesisFirehoseToS3 extends Construct { } }); - // This Construct requires that the deliveryStreamType be overriden regardless of what is specified in the user props + // This Construct requires that the deliveryStreamType be overridden regardless of what is specified in the user props if (props.kinesisFirehoseProps) { if (props.kinesisFirehoseProps.deliveryStreamType !== undefined) { defaults.printWarning('Overriding deliveryStreamType type to be KinesisStreamAsSource'); @@ -183,4 +184,4 @@ export class KinesisStreamsToKinesisFirehoseToS3 extends Construct { this.cloudwatchAlarms = defaults.buildKinesisStreamCWAlarms(this); } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.customLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.customLoggingBucket.expected.json index 17ba9aba0..5f138e5ae 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.customLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.customLoggingBucket.expected.json @@ -422,9 +422,9 @@ "testkinesisfirehoses3KinesisStreamGetRecordsIteratorAgeAlarm52FF77D1": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -435,9 +435,9 @@ "testkinesisfirehoses3KinesisStreamReadProvisionedThroughputExceededAlarm4A9C6943": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existing-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existing-bucket.expected.json index 539088bd0..df0c49758 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existing-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existing-bucket.expected.json @@ -143,18 +143,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -423,9 +423,9 @@ "testexistingbucketfirehoses3stackKinesisStreamGetRecordsIteratorAgeAlarmD41CBD58": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -436,9 +436,9 @@ "testexistingbucketfirehoses3stackKinesisStreamReadProvisionedThroughputExceededAlarmEC9D97D6": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -489,109 +489,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existing-logging-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existing-logging-bucket.expected.json index 3e67087bf..7a92b2333 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existing-logging-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existing-logging-bucket.expected.json @@ -143,18 +143,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -493,9 +493,9 @@ "testexistingloggingbucketstreamsfirehoses3stackKinesisStreamGetRecordsIteratorAgeAlarmF190BB96": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -506,9 +506,9 @@ "testexistingloggingbucketstreamsfirehoses3stackKinesisStreamReadProvisionedThroughputExceededAlarmCF515815": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -559,109 +559,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existingStreamObj.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existingStreamObj.expected.json index 1fe2510bc..93eda755b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existingStreamObj.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.existingStreamObj.expected.json @@ -153,18 +153,18 @@ }, "S3Key": "26cf7db64552331215006953bf73e5adfb49b5bf0eb2298bfe04547b76c08b88.zip" }, - "Role": { - "Fn::GetAtt": [ - "testkinesislambdaLambdaFunctionServiceRole965E2A08", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testkinesislambdaLambdaFunctionServiceRole965E2A08", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -196,9 +196,6 @@ "testkinesislambdaLambdaFunctionKinesisEventSourceexistingStreamObjtestkinesislambdaKinesisStreamA54D0C79BE6AA8BC": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testkinesislambdaLambdaFunction7F18F840" - }, "BatchSize": 100, "BisectBatchOnFunctionError": true, "DestinationConfig": { @@ -217,6 +214,9 @@ "Arn" ] }, + "FunctionName": { + "Ref": "testkinesislambdaLambdaFunction7F18F840" + }, "MaximumRecordAgeInSeconds": 86400, "MaximumRetryAttempts": 500, "StartingPosition": "TRIM_HORIZON" @@ -304,9 +304,9 @@ "testkinesislambdaKinesisStreamGetRecordsIteratorAgeAlarm99DB34B3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -317,9 +317,9 @@ "testkinesislambdaKinesisStreamReadProvisionedThroughputExceededAlarmAE98686F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.no-arguments.expected.json index cc69403ef..97ed031e5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/integ.no-arguments.expected.json @@ -422,9 +422,9 @@ "teststreamfirehoses3KinesisStreamGetRecordsIteratorAgeAlarm8C693DF4": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -435,9 +435,9 @@ "teststreamfirehoses3KinesisStreamReadProvisionedThroughputExceededAlarm7C631AC0": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/kinesisstreams-kinesisfirehose-s3.test.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/kinesisstreams-kinesisfirehose-s3.test.ts index 5659bf6e1..ecd7174ca 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/kinesisstreams-kinesisfirehose-s3.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3/test/kinesisstreams-kinesisfirehose-s3.test.ts @@ -17,6 +17,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; import { Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; import * as s3 from 'aws-cdk-lib/aws-s3'; +import * as kinesis from 'aws-cdk-lib/aws-kinesis'; function deploy(stack: cdk.Stack, props: KinesisStreamsToKinesisFirehoseToS3Props = {}) { return new KinesisStreamsToKinesisFirehoseToS3(stack, 'test-stream-firehose-s3', props); @@ -237,4 +238,38 @@ test('s3 bucket with one content bucket and no logging bucket', () => { const template = Template.fromStack(stack); template.resourceCountIs("AWS::S3::Bucket", 1); -}); \ No newline at end of file +}); + +test("Confirm that CheckS3Props is being called", () => { + // Stack + const stack = new cdk.Stack(); + + const testBucket = new s3.Bucket(stack, 'test-bucket', {}); + + const app = () => { + // Helper declaration + new KinesisStreamsToKinesisFirehoseToS3(stack, "bad-s3-args", { + existingBucketObj: testBucket, + bucketProps: { + removalPolicy: cdk.RemovalPolicy.DESTROY + }, + }); + }; + // Assertion + expect(app).toThrowError("Error - Either provide bucketProps or existingBucketObj, but not both.\n"); +}); + +test('Confirm call to CheckKinesisStreamProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + + const props: KinesisStreamsToKinesisFirehoseToS3Props = { + existingStreamObj: new kinesis.Stream(stack, 'test', {}), + kinesisStreamProps: {} + }; + const app = () => { + new KinesisStreamsToKinesisFirehoseToS3(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/lib/index.ts index c9d0279a8..e0f68b198 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/lib/index.ts @@ -94,7 +94,8 @@ export class KinesisStreamsToLambda extends Construct { */ constructor(scope: Construct, id: string, props: KinesisStreamsToLambdaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckLambdaProps(props); + defaults.CheckKinesisStreamProps(props); // Setup the Kinesis Stream this.kinesisStream = defaults.buildKinesisStream(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/integ.existing.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/integ.existing.expected.json index a3f9dfb48..674cf8651 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/integ.existing.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/integ.existing.expected.json @@ -124,13 +124,13 @@ }, "S3Key": "26cf7db64552331215006953bf73e5adfb49b5bf0eb2298bfe04547b76c08b88.zip" }, + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "testroleB50A37BE", "Arn" ] }, - "Handler": "index.handler", "Runtime": "nodejs16.x" }, "DependsOn": [ @@ -155,9 +155,6 @@ "testfnKinesisEventSourceexistingteststream96164F11F0EBC1A4": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testfn76BCC25C" - }, "BatchSize": 1, "BisectBatchOnFunctionError": true, "DestinationConfig": { @@ -176,6 +173,9 @@ "Arn" ] }, + "FunctionName": { + "Ref": "testfn76BCC25C" + }, "MaximumRecordAgeInSeconds": 86400, "MaximumRetryAttempts": 500, "StartingPosition": "LATEST" @@ -274,9 +274,9 @@ "testkslambdaKinesisStreamGetRecordsIteratorAgeAlarmD5DC1A73": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -287,9 +287,9 @@ "testkslambdaKinesisStreamReadProvisionedThroughputExceededAlarmFAEF1236": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/integ.no-arguments.expected.json index cf6bffe41..3988a597e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/integ.no-arguments.expected.json @@ -153,18 +153,18 @@ }, "S3Key": "26cf7db64552331215006953bf73e5adfb49b5bf0eb2298bfe04547b76c08b88.zip" }, - "Role": { - "Fn::GetAtt": [ - "testkinesisstreamslambdaLambdaFunctionServiceRoleAD98836E", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testkinesisstreamslambdaLambdaFunctionServiceRoleAD98836E", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -196,9 +196,6 @@ "testkinesisstreamslambdaLambdaFunctionKinesisEventSourcenoargumentstestkinesisstreamslambdaKinesisStream697B4A2015E59078": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testkinesisstreamslambdaLambdaFunctionB9A91CA7" - }, "BatchSize": 100, "BisectBatchOnFunctionError": true, "DestinationConfig": { @@ -217,6 +214,9 @@ "Arn" ] }, + "FunctionName": { + "Ref": "testkinesisstreamslambdaLambdaFunctionB9A91CA7" + }, "MaximumRecordAgeInSeconds": 86400, "MaximumRetryAttempts": 5, "StartingPosition": "TRIM_HORIZON" @@ -304,9 +304,9 @@ "testkinesisstreamslambdaKinesisStreamGetRecordsIteratorAgeAlarmFB74C363": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -317,9 +317,9 @@ "testkinesisstreamslambdaKinesisStreamReadProvisionedThroughputExceededAlarm5ABF4346": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/kinesisstreams-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/kinesisstreams-lambda.test.ts index 5392f5a4c..1d6cfe0c4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/kinesisstreams-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-kinesisstreams-lambda/test/kinesisstreams-lambda.test.ts @@ -18,9 +18,6 @@ import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as kinesis from 'aws-cdk-lib/aws-kinesis'; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Test properties -// -------------------------------------------------------------- test('Test properties', () => { // Initial Setup const stack = new Stack(); @@ -33,16 +30,13 @@ test('Test properties', () => { }; const app = new KinesisStreamsToLambda(stack, 'test-kinesis-streams-lambda', props); // Assertion 1 - expect(app.lambdaFunction !== null); + expect(app.lambdaFunction).toBeDefined(); // Assertion 2 - expect(app.kinesisStream !== null); + expect(app.kinesisStream).toBeDefined(); // Assertion 3 - expect(app.cloudwatchAlarms !== null); + expect(app.cloudwatchAlarms).toBeDefined(); }); -// -------------------------------------------------------------- -// Test existing resources -// -------------------------------------------------------------- test('Test existing resources', () => { // Initial Setup const stack = new Stack(); @@ -79,9 +73,6 @@ test('Test existing resources', () => { }); }); -// -------------------------------------------------------------- -// Test sqsDlqQueueProps override -// -------------------------------------------------------------- test('test sqsDlqQueueProps override', () => { const stack = new Stack(); const props: KinesisStreamsToLambdaProps = { @@ -104,9 +95,6 @@ test('test sqsDlqQueueProps override', () => { }); }); -// -------------------------------------------------------------- -// Test properties with no CW Alarms -// -------------------------------------------------------------- test('Test properties with no CW Alarms', () => { // Initial Setup const stack = new Stack(); @@ -120,9 +108,53 @@ test('Test properties with no CW Alarms', () => { }; const app = new KinesisStreamsToLambda(stack, 'test-kinesis-streams-lambda', props); // Assertion 1 - expect(app.lambdaFunction !== null); + expect(app.lambdaFunction).toBeDefined(); // Assertion 2 - expect(app.kinesisStream !== null); + expect(app.kinesisStream).toBeDefined(); // Assertion 3 - expect(app.cloudwatchAlarms === null); -}); \ No newline at end of file + expect(app.cloudwatchAlarms).not.toBeDefined(); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: KinesisStreamsToLambdaProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new KinesisStreamsToLambda(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); + +test('Confirm call to CheckKinesisStreamProps', () => { + // Initial Setup + const stack = new Stack(); + + const props: KinesisStreamsToLambdaProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingStreamObj: new kinesis.Stream(stack, 'test', {}), + kinesisStreamProps: {} + }; + const app = () => { + new KinesisStreamsToLambda(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/README.md index e6713cc03..4e1c2e62e 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/README.md @@ -89,7 +89,7 @@ new LambdaToDynamoDB(this, "test_lambda_dynamodb_stack", new LambdaToDynamoDBPro |tablePermissions?|`string`|Optional table permissions to grant to the Lambda function. One of the following may be specified: `All`, `Read`, `ReadWrite`, `Write`.| |tableEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the name of the DynamoDB table. Default: DDB_TABLE_NAME | |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and a Gateway Endpoint will be created in the VPC for Amazon DynamoDB. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| ## Pattern Properties diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/lib/index.ts index 73cfa2d0e..2379fdd58 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/lib/index.ts @@ -90,7 +90,9 @@ export class LambdaToDynamoDB extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToDynamoDBProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckDynamoDBProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); // Other permissions for constructs are accepted as arrays, turning tablePermissions into // an array to use the same validation function. @@ -99,10 +101,6 @@ export class LambdaToDynamoDB extends Construct { } if (props.deployVpc || props.existingVpc) { - if (props.deployVpc && props.existingVpc) { - throw new Error("More than 1 VPC specified in the properties"); - } - this.vpc = defaults.buildVpc(scope, { defaultVpcProps: defaults.DefaultIsolatedVpcProps(), existingVpc: props.existingVpc, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.add-secondary-index.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.add-secondary-index.expected.json index 7c73a959d..314be3205 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.add-secondary-index.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.add-secondary-index.expected.json @@ -137,12 +137,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -152,6 +146,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -183,12 +183,6 @@ "testlambdadynamodbstackDynamoTable8138E93B": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ - { - "AttributeName": "id", - "KeyType": "HASH" - } - ], "AttributeDefinitions": [ { "AttributeName": "id", @@ -214,6 +208,12 @@ } } ], + "KeySchema": [ + { + "AttributeName": "id", + "KeyType": "HASH" + } + ], "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.deployFunctionWithExistingVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.deployFunctionWithExistingVpc.expected.json index 53d92cbb8..f0a2aa527 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.deployFunctionWithExistingVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.deployFunctionWithExistingVpc.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,32 +657,22 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcDDB49FBEC5F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { - "ServiceName": { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".dynamodb" - ] - ] - }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, "RouteTableIds": [ { "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" @@ -708,7 +693,22 @@ "Ref": "VpcPublicSubnet3RouteTable93458DBB" } ], - "VpcEndpointType": "Gateway" + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".dynamodb" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testlambdadynamodbstackLambdaFunctionServiceRole758347A1": { @@ -878,12 +878,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -893,6 +887,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -951,19 +951,19 @@ "testlambdadynamodbstackDynamoTable8138E93B": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.deployFunctionWithVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.deployFunctionWithVpc.expected.json index 05c3865e6..17fcd590c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.deployFunctionWithVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.deployFunctionWithVpc.expected.json @@ -168,12 +168,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -183,6 +177,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -238,19 +238,19 @@ "testlambdadynamodbstackDynamoTable8138E93B": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, @@ -279,9 +279,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -298,21 +295,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -329,9 +329,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -348,21 +345,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -379,9 +379,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -398,21 +395,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -444,7 +444,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] } @@ -496,7 +496,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] }, @@ -516,11 +516,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -531,17 +526,33 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcDDB49FBEC5F": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "RouteTableIds": [ + { + "Ref": "VpcisolatedSubnet1RouteTableE442650B" + }, + { + "Ref": "VpcisolatedSubnet2RouteTable334F9764" + }, + { + "Ref": "VpcisolatedSubnet3RouteTableA2F6BBC0" + } + ], "ServiceName": { "Fn::Join": [ "", @@ -554,21 +565,10 @@ ] ] }, + "VpcEndpointType": "Gateway", "VpcId": { "Ref": "Vpc8378EB38" - }, - "RouteTableIds": [ - { - "Ref": "VpcisolatedSubnet1RouteTableE442650B" - }, - { - "Ref": "VpcisolatedSubnet2RouteTable334F9764" - }, - { - "Ref": "VpcisolatedSubnet3RouteTableA2F6BBC0" - } - ], - "VpcEndpointType": "Gateway" + } } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.no-arguments.expected.json index c65bb799c..0ca01d4fe 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.no-arguments.expected.json @@ -126,12 +126,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -141,6 +135,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -172,19 +172,19 @@ "testlambdadynamodbstackDynamoTable8138E93B": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.set-billing-mode.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.set-billing-mode.expected.json index a6ec259c1..62f5de7c5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.set-billing-mode.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.set-billing-mode.expected.json @@ -126,12 +126,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -141,6 +135,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdadynamodbstackLambdaFunctionServiceRole758347A1", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -172,16 +172,16 @@ "testlambdadynamodbstackDynamoTable8138E93B": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], "PointInTimeRecoverySpecification": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.use-existing-func.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.use-existing-func.expected.json index fb888101b..4cfeed2f1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.use-existing-func.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/integ.use-existing-func.expected.json @@ -126,12 +126,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -141,6 +135,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -172,19 +172,19 @@ "testlambdadynamodbstackDynamoTable8138E93B": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "id", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "id", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", "PointInTimeRecoverySpecification": { "PointInTimeRecoveryEnabled": true }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/lambda-dynamodb.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/lambda-dynamodb.test.ts index 1b586b259..5051a0fda 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/lambda-dynamodb.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/lambda-dynamodb.test.ts @@ -275,8 +275,8 @@ test('check properties', () => { const construct: LambdaToDynamoDB = deployNewFunc(stack); - expect(construct.lambdaFunction !== null); - expect(construct.dynamoTable !== null); + expect(construct.lambdaFunction).toBeDefined(); + expect(construct.dynamoTable).toBeDefined(); }); test('check exception for Missing existingObj from props', () => { @@ -759,10 +759,7 @@ test("Test minimal deployment with an existing VPC and existing Lambda function }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { +test("Confirm CheckVpcProps is called", () => { // Stack const stack = new cdk.Stack(); @@ -781,7 +778,7 @@ test("Test bad call with existingVpc and deployVpc", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); }); test('Test bad table permission', () => { @@ -802,4 +799,64 @@ test('Test bad table permission', () => { // Assertion expect(app).toThrowError(/Invalid table permission submitted - Reed/); -}); \ No newline at end of file +}); + +test('Test that CheckDynamoDBProps is getting called', () => { + const stack = new cdk.Stack(); + const tableName = 'custom-table-name'; + + const existingTable = new dynamodb.Table(stack, 'MyTablet', { + tableName, + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING + } + }); + + const props: LambdaToDynamoDBProps = { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, + existingTableObj: existingTable, + dynamoTableProps: { + tableName, + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING + }, + }, + }; + + const app = () => { + new LambdaToDynamoDB(stack, 'test-lambda-dynamodb-stack', props); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide existingTableObj or dynamoTableProps, but not both.\n/); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToDynamoDBProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToDynamoDB(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/README.md index a16478bac..67ff61b56 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/README.md @@ -83,7 +83,7 @@ new LambdaToElasticachememcached(this, "LambdaToCachePattern", new LambdaToElast |existingLambdaObj?|[`lambda.Function`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html)|Existing instance of Lambda Function object, providing both this and `lambdaFunctionProps` will cause an error.| |lambdaFunctionProps?|[`lambda.FunctionProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.FunctionProps.html)|Optional user provided props to override the default props for the Lambda function.| |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for Amazon Elasticache. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user provided properties to override the default properties for the new VPC. `subnetConfiguration` is set by the pattern, so any values for those properties supplied here will be overrriden. | +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user provided properties to override the default properties for the new VPC. `subnetConfiguration` is set by the pattern, so any values for those properties supplied here will be overridden. | | cacheEndpointEnvironmentVariableName?| string | Optional Name for the Lambda function environment variable set to the cache endpoint. Default: CACHE_ENDPOINT | | cacheProps? | [`cache.CfnCacheClusterProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_elasticache.CfnCacheClusterProps.html) | Optional user provided props to override the default props for the Elasticache Cluster. Providing both this and `existingCache` will cause an error. | | existingCache? | [`cache.CfnCacheCluster`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_elasticache.CfnCacheCluster.html#attrconfigurationendpointport) | Existing instance of Elasticache Cluster object, providing both this and `cacheProps` will cause an error. If you provide this, you must provide the associated VPC in existingVpc. | diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/lib/index.ts index dce8c4152..1d8397080 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/lib/index.ts @@ -92,7 +92,8 @@ export class LambdaToElasticachememcached extends Construct { props: LambdaToElasticachememcachedProps ) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); if ((props.existingCache || props.existingLambdaObj) && (!props.existingVpc)) { throw Error('If providing an existing Cache or Lambda Function, you must also supply the associated existingVpc'); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.existingResources.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.existingResources.expected.json index 27ca0eb36..4d18bbc39 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.existingResources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.existingResources.expected.json @@ -19,9 +19,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/18", "MapPublicIpOnLaunch": false, @@ -38,21 +35,24 @@ "Key": "Name", "Value": "existingResources/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingResources/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -69,9 +69,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.64.0/18", "MapPublicIpOnLaunch": false, @@ -88,21 +85,24 @@ "Key": "Name", "Value": "existingResources/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingResources/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -119,9 +119,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.128.0/18", "MapPublicIpOnLaunch": false, @@ -138,21 +135,24 @@ "Key": "Name", "Value": "existingResources/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingResources/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -184,7 +184,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingResources/Vpc" + "Value": "existingResources/Vpc/FlowLog" } ] } @@ -236,7 +236,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingResources/Vpc" + "Value": "existingResources/Vpc/FlowLog" } ] }, @@ -256,11 +256,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -271,12 +266,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existingResources/Vpc" + "Value": "existingResources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "testsgsecuritygroup89DCF621": { @@ -366,12 +366,6 @@ }, "S3Key": "c1b23d6af38c04acb744bda25a3dc7f4394daea942c67eaff40911a707a3c37a.zip" }, - "Role": { - "Fn::GetAtt": [ - "testfunctionServiceRoleFB85AD63", - "Arn" - ] - }, "Environment": { "Variables": { "CACHE_ENDPOINT": { @@ -397,6 +391,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testfunctionServiceRoleFB85AD63", + "Arn" + ] + }, "Runtime": "nodejs16.x", "VpcConfig": { "SecurityGroupIds": [ @@ -450,6 +450,7 @@ "ecsubnetgrouptestcache": { "Type": "AWS::ElastiCache::SubnetGroup", "Properties": { + "CacheSubnetGroupName": "test-cache-subnet-group", "Description": "Solutions Constructs generated Cache Subnet Group", "SubnetIds": [ { @@ -461,8 +462,7 @@ { "Ref": "VpcisolatedSubnet3Subnet44F2537D" } - ], - "CacheSubnetGroupName": "test-cache-subnet-group" + ] } }, "testcachecachesg7265880E": { @@ -502,12 +502,12 @@ "testcachecluster": { "Type": "AWS::ElastiCache::CacheCluster", "Properties": { - "CacheNodeType": "cache.t3.medium", - "Engine": "memcached", - "NumCacheNodes": 2, "AZMode": "cross-az", + "CacheNodeType": "cache.t3.medium", "CacheSubnetGroupName": "test-cache-subnet-group", "ClusterName": "test-cache-cdk-cluster", + "Engine": "memcached", + "NumCacheNodes": 2, "Port": 11222, "VpcSecurityGroupIds": [ { @@ -561,7 +561,6 @@ "testtestingress291C0179": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { - "IpProtocol": "TCP", "Description": "Self referencing rule to control access to Elasticache memcached cluster", "FromPort": { "Fn::GetAtt": [ @@ -575,6 +574,7 @@ "GroupId" ] }, + "IpProtocol": "TCP", "SourceSecurityGroupId": { "Fn::GetAtt": [ "testtestcachesg9F6CF9E2", diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.newResources.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.newResources.expected.json index d7efaa91f..6c53c8f4c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.newResources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.newResources.expected.json @@ -34,7 +34,6 @@ "testtestingress291C0179": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { - "IpProtocol": "TCP", "Description": "Self referencing rule to control access to Elasticache memcached cluster", "FromPort": 11222, "GroupId": { @@ -43,6 +42,7 @@ "GroupId" ] }, + "IpProtocol": "TCP", "SourceSecurityGroupId": { "Fn::GetAtt": [ "testtestcachesg9F6CF9E2", @@ -58,6 +58,7 @@ "testecsubnetgrouptest868C53AE": { "Type": "AWS::ElastiCache::SubnetGroup", "Properties": { + "CacheSubnetGroupName": "test-subnet-group", "Description": "Solutions Constructs generated Cache Subnet Group", "SubnetIds": [ { @@ -69,19 +70,18 @@ { "Ref": "VpcisolatedSubnet3Subnet44F2537D" } - ], - "CacheSubnetGroupName": "test-subnet-group" + ] } }, "testtestcluster57FB8D14": { "Type": "AWS::ElastiCache::CacheCluster", "Properties": { - "CacheNodeType": "cache.t3.medium", - "Engine": "memcached", - "NumCacheNodes": 2, "AZMode": "cross-az", + "CacheNodeType": "cache.t3.medium", "CacheSubnetGroupName": "test-subnet-group", "ClusterName": "test-cdk-cluster", + "Engine": "memcached", + "NumCacheNodes": 2, "Port": 11222, "VpcSecurityGroupIds": [ { @@ -235,12 +235,6 @@ }, "S3Key": "c1b23d6af38c04acb744bda25a3dc7f4394daea942c67eaff40911a707a3c37a.zip" }, - "Role": { - "Fn::GetAtt": [ - "testLambdaFunctionServiceRoleA03EDA2B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -267,6 +261,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testLambdaFunctionServiceRoleA03EDA2B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -343,9 +343,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -362,21 +359,24 @@ "Key": "Name", "Value": "newResources/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "newResources/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -393,9 +393,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -412,21 +409,24 @@ "Key": "Name", "Value": "newResources/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "newResources/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -443,9 +443,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -462,21 +459,24 @@ "Key": "Name", "Value": "newResources/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "newResources/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -508,7 +508,7 @@ "Tags": [ { "Key": "Name", - "Value": "newResources/Vpc" + "Value": "newResources/Vpc/FlowLog" } ] } @@ -560,7 +560,7 @@ "Tags": [ { "Key": "Name", - "Value": "newResources/Vpc" + "Value": "newResources/Vpc/FlowLog" } ] }, @@ -580,11 +580,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -595,12 +590,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "newResources/Vpc" + "Value": "newResources/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.withClientProps.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.withClientProps.expected.json index c0664ed15..cc0020c2e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.withClientProps.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/integ.withClientProps.expected.json @@ -34,7 +34,6 @@ "testtestingress291C0179": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { - "IpProtocol": "TCP", "Description": "Self referencing rule to control access to Elasticache memcached cluster", "FromPort": 11222, "GroupId": { @@ -43,6 +42,7 @@ "GroupId" ] }, + "IpProtocol": "TCP", "SourceSecurityGroupId": { "Fn::GetAtt": [ "testtestcachesg9F6CF9E2", @@ -58,6 +58,7 @@ "testecsubnetgrouptest868C53AE": { "Type": "AWS::ElastiCache::SubnetGroup", "Properties": { + "CacheSubnetGroupName": "test-subnet-group", "Description": "Solutions Constructs generated Cache Subnet Group", "SubnetIds": [ { @@ -69,19 +70,18 @@ { "Ref": "VpcisolatedSubnet3Subnet44F2537D" } - ], - "CacheSubnetGroupName": "test-subnet-group" + ] } }, "testtestcluster57FB8D14": { "Type": "AWS::ElastiCache::CacheCluster", "Properties": { - "CacheNodeType": "cache.t3.medium", - "Engine": "memcached", - "NumCacheNodes": 2, "AZMode": "single-az", + "CacheNodeType": "cache.t3.medium", "CacheSubnetGroupName": "test-subnet-group", "ClusterName": "test-cdk-cluster", + "Engine": "memcached", + "NumCacheNodes": 2, "Port": 11222, "VpcSecurityGroupIds": [ { @@ -235,12 +235,6 @@ }, "S3Key": "c1b23d6af38c04acb744bda25a3dc7f4394daea942c67eaff40911a707a3c37a.zip" }, - "Role": { - "Fn::GetAtt": [ - "testLambdaFunctionServiceRoleA03EDA2B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -267,6 +261,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testLambdaFunctionServiceRoleA03EDA2B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -343,9 +343,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "192.68.0.0/18", "MapPublicIpOnLaunch": false, @@ -362,21 +359,24 @@ "Key": "Name", "Value": "withClientProps/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "withClientProps/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -393,9 +393,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "192.68.64.0/18", "MapPublicIpOnLaunch": false, @@ -412,21 +409,24 @@ "Key": "Name", "Value": "withClientProps/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "withClientProps/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -443,9 +443,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "192.68.128.0/18", "MapPublicIpOnLaunch": false, @@ -462,21 +459,24 @@ "Key": "Name", "Value": "withClientProps/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "withClientProps/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -508,7 +508,7 @@ "Tags": [ { "Key": "Name", - "Value": "withClientProps/Vpc" + "Value": "withClientProps/Vpc/FlowLog" } ] } @@ -560,7 +560,7 @@ "Tags": [ { "Key": "Name", - "Value": "withClientProps/Vpc" + "Value": "withClientProps/Vpc/FlowLog" } ] }, @@ -580,11 +580,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -595,12 +590,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "withClientProps/Vpc" + "Value": "withClientProps/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/lambda-elasticachememcached.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/lambda-elasticachememcached.test.ts index 99c126081..758c59427 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/lambda-elasticachememcached.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticachememcached/test/lambda-elasticachememcached.test.ts @@ -15,7 +15,7 @@ import * as defaults from "@aws-solutions-constructs/core"; import * as cdk from "aws-cdk-lib"; import * as lambda from "aws-cdk-lib/aws-lambda"; -import { LambdaToElasticachememcached } from "../lib"; +import { LambdaToElasticachememcached, LambdaToElasticachememcachedProps } from "../lib"; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import { Template } from "aws-cdk-lib/assertions"; @@ -282,7 +282,7 @@ test('Test for the proper self referencing security group', () => { }, }); }); -// test('', () => {}); + test("Test error from existingCache and no VPC", () => { const stack = new cdk.Stack(); @@ -370,3 +370,52 @@ test("Test error from trying to launch Redis", () => { expect(app).toThrowError("This construct can only launch memcached clusters"); }); + +test("Test error from existingCache and no VPC", () => { + const stack = new cdk.Stack(); + + const vpc = defaults.getTestVpc(stack); + + const app = () => { + new LambdaToElasticachememcached(stack, "testStack", { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: ".handler", + }, + vpcProps: {}, + existingVpc: vpc + }); + }; + + expect(app).toThrowError( + 'Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n' + ); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const testVpc = defaults.getTestVpc(stack); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + vpc: testVpc, + }); + + const props: LambdaToElasticachememcachedProps = { + existingVpc: testVpc, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToElasticachememcached(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/README.md index 149d0d581..972d3818c 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/README.md @@ -114,7 +114,7 @@ new LambdaToElasticSearchAndKibana(this, "sample", |createCloudWatchAlarms?|`boolean`|Whether to create recommended CloudWatch alarms| |domainEndpointEnvironmentVariableName?|`string`|Optional Name for the ElasticSearch domain endpoint environment variable set for the Lambda function.| |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| ## Pattern Properties diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/lib/index.ts index dffaf3625..742ea3498 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/lib/index.ts @@ -107,7 +107,8 @@ export class LambdaToElasticSearchAndKibana extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToElasticSearchAndKibanaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); if (props.vpcProps && !props.deployVpc) { throw new Error("Error - deployVpc must be true when defining vpcProps"); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithClusterConfig.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithClusterConfig.expected.json index f2268c180..ea01e758f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithClusterConfig.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithClusterConfig.expected.json @@ -139,12 +139,6 @@ }, "S3Key": "35bbbc7b04b21f225891f139adf234188f348ebad5f4bbc2c06edf8aa3784c97.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaelasticsearchkibana5LambdaFunctionServiceRole26E43B12", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -157,6 +151,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaelasticsearchkibana5LambdaFunctionServiceRole26E43B12", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -242,9 +242,6 @@ "testlambdaelasticsearchkibana5CognitoUserPoolClientB41FB91B": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaelasticsearchkibana5CognitoUserPool4E321CD0" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -262,7 +259,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaelasticsearchkibana5CognitoUserPool4E321CD0" + } } }, "testlambdaelasticsearchkibana5CognitoIdentityPool1B0A6046": { @@ -618,9 +618,9 @@ "testlambdaelasticsearchkibana5StatusRedAlarm916EC672": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -631,9 +631,9 @@ "testlambdaelasticsearchkibana5StatusYellowAlarm7DCAF60A": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -644,9 +644,9 @@ "testlambdaelasticsearchkibana5FreeStorageSpaceTooLowAlarmEC2C0D7B": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -657,9 +657,9 @@ "testlambdaelasticsearchkibana5IndexWritesBlockedTooHighAlarmD496CE3E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -670,9 +670,9 @@ "testlambdaelasticsearchkibana5AutomatedSnapshotFailureTooHighAlarm97129BC4": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -683,9 +683,9 @@ "testlambdaelasticsearchkibana5CPUUtilizationTooHighAlarm3BAAA397": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -696,9 +696,9 @@ "testlambdaelasticsearchkibana5JVMMemoryPressureTooHighAlarm251AD583": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -709,9 +709,9 @@ "testlambdaelasticsearchkibana5MasterCPUUtilizationTooHighAlarm97A330CC": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -722,9 +722,9 @@ "testlambdaelasticsearchkibana5MasterJVMMemoryPressureTooHighAlarm7DABB351": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -750,9 +750,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -769,21 +766,24 @@ "Key": "Name", "Value": "deployFunctionWithClusterConfig/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithClusterConfig/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -800,9 +800,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -819,21 +816,24 @@ "Key": "Name", "Value": "deployFunctionWithClusterConfig/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithClusterConfig/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -865,7 +865,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithClusterConfig/Vpc" + "Value": "deployFunctionWithClusterConfig/Vpc/FlowLog" } ] } @@ -917,7 +917,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithClusterConfig/Vpc" + "Value": "deployFunctionWithClusterConfig/Vpc/FlowLog" } ] }, @@ -937,10 +937,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -951,10 +947,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithClusterConfig/Vpc" + "Value": "deployFunctionWithClusterConfig/Vpc/FlowLog" } ], "TrafficType": "ALL" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithExistingVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithExistingVpc.expected.json index 419ab19d7..0e5f2100c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithExistingVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithExistingVpc.expected.json @@ -18,9 +18,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -37,7 +34,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -53,15 +53,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -78,12 +78,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -105,15 +105,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -129,9 +129,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -148,7 +145,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -164,15 +164,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -189,12 +189,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -216,15 +216,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -240,9 +240,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -259,7 +256,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -275,15 +275,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -300,12 +300,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -327,15 +327,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -351,9 +351,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -370,21 +367,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -401,21 +401,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -432,21 +429,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -463,21 +463,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -494,21 +491,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -525,12 +525,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -548,11 +548,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -574,7 +574,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } ] } @@ -626,7 +626,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } ] }, @@ -646,10 +646,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -660,10 +656,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -806,12 +806,6 @@ "S3Bucket": "cdk-hnb659fds-assets-12345678-test-region", "S3Key": "35bbbc7b04b21f225891f139adf234188f348ebad5f4bbc2c06edf8aa3784c97.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaelasticsearchkibana4LambdaFunctionServiceRoleA52BB7F9", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -824,6 +818,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaelasticsearchkibana4LambdaFunctionServiceRoleA52BB7F9", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -916,9 +916,6 @@ "testlambdaelasticsearchkibana4CognitoUserPoolClientABBF34C4": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaelasticsearchkibana4CognitoUserPool37A5CDE1" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -936,7 +933,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaelasticsearchkibana4CognitoUserPool37A5CDE1" + } } }, "testlambdaelasticsearchkibana4CognitoIdentityPool76EE9793": { @@ -1295,9 +1295,9 @@ "testlambdaelasticsearchkibana4StatusRedAlarm56DEE5C7": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -1308,9 +1308,9 @@ "testlambdaelasticsearchkibana4StatusYellowAlarm810B4F9E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -1321,9 +1321,9 @@ "testlambdaelasticsearchkibana4FreeStorageSpaceTooLowAlarmF3FB31EA": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -1334,9 +1334,9 @@ "testlambdaelasticsearchkibana4IndexWritesBlockedTooHighAlarmF2968C92": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -1347,9 +1347,9 @@ "testlambdaelasticsearchkibana4AutomatedSnapshotFailureTooHighAlarm53EB1ABB": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -1360,9 +1360,9 @@ "testlambdaelasticsearchkibana4CPUUtilizationTooHighAlarm29B67D10": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -1373,9 +1373,9 @@ "testlambdaelasticsearchkibana4JVMMemoryPressureTooHighAlarm9DDED711": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -1386,9 +1386,9 @@ "testlambdaelasticsearchkibana4MasterCPUUtilizationTooHighAlarmE66867F2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -1399,9 +1399,9 @@ "testlambdaelasticsearchkibana4MasterJVMMemoryPressureTooHighAlarm83E1822E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithVpcProps.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithVpcProps.expected.json index de038946d..ca661cffd 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithVpcProps.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployFunctionWithVpcProps.expected.json @@ -137,12 +137,6 @@ "S3Bucket": "cdk-hnb659fds-assets-12345678-test-region", "S3Key": "35bbbc7b04b21f225891f139adf234188f348ebad5f4bbc2c06edf8aa3784c97.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaelasticsearchkibana3LambdaFunctionServiceRoleA3C1E07E", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -155,6 +149,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaelasticsearchkibana3LambdaFunctionServiceRoleA3C1E07E", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -244,9 +244,6 @@ "testlambdaelasticsearchkibana3CognitoUserPoolClient89D3C6A0": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaelasticsearchkibana3CognitoUserPoolEF0D5793" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -264,7 +261,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaelasticsearchkibana3CognitoUserPoolEF0D5793" + } } }, "testlambdaelasticsearchkibana3CognitoIdentityPool48956B3D": { @@ -623,9 +623,9 @@ "testlambdaelasticsearchkibana3StatusRedAlarmFECC950E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -636,9 +636,9 @@ "testlambdaelasticsearchkibana3StatusYellowAlarmC7FC4662": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -649,9 +649,9 @@ "testlambdaelasticsearchkibana3FreeStorageSpaceTooLowAlarmB9AD5427": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -662,9 +662,9 @@ "testlambdaelasticsearchkibana3IndexWritesBlockedTooHighAlarm36E1D418": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -675,9 +675,9 @@ "testlambdaelasticsearchkibana3AutomatedSnapshotFailureTooHighAlarmA83D4971": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -688,9 +688,9 @@ "testlambdaelasticsearchkibana3CPUUtilizationTooHighAlarmE77470C0": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -701,9 +701,9 @@ "testlambdaelasticsearchkibana3JVMMemoryPressureTooHighAlarm084D2991": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -714,9 +714,9 @@ "testlambdaelasticsearchkibana3MasterCPUUtilizationTooHighAlarm3331F781": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -727,9 +727,9 @@ "testlambdaelasticsearchkibana3MasterJVMMemoryPressureTooHighAlarm149E8D14": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -755,9 +755,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/18", "MapPublicIpOnLaunch": false, @@ -774,21 +771,24 @@ "Key": "Name", "Value": "deployFunctionWithVpcProps/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpcProps/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -805,9 +805,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.64.0/18", "MapPublicIpOnLaunch": false, @@ -824,21 +821,24 @@ "Key": "Name", "Value": "deployFunctionWithVpcProps/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpcProps/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -855,9 +855,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.128.0/18", "MapPublicIpOnLaunch": false, @@ -874,21 +871,24 @@ "Key": "Name", "Value": "deployFunctionWithVpcProps/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpcProps/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -920,7 +920,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpcProps/Vpc" + "Value": "deployFunctionWithVpcProps/Vpc/FlowLog" } ] } @@ -972,7 +972,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpcProps/Vpc" + "Value": "deployFunctionWithVpcProps/Vpc/FlowLog" } ] }, @@ -992,10 +992,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1006,10 +1002,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpcProps/Vpc" + "Value": "deployFunctionWithVpcProps/Vpc/FlowLog" } ], "TrafficType": "ALL" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployToFiveZones.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployToFiveZones.expected.json index 87be3185f..17ec407e2 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployToFiveZones.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.deployToFiveZones.expected.json @@ -139,12 +139,6 @@ }, "S3Key": "35bbbc7b04b21f225891f139adf234188f348ebad5f4bbc2c06edf8aa3784c97.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaelasticsearchkibanaLambdaFunctionServiceRole3AFFEAA2", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -157,6 +151,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaelasticsearchkibanaLambdaFunctionServiceRole3AFFEAA2", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -246,9 +246,6 @@ "testlambdaelasticsearchkibanaCognitoUserPoolClient8F70A2AA": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaelasticsearchkibanaCognitoUserPool9537802B" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -266,7 +263,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaelasticsearchkibanaCognitoUserPool9537802B" + } } }, "testlambdaelasticsearchkibanaCognitoIdentityPoolC48068F0": { @@ -625,9 +625,9 @@ "testlambdaelasticsearchkibanaStatusRedAlarmCFCDB629": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -638,9 +638,9 @@ "testlambdaelasticsearchkibanaStatusYellowAlarm24B9D1CB": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -651,9 +651,9 @@ "testlambdaelasticsearchkibanaFreeStorageSpaceTooLowAlarm0B4D4E35": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -664,9 +664,9 @@ "testlambdaelasticsearchkibanaIndexWritesBlockedTooHighAlarmB8C0E99C": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -677,9 +677,9 @@ "testlambdaelasticsearchkibanaAutomatedSnapshotFailureTooHighAlarm75F2676B": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -690,9 +690,9 @@ "testlambdaelasticsearchkibanaCPUUtilizationTooHighAlarmF16BA5D9": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -703,9 +703,9 @@ "testlambdaelasticsearchkibanaJVMMemoryPressureTooHighAlarm18224533": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -716,9 +716,9 @@ "testlambdaelasticsearchkibanaMasterCPUUtilizationTooHighAlarmE5E5999F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -729,9 +729,9 @@ "testlambdaelasticsearchkibanaMasterJVMMemoryPressureTooHighAlarm297FF1BE": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -757,9 +757,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -776,21 +773,24 @@ "Key": "Name", "Value": "deployToFiveZones/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployToFiveZones/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -807,9 +807,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -826,21 +823,24 @@ "Key": "Name", "Value": "deployToFiveZones/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployToFiveZones/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -857,9 +857,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -876,21 +873,24 @@ "Key": "Name", "Value": "deployToFiveZones/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployToFiveZones/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -922,7 +922,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployToFiveZones/Vpc" + "Value": "deployToFiveZones/Vpc/FlowLog" } ] } @@ -974,7 +974,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployToFiveZones/Vpc" + "Value": "deployToFiveZones/Vpc/FlowLog" } ] }, @@ -994,10 +994,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1008,10 +1004,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployToFiveZones/Vpc" + "Value": "deployToFiveZones/Vpc/FlowLog" } ], "TrafficType": "ALL" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.disabledZoneAwareness.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.disabledZoneAwareness.expected.json index 9adfc0a56..cff23b60c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.disabledZoneAwareness.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.disabledZoneAwareness.expected.json @@ -139,12 +139,6 @@ }, "S3Key": "35bbbc7b04b21f225891f139adf234188f348ebad5f4bbc2c06edf8aa3784c97.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaelasticsearchkibanaLambdaFunctionServiceRole3AFFEAA2", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -157,6 +151,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaelasticsearchkibanaLambdaFunctionServiceRole3AFFEAA2", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -238,9 +238,6 @@ "testlambdaelasticsearchkibanaCognitoUserPoolClient8F70A2AA": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaelasticsearchkibanaCognitoUserPool9537802B" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -258,7 +255,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaelasticsearchkibanaCognitoUserPool9537802B" + } } }, "testlambdaelasticsearchkibanaCognitoIdentityPoolC48068F0": { @@ -608,9 +608,9 @@ "testlambdaelasticsearchkibanaStatusRedAlarmCFCDB629": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -621,9 +621,9 @@ "testlambdaelasticsearchkibanaStatusYellowAlarm24B9D1CB": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -634,9 +634,9 @@ "testlambdaelasticsearchkibanaFreeStorageSpaceTooLowAlarm0B4D4E35": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -647,9 +647,9 @@ "testlambdaelasticsearchkibanaIndexWritesBlockedTooHighAlarmB8C0E99C": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -660,9 +660,9 @@ "testlambdaelasticsearchkibanaAutomatedSnapshotFailureTooHighAlarm75F2676B": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -673,9 +673,9 @@ "testlambdaelasticsearchkibanaCPUUtilizationTooHighAlarmF16BA5D9": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -686,9 +686,9 @@ "testlambdaelasticsearchkibanaJVMMemoryPressureTooHighAlarm18224533": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -699,9 +699,9 @@ "testlambdaelasticsearchkibanaMasterCPUUtilizationTooHighAlarmE5E5999F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -712,9 +712,9 @@ "testlambdaelasticsearchkibanaMasterJVMMemoryPressureTooHighAlarm297FF1BE": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -740,9 +740,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -759,21 +756,24 @@ "Key": "Name", "Value": "disabledZoneAwareness/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "disabledZoneAwareness/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -805,7 +805,7 @@ "Tags": [ { "Key": "Name", - "Value": "disabledZoneAwareness/Vpc" + "Value": "disabledZoneAwareness/Vpc/FlowLog" } ] } @@ -857,7 +857,7 @@ "Tags": [ { "Key": "Name", - "Value": "disabledZoneAwareness/Vpc" + "Value": "disabledZoneAwareness/Vpc/FlowLog" } ] }, @@ -877,10 +877,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -891,10 +887,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "disabledZoneAwareness/Vpc" + "Value": "disabledZoneAwareness/Vpc/FlowLog" } ], "TrafficType": "ALL" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.domain-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.domain-arguments.expected.json index a797b241a..f76540ca7 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.domain-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/integ.domain-arguments.expected.json @@ -98,12 +98,6 @@ }, "S3Key": "35bbbc7b04b21f225891f139adf234188f348ebad5f4bbc2c06edf8aa3784c97.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaelasticsearchkibana2LambdaFunctionServiceRoleA59E9EBF", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -116,6 +110,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaelasticsearchkibana2LambdaFunctionServiceRoleA59E9EBF", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -181,9 +181,6 @@ "testlambdaelasticsearchkibana2CognitoUserPoolClientB0F3872A": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaelasticsearchkibana2CognitoUserPool9D73D9DA" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -201,7 +198,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaelasticsearchkibana2CognitoUserPool9D73D9DA" + } } }, "testlambdaelasticsearchkibana2CognitoIdentityPool0681F400": { @@ -539,9 +539,9 @@ "testlambdaelasticsearchkibana2StatusRedAlarm508A4D17": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -552,9 +552,9 @@ "testlambdaelasticsearchkibana2StatusYellowAlarmEF13F129": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -565,9 +565,9 @@ "testlambdaelasticsearchkibana2FreeStorageSpaceTooLowAlarm1ED7AA90": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -578,9 +578,9 @@ "testlambdaelasticsearchkibana2IndexWritesBlockedTooHighAlarmCE02A217": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -591,9 +591,9 @@ "testlambdaelasticsearchkibana2AutomatedSnapshotFailureTooHighAlarm75E8F988": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -604,9 +604,9 @@ "testlambdaelasticsearchkibana2CPUUtilizationTooHighAlarm7E4A7ADE": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -617,9 +617,9 @@ "testlambdaelasticsearchkibana2JVMMemoryPressureTooHighAlarm7CB5E1C7": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -630,9 +630,9 @@ "testlambdaelasticsearchkibana2MasterCPUUtilizationTooHighAlarmE22B714C": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -643,9 +643,9 @@ "testlambdaelasticsearchkibana2MasterJVMMemoryPressureTooHighAlarm37A392A6": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/lambda-elasticsearch-kibana.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/lambda-elasticsearch-kibana.test.ts index 59452bd7d..767deaa05 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/lambda-elasticsearch-kibana.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-elasticsearch-kibana/test/lambda-elasticsearch-kibana.test.ts @@ -93,6 +93,25 @@ test('check properties with no CW Alarms ', () => { expect(construct.elasticsearchRole).toBeDefined(); }); +test('Check that TLS 1.2 is the default', () => { + const stack = new cdk.Stack(); + + const props: LambdaToElasticSearchAndKibanaProps = { + lambdaFunctionProps: getDefaultTestLambdaProps(), + domainName: 'test-domain', + createCloudWatchAlarms: false + }; + + new LambdaToElasticSearchAndKibana(stack, 'test-lambda-opensearch-stack', props); + const template = Template.fromStack(stack); + template.hasResourceProperties("AWS::Elasticsearch::Domain", { + DomainEndpointOptions: { + EnforceHTTPS: true, + TLSSecurityPolicy: "Policy-Min-TLS-1-2-2019-07" + }, + }); +}); + test('check lambda function custom environment variable', () => { const stack = new cdk.Stack(); const props: LambdaToElasticSearchAndKibanaProps = { @@ -548,4 +567,47 @@ function getDefaultTestLambdaProps(): lambda.FunctionProps { runtime: lambda.Runtime.NODEJS_16_X, handler: 'index.handler', }; -} \ No newline at end of file +} + +test('Confirm CheckVpcProps is being called', () => { + const stack = new cdk.Stack(); + + const app = () => { + new LambdaToElasticSearchAndKibana(stack, 'test-lambda-elasticsearch-kibana', { + lambdaFunctionProps: getDefaultTestLambdaProps(), + domainName: "test", + deployVpc: true, + vpcProps: { + vpcName: "existing-vpc-test" + }, + existingVpc: defaults.getTestVpc(stack), + }); + }; + + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToElasticSearchAndKibanaProps = { + domainName: 'name', + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToElasticSearchAndKibana(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/README.md index f9aa7aaf8..aa6663b1e 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/README.md @@ -88,7 +88,7 @@ new LambdaToEventbridge(this, "LambdaToEventbridgePattern", new LambdaToEventbri |existingEventBusInterface?|[`events.IEventBus`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_events.IEventBus.html)| Optional user-provided custom EventBus for construct to use. Providing both this and `eventBusProps` results an error.| |eventBusProps?|[`events.EventBusProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_events.EventBusProps.html)|Optional user-provided properties to override the default properties when creating a custom EventBus. Setting this value to `{}` will create a custom EventBus using all default properties. If neither this nor `existingEventBusInterface` is provided the construct will use the `default` EventBus. Providing both this and `existingEventBusInterface` results an error.| |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for Amazon EventBridge. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| |eventBusEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the name of the Event bus. Default: EVENTBUS_NAME | diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/lib/index.ts index d2f3815c2..8a0fbaaa3 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/lib/index.ts @@ -86,13 +86,11 @@ export class LambdaToEventbridge extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToEventbridgeProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); + defaults.CheckEventBridgeProps(props); if (props.deployVpc || props.existingVpc) { - if (props.deployVpc && props.existingVpc) { - throw new Error("More than 1 VPC specified in the properties"); - } - this.vpc = defaults.buildVpc(scope, { defaultVpcProps: defaults.DefaultIsolatedVpcProps(), existingVpc: props.existingVpc, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/aws-lambda-eventbridge.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/aws-lambda-eventbridge.test.ts index 93e167b64..ca46ce863 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/aws-lambda-eventbridge.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/aws-lambda-eventbridge.test.ts @@ -73,9 +73,6 @@ const vpcConfig = { }, }; -// -------------------------------------------------------------- -// Tests minimal deployment with new Lambda function -// -------------------------------------------------------------- test('Test minimal deployment with new Lambda function', () => { // Stack const stack = new Stack(); @@ -121,10 +118,7 @@ test('Test minimal deployment with new Lambda function', () => { }); }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { +test("Confirm CheckVpcProps is being called", () => { // Stack const stack = new Stack(); @@ -134,7 +128,7 @@ test("Test bad call with existingVpc and deployVpc", () => { // Helper declaration new LambdaToEventbridge(stack, "lambda-to-eventbridge-stack", { lambdaFunctionProps: { - runtime: lambda.Runtime.NODEJS_16_X, + runtime: lambda.Runtime.NODEJS_18_X, handler: "index.handler", code: lambda.Code.fromAsset(`${__dirname}/lambda`), }, @@ -143,13 +137,10 @@ test("Test bad call with existingVpc and deployVpc", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); }); -// -------------------------------------------------------------- -// Test exception while passing existingEventBus & eventBusProps -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { +test("Confirm CheckEventBridgeProps is called", () => { // Stack const stack = new Stack(); @@ -166,12 +157,9 @@ test("Test bad call with existingVpc and deployVpc", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'); }); -// -------------------------------------------------------------- -// Test deployment w/ existing eventbus -// -------------------------------------------------------------- test('Test deployment w/ existing eventbus', () => { // Stack const stack = new Stack(); @@ -213,9 +201,6 @@ test('Test deployment w/ existing eventbus', () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC without vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC without vpcProps", () => { // Stack const stack = new Stack(); @@ -245,9 +230,6 @@ test("Test minimal deployment that deploys a VPC without vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC w/vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC w/vpcProps", () => { // Stack const stack = new Stack(); @@ -283,9 +265,6 @@ test("Test minimal deployment that deploys a VPC w/vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC", () => { // Stack const stack = new Stack(); @@ -350,12 +329,6 @@ test("Test minimal deployment with an existing VPC", () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC and existing Lambda function not in a VPC -// -// buildLambdaFunction should throw an error if the Lambda function is not -// attached to a VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC and existing Lambda function not in a VPC", () => { // Stack const stack = new Stack(); @@ -370,7 +343,8 @@ test("Test minimal deployment with an existing VPC and existing Lambda function // Helper declaration const app = () => { - // Helper declaration + // buildLambdaFunction should throw an error if the Lambda function is not + // attached to a VPC new LambdaToEventbridge(stack, "lambda-to-eventbridge-stack", { existingLambdaObj: testLambdaFunction, existingVpc: testVpc, @@ -378,13 +352,10 @@ test("Test minimal deployment with an existing VPC and existing Lambda function }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('A Lambda function must be bound to a VPC upon creation, it cannot be added to a VPC in a subsequent construct'); }); -// ---------------------------------------------------------------------------------- -// Test lambda function custom environment variable and custom event bus permissions -// ---------------------------------------------------------------------------------- test('Test lambda function custom environment variable', () => { // Stack const stack = new Stack(); @@ -486,7 +457,7 @@ test('check multiple lambda functions publishing to single event bus', () => { // Make sure 2 lambda functions exist template.resourceCountIs('AWS::Lambda::Function', 2); - // Check whether lambdas have permisison to publish to the event bus + // Check whether lambdas have permission to publish to the event bus template.hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ @@ -518,4 +489,28 @@ test('check multiple lambda functions publishing to single event bus', () => { } } }); -}); \ No newline at end of file +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToEventbridgeProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToEventbridge(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunction.expected.json index 5ab39a3c3..8489843f4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunction.expected.json @@ -123,12 +123,6 @@ }, "S3Key": "b5faf4ff1ebde477120133d1e645d20d7c3d4952b76c3b586100069b94b2f146.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaeventbridgeLambdaFunctionServiceRole0FD85077", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -136,6 +130,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaeventbridgeLambdaFunctionServiceRole0FD85077", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunctionWithNewEventBus.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunctionWithNewEventBus.expected.json index ce8b67b82..e44ac5c83 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunctionWithNewEventBus.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunctionWithNewEventBus.expected.json @@ -150,12 +150,6 @@ }, "S3Key": "b5faf4ff1ebde477120133d1e645d20d7c3d4952b76c3b586100069b94b2f146.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaeventbridgeLambdaFunctionServiceRole0FD85077", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -165,6 +159,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaeventbridgeLambdaFunctionServiceRole0FD85077", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -241,9 +241,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -260,21 +257,24 @@ "Key": "Name", "Value": "deployFunctionWithNewEventBus/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithNewEventBus/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -291,9 +291,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -310,21 +307,24 @@ "Key": "Name", "Value": "deployFunctionWithNewEventBus/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithNewEventBus/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -341,9 +341,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -360,21 +357,24 @@ "Key": "Name", "Value": "deployFunctionWithNewEventBus/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithNewEventBus/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -406,7 +406,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithNewEventBus/Vpc" + "Value": "deployFunctionWithNewEventBus/Vpc/FlowLog" } ] } @@ -458,7 +458,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithNewEventBus/Vpc" + "Value": "deployFunctionWithNewEventBus/Vpc/FlowLog" } ] }, @@ -478,11 +478,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -493,17 +488,31 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithNewEventBus/Vpc" + "Value": "deployFunctionWithNewEventBus/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcCLOUDWATCHEVENTS1A0DAFBF": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "deployFunctionWithNewEventBusCLOUDWATCHEVENTSsecuritygroupD8A263BF", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -516,18 +525,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "deployFunctionWithNewEventBusCLOUDWATCHEVENTSsecuritygroupD8A263BF", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -539,7 +536,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "deployFunctionWithNewEventBusCLOUDWATCHEVENTSsecuritygroupD8A263BF": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunctionWithVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunctionWithVpc.expected.json index 039171e95..916504c1e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunctionWithVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.deployFunctionWithVpc.expected.json @@ -164,12 +164,6 @@ }, "S3Key": "b5faf4ff1ebde477120133d1e645d20d7c3d4952b76c3b586100069b94b2f146.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaeventbridgeLambdaFunctionServiceRole0FD85077", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -177,6 +171,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaeventbridgeLambdaFunctionServiceRole0FD85077", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -247,9 +247,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -266,21 +263,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -297,9 +297,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -316,21 +313,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -347,9 +347,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -366,21 +363,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -412,7 +412,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] } @@ -464,7 +464,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] }, @@ -484,11 +484,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -499,17 +494,31 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcCLOUDWATCHEVENTS1A0DAFBF": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "deployFunctionWithVpcCLOUDWATCHEVENTSsecuritygroupB8797C76", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -522,18 +531,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "deployFunctionWithVpcCLOUDWATCHEVENTSsecuritygroupB8797C76", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -545,7 +542,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "deployFunctionWithVpcCLOUDWATCHEVENTSsecuritygroupB8797C76": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.existingEventBus.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.existingEventBus.expected.json index bf5172fd4..5f3d822d0 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.existingEventBus.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.existingEventBus.expected.json @@ -109,12 +109,6 @@ }, "S3Key": "b5faf4ff1ebde477120133d1e645d20d7c3d4952b76c3b586100069b94b2f146.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -124,6 +118,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.existingFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.existingFunction.expected.json index 39b2e657e..6756239b0 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.existingFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-eventbridge/test/integ.existingFunction.expected.json @@ -123,12 +123,6 @@ }, "S3Key": "b5faf4ff1ebde477120133d1e645d20d7c3d4952b76c3b586100069b94b2f146.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -136,6 +130,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/README.md index 8cae3fe5d..03992a347 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/README.md @@ -78,7 +78,7 @@ TBD | existingKendraIndexObj? | [`kendra.cfnIndex`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kendra.CfnIndex.html) | An existing Kendra index to which the Lambda function will be granted access. Supplying along with kendraIndexProps or kendraDataSourceProps will throw an error. | | existingVpc? | [`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html) | An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method. | | vpcProps? | [`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html) | Optional user provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored. | -| deployVpc? | `boolean` | Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
\- One isolated subnet in each Availability Zone used by the CDK program
\- `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`. | +| deployVpc? | `boolean` | Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to `true` will deploy the minimal, most private VPC to run the pattern, consisting of (1) one isolated subnet in each Availability Zone used by the CDK program; and (2) `enableDnsHostnames` and `enableDnsSupport` both being set to `true`. If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`. | ## Pattern Properties @@ -129,4 +129,4 @@ Out of the box implementation of the Construct without any overrides will set th * * * -© Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. \ No newline at end of file +© Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/achitecture.png b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/architecture.png similarity index 100% rename from source/patterns/@aws-solutions-constructs/aws-lambda-kendra/achitecture.png rename to source/patterns/@aws-solutions-constructs/aws-lambda-kendra/architecture.png diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/lib/index.ts index e44f13a92..bdccc5944 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/lib/index.ts @@ -104,7 +104,8 @@ export class LambdaToKendra extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToKendraProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); if (props.kendraIndexProps && props.existingKendraIndexObj) { throw new Error('You may not provide both kendraIndexProps and existingKendraIndexObj'); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/package.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/package.json index a5d16ad28..6e8505403 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/package.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/package.json @@ -54,7 +54,7 @@ "devDependencies": { "@types/jest": "^27.4.0", "@types/node": "^10.3.0", - "aws-cdk-lib": "2.82.0", + "aws-cdk-lib": "0.0.0", "@aws-solutions-constructs/core": "0.0.0", "constructs": "^10.0.0" }, @@ -74,7 +74,7 @@ }, "peerDependencies": { "@aws-solutions-constructs/core": "0.0.0", - "aws-cdk-lib": "^2.82.0", + "aws-cdk-lib": "^0.0.0", "constructs": "^10.0.0" }, "keywords": [ diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.minimal-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.minimal-arguments.expected.json index d423282c9..95121ec2e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.minimal-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.minimal-arguments.expected.json @@ -143,18 +143,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -315,12 +315,6 @@ }, "S3Key": "e0128dd6e376c58a74b37bd6178ded8a5909d414a6891c26547b9778ac25679b.zip" }, - "Role": { - "Fn::GetAtt": [ - "minimalargumentsLambdaFunctionServiceRole73B77FF7", - "Arn" - ] - }, "Environment": { "Variables": { "KENDRA_INDEX_ID": { @@ -332,6 +326,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "minimalargumentsLambdaFunctionServiceRole73B77FF7", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -598,6 +598,13 @@ "minimalargumentsdatasourceminimalarguments05A02FF3B": { "Type": "AWS::Kendra::DataSource", "Properties": { + "DataSourceConfiguration": { + "S3Configuration": { + "BucketName": { + "Ref": "scrapBucketB11863B7" + } + } + }, "IndexId": { "Ref": "minimalargumentskendraindexminimalarguments5CBDD236" }, @@ -622,123 +629,13 @@ ] ] }, - "Type": "S3", - "DataSourceConfiguration": { - "S3Configuration": { - "BucketName": { - "Ref": "scrapBucketB11863B7" - } - } - }, "RoleArn": { "Fn::GetAtt": [ "minimalargumentsdatasourceroleminimalarguments00EAC5006", "Arn" ] - } - } - } - }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" + }, + "Type": "S3" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.multiple-sources.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.multiple-sources.expected.json index 9e715550e..3850d7547 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.multiple-sources.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.multiple-sources.expected.json @@ -143,18 +143,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -332,12 +332,6 @@ }, "S3Key": "e0128dd6e376c58a74b37bd6178ded8a5909d414a6891c26547b9778ac25679b.zip" }, - "Role": { - "Fn::GetAtt": [ - "minimalargumentsLambdaFunctionServiceRole73B77FF7", - "Arn" - ] - }, "Environment": { "Variables": { "KENDRA_INDEX_ID": { @@ -349,6 +343,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "minimalargumentsLambdaFunctionServiceRole73B77FF7", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -615,6 +615,13 @@ "minimalargumentsdatasourceminimalarguments05A02FF3B": { "Type": "AWS::Kendra::DataSource", "Properties": { + "DataSourceConfiguration": { + "S3Configuration": { + "BucketName": { + "Ref": "scrapBucketB11863B7" + } + } + }, "IndexId": { "Ref": "minimalargumentskendraindexminimalarguments5CBDD236" }, @@ -639,33 +646,18 @@ ] ] }, - "Type": "S3", - "DataSourceConfiguration": { - "S3Configuration": { - "BucketName": { - "Ref": "scrapBucketB11863B7" - } - } - }, "RoleArn": { "Fn::GetAtt": [ "minimalargumentsdatasourceroleminimalarguments00EAC5006", "Arn" ] - } + }, + "Type": "S3" } }, "minimalargumentskendradatasourceminimalarguments1DA6FACEE": { "Type": "AWS::Kendra::DataSource", "Properties": { - "IndexId": { - "Fn::GetAtt": [ - "minimalargumentskendraindexminimalarguments5CBDD236", - "Id" - ] - }, - "Name": "web-source", - "Type": "WEBCRAWLER", "DataSourceConfiguration": { "WebCrawlerConfiguration": { "CrawlDepth": 1, @@ -678,115 +670,20 @@ } } }, + "IndexId": { + "Fn::GetAtt": [ + "minimalargumentskendraindexminimalarguments5CBDD236", + "Id" + ] + }, + "Name": "web-source", "RoleArn": { "Fn::GetAtt": [ "existingRole3E995BBA", "Arn" ] - } - } - } - }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" + }, + "Type": "WEBCRAWLER" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.with-vpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.with-vpc.expected.json index 394098d54..0bc0c7c64 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.with-vpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/integ.with-vpc.expected.json @@ -143,18 +143,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -356,12 +356,6 @@ }, "S3Key": "e0128dd6e376c58a74b37bd6178ded8a5909d414a6891c26547b9778ac25679b.zip" }, - "Role": { - "Fn::GetAtt": [ - "minimalargumentsLambdaFunctionServiceRole73B77FF7", - "Arn" - ] - }, "Environment": { "Variables": { "KENDRA_INDEX_ID": { @@ -373,6 +367,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "minimalargumentsLambdaFunctionServiceRole73B77FF7", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -663,6 +663,13 @@ "minimalargumentsdatasourceminimalarguments05A02FF3B": { "Type": "AWS::Kendra::DataSource", "Properties": { + "DataSourceConfiguration": { + "S3Configuration": { + "BucketName": { + "Ref": "scrapBucketB11863B7" + } + } + }, "IndexId": { "Ref": "minimalargumentskendraindexminimalarguments5CBDD236" }, @@ -687,20 +694,13 @@ ] ] }, - "Type": "S3", - "DataSourceConfiguration": { - "S3Configuration": { - "BucketName": { - "Ref": "scrapBucketB11863B7" - } - } - }, "RoleArn": { "Fn::GetAtt": [ "minimalargumentsdatasourceroleminimalarguments00EAC5006", "Arn" ] - } + }, + "Type": "S3" } }, "Vpc8378EB38": { @@ -721,9 +721,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -740,21 +737,24 @@ "Key": "Name", "Value": "with-vpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "with-vpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -771,9 +771,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -790,21 +787,24 @@ "Key": "Name", "Value": "with-vpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "with-vpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -821,9 +821,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -840,21 +837,24 @@ "Key": "Name", "Value": "with-vpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "with-vpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -886,7 +886,7 @@ "Tags": [ { "Key": "Name", - "Value": "with-vpc/Vpc" + "Value": "with-vpc/Vpc/FlowLog" } ] } @@ -938,7 +938,7 @@ "Tags": [ { "Key": "Name", - "Value": "with-vpc/Vpc" + "Value": "with-vpc/Vpc/FlowLog" } ] }, @@ -958,10 +958,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -972,10 +968,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "with-vpc/Vpc" + "Value": "with-vpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -984,6 +984,15 @@ "VpcKENDRAD98378E1": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "withvpcKENDRAsecuritygroup6E04E691", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -996,18 +1005,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "withvpcKENDRAsecuritygroup6E04E691", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -1019,7 +1016,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "withvpcKENDRAsecuritygroup6E04E691": { @@ -1081,109 +1081,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/lambda-kendra.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/lambda-kendra.test.ts index df13e471c..a80ff5355 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/lambda-kendra.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kendra/test/lambda-kendra.test.ts @@ -11,16 +11,15 @@ * and limitations under the License. */ -import { LambdaToKendra } from "../lib"; +import { LambdaToKendra, LambdaToKendraProps } from "../lib"; import * as lambda from 'aws-cdk-lib/aws-lambda'; -import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as kendra from 'aws-cdk-lib/aws-kendra'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as cdk from "aws-cdk-lib"; import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; -test.only('Launch with minimal code and check structure', () => { +test('Launch with minimal code and check structure', () => { const stack = new cdk.Stack(); const testFunctionName = 'test-function-name24334'; const testBucketName = 'test-bucket-name12344'; @@ -445,39 +444,6 @@ test('Launch with existing lambda', () => { }); }); -test('Confirm error with existing vpc and vpc props', () => { - const stack = new cdk.Stack(); - const testBucketName = 'test-bucket-name22'; - - const lambdaProps: lambda.FunctionProps = { - code: lambda.Code.fromAsset(`${__dirname}/lambda`), - runtime: lambda.Runtime.NODEJS_18_X, - handler: 'index.handler' - }; - - const app = () => { - new LambdaToKendra(stack, 'sample', { - existingVpc: defaults.getTestVpc(stack), - deployVpc: true, - vpcProps: { - ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16') - }, - lambdaFunctionProps: lambdaProps, - kendraDataSourcesProps: [{ - type: 'S3', - dataSourceConfiguration: { - s3Configuration: { - bucketName: testBucketName, - } - } - } - ], - }); - }; - - expect(app).toThrowError(/Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n/); -}); - test('Confirm error with data source with no bucket name', () => { const stack = new cdk.Stack(); @@ -501,7 +467,7 @@ test('Confirm error with data source with no bucket name', () => { }); }; - expect(app).toThrowError(/Error - an S3 Kendra DataSource requires the DataSourceCofiguration.S3Configuration.bucketName prop/); + expect(app).toThrowError(/Error - an S3 Kendra DataSource requires the DataSourceConfiguration.S3Configuration.bucketName prop/); }); test('Launch with existing vpc', () => { @@ -1038,3 +1004,78 @@ test('Test with custom environment variable name', () => { }); }); + +test('Confirm CheckVpcProps is being called', () => { + const stack = new cdk.Stack(); + const testFunctionName = 'test-function-name24334'; + const testBucketName = 'test-bucket-name12344'; + + const vpc = defaults.buildVpc(stack, { + defaultVpcProps: defaults.DefaultIsolatedVpcProps(), + constructVpcProps: { + enableDnsHostnames: true, + enableDnsSupport: true, + }, + }); + + const lambdaProps: lambda.FunctionProps = { + functionName: testFunctionName, + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler' + }; + + const props: LambdaToKendraProps = { + lambdaFunctionProps: lambdaProps, + kendraDataSourcesProps: [{ + type: 'S3', + dataSourceConfiguration: { + s3Configuration: { + bucketName: testBucketName, + } + } + } + ], + deployVpc: true, + existingVpc: vpc + }; + + const app = () => { + new LambdaToKendra(stack, 'sample', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToKendraProps = { + kendraDataSourcesProps: [{ + type: 'S3', + dataSourceConfiguration: { + s3Configuration: { + bucketName: 'testBucketName', + } + } + } + ], + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToKendra(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/README.md index b4f908309..90356dc65 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/README.md @@ -99,7 +99,7 @@ new LambdaToKinesisFirehose(this, "LambdaToFirehosePattern", new LambdaToKinesis |lambdaFunctionProps?|[`lambda.FunctionProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.FunctionProps.html)|Optional user provided props to override the default props for the Lambda function.| |existingKinesisFirehose|[kinesisfirehose.CfnDeliveryStream](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kinesisfirehose.CfnDeliveryStream.html)|An existing Kinesis Firehose Delivery Stream to which the Lambda function can put data. Note - the delivery stream construct must have already been created and have the deliveryStreamName set. This construct will *not* create a new Delivery Stream.| |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for Amazon Kinesis Data Firehose. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| |firehoseEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the name of the delivery stream. Default: FIREHOSE_DELIVERYSTREAM_NAME | diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/lib/index.ts index 6971f5946..e5a4677e4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/lib/index.ts @@ -82,7 +82,8 @@ export class LambdaToKinesisFirehose extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToKinesisFirehoseProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); if (!props.deployVpc && props.vpcProps) { throw new Error('Error - If deployVpc is not true, then vpcProps is ignored'); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/aws-lambda-kinesisfirehose.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/aws-lambda-kinesisfirehose.test.ts index e049b30fb..6a585408f 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/aws-lambda-kinesisfirehose.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/aws-lambda-kinesisfirehose.test.ts @@ -15,7 +15,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import * as cdk from 'aws-cdk-lib'; import * as lambda from 'aws-cdk-lib/aws-lambda'; -import { LambdaToKinesisFirehose } from '../lib'; +import { LambdaToKinesisFirehose, LambdaToKinesisFirehoseProps } from '../lib'; import * as defaults from '@aws-solutions-constructs/core'; import { GetTestFirehoseDestination } from './test-helper'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; @@ -108,7 +108,7 @@ test('Test that new VPC is created', () => { } }); - expect(construct.vpc !== null); + expect(construct.vpc).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::EC2::VPC", { @@ -148,7 +148,7 @@ test('Test that existing VPC is used', () => { existingVpc: myVpc }); - expect(construct.vpc !== null); + expect(construct.vpc).toBeDefined(); // Make sure we didn't deploy a new one anyway const template = Template.fromStack(stack); @@ -242,3 +242,58 @@ test('Test fail Vpc check with vpcProps yet deployVpc is undefined', () => { // Assertion expect(app).toThrowError('Error - If deployVpc is not true, then vpcProps is ignored'); }); + +test('Confirm CheckVpcProps() is being called', () => { + const stack = new cdk.Stack(); + const destination = GetTestFirehoseDestination(stack, 'test-destination'); + + const vpc = defaults.buildVpc(stack, { + defaultVpcProps: defaults.DefaultIsolatedVpcProps(), + constructVpcProps: { + enableDnsHostnames: true, + enableDnsSupport: true, + }, + }); + + const app = () => { + // Helper declaration + new LambdaToKinesisFirehose(stack, 'test-lambda-kinesisfirehose', { + existingKinesisFirehose: destination.kinesisFirehose, + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler' + }, + deployVpc: true, + existingVpc: vpc + }); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + const destination = GetTestFirehoseDestination(stack, 'test-destination'); + + const props: LambdaToKinesisFirehoseProps = { + existingKinesisFirehose: destination.kinesisFirehose, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToKinesisFirehose(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.existing-function.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.existing-function.expected.json index b2ff686f1..00be5feb3 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.existing-function.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.existing-function.expected.json @@ -550,18 +550,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -668,18 +668,18 @@ }, "S3Key": "e223396f670e1c26b56c83fd2179ab8672928b9795821c6a437874a06625eb53.zip" }, - "Role": { - "Fn::GetAtt": [ - "existingfunctionServiceRole90E818C0", - "Arn" - ] - }, "Environment": { "Variables": { "FIREHOSE_DELIVERYSTREAM_NAME": "KinesisFirehoseexistingfunctiondestinationfirehoseE53928C2" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "existingfunctionServiceRole90E818C0", + "Arn" + ] + }, "Runtime": "nodejs18.x" }, "DependsOn": [ @@ -706,109 +706,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.existing-vpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.existing-vpc.expected.json index 0c3273c35..624ba79bd 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.existing-vpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.existing-vpc.expected.json @@ -550,18 +550,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -615,9 +615,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -634,7 +631,10 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -650,15 +650,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -675,12 +675,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -702,15 +702,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -726,9 +726,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -745,7 +742,10 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -761,15 +761,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -786,12 +786,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -813,15 +813,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -837,9 +837,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -856,7 +853,10 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -872,15 +872,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -897,12 +897,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -924,15 +924,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -948,9 +948,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -967,21 +964,24 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -998,21 +998,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -1029,21 +1026,24 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -1060,21 +1060,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -1091,21 +1088,24 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -1122,12 +1122,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -1145,11 +1145,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -1171,7 +1171,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-vpc/Vpc" + "Value": "existing-vpc/Vpc/FlowLog" } ] } @@ -1223,7 +1223,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-vpc/Vpc" + "Value": "existing-vpc/Vpc/FlowLog" } ] }, @@ -1243,10 +1243,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1257,10 +1253,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-vpc/Vpc" + "Value": "existing-vpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -1269,6 +1269,15 @@ "VpcKINESISFIREHOSE4115B5D1": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingvpcKINESISFIREHOSEsecuritygroupF123580F", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -1281,18 +1290,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingvpcKINESISFIREHOSEsecuritygroupF123580F", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -1304,7 +1301,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testconstructLambdaFunctionServiceRole435FDF6F": { @@ -1461,18 +1461,18 @@ }, "S3Key": "e223396f670e1c26b56c83fd2179ab8672928b9795821c6a437874a06625eb53.zip" }, - "Role": { - "Fn::GetAtt": [ - "testconstructLambdaFunctionServiceRole435FDF6F", - "Arn" - ] - }, "Environment": { "Variables": { "FIREHOSE_DELIVERYSTREAM_NAME": "KinesisFirehoseexistingvpcdestinationfirehoseFCC6BBF7" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testconstructLambdaFunctionServiceRole435FDF6F", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -1587,109 +1587,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.new-vpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.new-vpc.expected.json index ceb539324..77af4c7da 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.new-vpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.new-vpc.expected.json @@ -550,18 +550,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -751,18 +751,18 @@ }, "S3Key": "e223396f670e1c26b56c83fd2179ab8672928b9795821c6a437874a06625eb53.zip" }, - "Role": { - "Fn::GetAtt": [ - "testconstructLambdaFunctionServiceRole435FDF6F", - "Arn" - ] - }, "Environment": { "Variables": { "FIREHOSE_DELIVERYSTREAM_NAME": "KinesisFirehosenewvpcdestinationfirehoseEC1F5A2C" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testconstructLambdaFunctionServiceRole435FDF6F", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -833,9 +833,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.100.0.0/18", "MapPublicIpOnLaunch": false, @@ -852,21 +849,24 @@ "Key": "Name", "Value": "new-vpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-vpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -883,9 +883,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.100.64.0/18", "MapPublicIpOnLaunch": false, @@ -902,21 +899,24 @@ "Key": "Name", "Value": "new-vpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-vpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -933,9 +933,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.100.128.0/18", "MapPublicIpOnLaunch": false, @@ -952,21 +949,24 @@ "Key": "Name", "Value": "new-vpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "new-vpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -998,7 +998,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-vpc/Vpc" + "Value": "new-vpc/Vpc/FlowLog" } ] } @@ -1050,7 +1050,7 @@ "Tags": [ { "Key": "Name", - "Value": "new-vpc/Vpc" + "Value": "new-vpc/Vpc/FlowLog" } ] }, @@ -1070,10 +1070,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1084,10 +1080,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "new-vpc/Vpc" + "Value": "new-vpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -1096,6 +1096,15 @@ "VpcKINESISFIREHOSE4115B5D1": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "newvpcKINESISFIREHOSEsecuritygroup3F345517", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -1108,18 +1117,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "newvpcKINESISFIREHOSEsecuritygroup3F345517", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -1131,7 +1128,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newvpcKINESISFIREHOSEsecuritygroup3F345517": { @@ -1193,109 +1193,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.no-arguments.expected.json index 0c347bb90..688ddcad6 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisfirehose/test/integ.no-arguments.expected.json @@ -550,18 +550,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -710,18 +710,18 @@ }, "S3Key": "e223396f670e1c26b56c83fd2179ab8672928b9795821c6a437874a06625eb53.zip" }, - "Role": { - "Fn::GetAtt": [ - "testconstructLambdaFunctionServiceRole435FDF6F", - "Arn" - ] - }, "Environment": { "Variables": { "FIREHOSE_DELIVERYSTREAM_NAME": "KinesisFirehosenoargumentsdestinationfirehose5454CC08" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testconstructLambdaFunctionServiceRole435FDF6F", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -751,109 +751,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/README.md index f3eb9a250..ac642e0af 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/README.md @@ -88,7 +88,7 @@ new LambdaToKinesisStreams(this, "LambdaToKinesisStreams", new LambdaToKinesisSt |kinesisStreamProps?|[`kinesis.StreamProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kinesis.StreamProps.html)|Optional user-provided props to override the default props for the Kinesis Data Stream.| |createCloudWatchAlarms|`boolean`|Whether to create recommended CloudWatch Alarms (defaults to true).| |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for Amazon Kinesis Streams. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| |streamEnvironmentVariableName?|`string`|Optional Name to override the Lambda Function default environment variable name that holds the Kinesis Data Stream name value. Default: KINESIS_DATASTREAM_NAME | diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/lib/index.ts index 06d6acbd1..f7451f252 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/lib/index.ts @@ -95,7 +95,9 @@ export class LambdaToKinesisStreams extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToKinesisStreamsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); + defaults.CheckKinesisStreamProps(props); // Setup the VPC if (props.deployVpc || props.existingVpc) { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingLambda.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingLambda.expected.json index 7ebdbedd1..11993f843 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingLambda.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingLambda.expected.json @@ -112,12 +112,6 @@ }, "S3Key": "c7dc0cc1b24bda1d2a5345f61897eee32184906649fdb1de93853c512e129dbf.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "KINESIS_DATASTREAM_NAME": { @@ -126,6 +120,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -168,9 +168,9 @@ "testlambdakinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarmC4A0FF00": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -181,9 +181,9 @@ "testlambdakinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarm9732E188": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingStream.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingStream.expected.json index 5b7140b32..aec1e8427 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingStream.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingStream.expected.json @@ -125,12 +125,6 @@ }, "S3Key": "c7dc0cc1b24bda1d2a5345f61897eee32184906649fdb1de93853c512e129dbf.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", - "Arn" - ] - }, "Environment": { "Variables": { "KINESIS_DATASTREAM_NAME": { @@ -139,6 +133,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -170,9 +170,9 @@ "testlambdakinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarmC4A0FF00": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -183,9 +183,9 @@ "testlambdakinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarm9732E188": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingStreamWithCmk.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingStreamWithCmk.expected.json index 9bb8057c1..7a8001b89 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingStreamWithCmk.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingStreamWithCmk.expected.json @@ -3,6 +3,7 @@ "testkey784D0285": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -30,8 +31,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" @@ -191,12 +191,6 @@ }, "S3Key": "c7dc0cc1b24bda1d2a5345f61897eee32184906649fdb1de93853c512e129dbf.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", - "Arn" - ] - }, "Environment": { "Variables": { "KINESIS_DATASTREAM_NAME": { @@ -205,6 +199,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -236,9 +236,9 @@ "testlambdakinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarmC4A0FF00": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -249,9 +249,9 @@ "testlambdakinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarm9732E188": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingVpc.expected.json index cef2eab71..bba6b14da 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.existingVpc.expected.json @@ -18,9 +18,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -37,7 +34,10 @@ "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -53,15 +53,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -78,12 +78,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -105,15 +105,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -129,9 +129,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -148,7 +145,10 @@ "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -164,15 +164,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -189,12 +189,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -216,15 +216,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -240,9 +240,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -259,7 +256,10 @@ "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -275,15 +275,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -300,12 +300,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -327,15 +327,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -351,9 +351,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -370,21 +367,24 @@ "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -401,21 +401,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -432,21 +429,24 @@ "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -463,21 +463,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -494,21 +491,24 @@ "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -525,12 +525,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -548,11 +548,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -574,7 +574,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingVpc/Vpc" + "Value": "existingVpc/Vpc/FlowLog" } ] } @@ -626,7 +626,7 @@ "Tags": [ { "Key": "Name", - "Value": "existingVpc/Vpc" + "Value": "existingVpc/Vpc/FlowLog" } ] }, @@ -646,10 +646,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -660,10 +656,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existingVpc/Vpc" + "Value": "existingVpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -672,6 +672,15 @@ "VpcKINESISSTREAMSC07D91B5": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "existingVpcKINESISSTREAMSsecuritygroupDE0E9DB9", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -684,18 +693,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "existingVpcKINESISSTREAMSsecuritygroupDE0E9DB9", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -707,7 +704,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3": { @@ -863,12 +863,6 @@ }, "S3Key": "c7dc0cc1b24bda1d2a5345f61897eee32184906649fdb1de93853c512e129dbf.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", - "Arn" - ] - }, "Environment": { "Variables": { "KINESIS_DATASTREAM_NAME": { @@ -877,6 +871,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -946,9 +946,9 @@ "testlambdakinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarmC4A0FF00": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -959,9 +959,9 @@ "testlambdakinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarm9732E188": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newStreamFromProps.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newStreamFromProps.expected.json index 8733cc5eb..323c78280 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newStreamFromProps.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newStreamFromProps.expected.json @@ -112,12 +112,6 @@ }, "S3Key": "c7dc0cc1b24bda1d2a5345f61897eee32184906649fdb1de93853c512e129dbf.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", - "Arn" - ] - }, "Environment": { "Variables": { "KINESIS_DATASTREAM_NAME": { @@ -126,6 +120,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -170,9 +170,9 @@ "testlambdakinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarmC4A0FF00": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -183,9 +183,9 @@ "testlambdakinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarm9732E188": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newVpc.expected.json index 7f798590d..1eddf3e1e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newVpc.expected.json @@ -153,12 +153,6 @@ }, "S3Key": "c7dc0cc1b24bda1d2a5345f61897eee32184906649fdb1de93853c512e129dbf.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", - "Arn" - ] - }, "Environment": { "Variables": { "KINESIS_DATASTREAM_NAME": { @@ -167,6 +161,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -233,9 +233,9 @@ "testlambdakinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarmC4A0FF00": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -246,9 +246,9 @@ "testlambdakinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarm9732E188": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -274,9 +274,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -293,21 +290,24 @@ "Key": "Name", "Value": "newVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "newVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -324,9 +324,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -343,21 +340,24 @@ "Key": "Name", "Value": "newVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "newVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -374,9 +374,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -393,21 +390,24 @@ "Key": "Name", "Value": "newVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "newVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -439,7 +439,7 @@ "Tags": [ { "Key": "Name", - "Value": "newVpc/Vpc" + "Value": "newVpc/Vpc/FlowLog" } ] } @@ -491,7 +491,7 @@ "Tags": [ { "Key": "Name", - "Value": "newVpc/Vpc" + "Value": "newVpc/Vpc/FlowLog" } ] }, @@ -511,10 +511,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -525,10 +521,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "newVpc/Vpc" + "Value": "newVpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -537,6 +537,15 @@ "VpcKINESISSTREAMSC07D91B5": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "newVpcKINESISSTREAMSsecuritygroup88F75AD5", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -549,18 +558,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "newVpcKINESISSTREAMSsecuritygroup88F75AD5", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -572,7 +569,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newVpcKINESISSTREAMSsecuritygroup88F75AD5": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newVpcFromProps.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newVpcFromProps.expected.json index fd977a1d1..398bfd9be 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newVpcFromProps.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.newVpcFromProps.expected.json @@ -153,12 +153,6 @@ }, "S3Key": "c7dc0cc1b24bda1d2a5345f61897eee32184906649fdb1de93853c512e129dbf.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", - "Arn" - ] - }, "Environment": { "Variables": { "KINESIS_DATASTREAM_NAME": { @@ -167,6 +161,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -225,9 +225,9 @@ "testlambdakinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarmC4A0FF00": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -238,9 +238,9 @@ "testlambdakinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarm9732E188": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, @@ -266,9 +266,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -285,21 +282,24 @@ "Key": "Name", "Value": "newVpcFromProps/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "newVpcFromProps/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -331,7 +331,7 @@ "Tags": [ { "Key": "Name", - "Value": "newVpcFromProps/Vpc" + "Value": "newVpcFromProps/Vpc/FlowLog" } ] } @@ -383,7 +383,7 @@ "Tags": [ { "Key": "Name", - "Value": "newVpcFromProps/Vpc" + "Value": "newVpcFromProps/Vpc/FlowLog" } ] }, @@ -403,10 +403,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -417,10 +413,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "newVpcFromProps/Vpc" + "Value": "newVpcFromProps/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -429,6 +429,15 @@ "VpcKINESISSTREAMSC07D91B5": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "newVpcFromPropsKINESISSTREAMSsecuritygroup9B3EE931", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -441,24 +450,15 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "newVpcFromPropsKINESISSTREAMSsecuritygroup9B3EE931", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "newVpcFromPropsKINESISSTREAMSsecuritygroup9B3EE931": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.noArguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.noArguments.expected.json index c79909567..8b55b1488 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.noArguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/integ.noArguments.expected.json @@ -112,12 +112,6 @@ }, "S3Key": "c7dc0cc1b24bda1d2a5345f61897eee32184906649fdb1de93853c512e129dbf.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", - "Arn" - ] - }, "Environment": { "Variables": { "KINESIS_DATASTREAM_NAME": { @@ -126,6 +120,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdakinesisstreamsLambdaFunctionServiceRole95206CF3", + "Arn" + ] + }, "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -168,9 +168,9 @@ "testlambdakinesisstreamsKinesisStreamGetRecordsIteratorAgeAlarmC4A0FF00": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", "MetricName": "GetRecords.IteratorAgeMilliseconds", "Namespace": "AWS/Kinesis", "Period": 300, @@ -181,9 +181,9 @@ "testlambdakinesisstreamsKinesisStreamReadProvisionedThroughputExceededAlarm9732E188": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "ComparisonOperator": "GreaterThanThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", "MetricName": "ReadProvisionedThroughputExceeded", "Namespace": "AWS/Kinesis", "Period": 300, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/lambda-kinesisstream.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/lambda-kinesisstream.test.ts index 60c375174..05fd96014 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/lambda-kinesisstream.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-kinesisstreams/test/lambda-kinesisstream.test.ts @@ -11,7 +11,7 @@ * and limitations under the License. */ -import { LambdaToKinesisStreams } from "../lib"; +import { LambdaToKinesisStreams, LambdaToKinesisStreamsProps } from "../lib"; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as cdk from "aws-cdk-lib"; import * as ec2 from "aws-cdk-lib/aws-ec2"; @@ -549,4 +549,75 @@ function verifyLambdaFunctionVpcProps(template: Template, vpcId: string, subnetT EnableDnsHostnames: true, EnableDnsSupport: true, }); -} \ No newline at end of file +} + +test('Confirm CheckVpcProps() is being called', () => { + const stack = new cdk.Stack(); + + const vpc = defaults.buildVpc(stack, { + defaultVpcProps: defaults.DefaultIsolatedVpcProps(), + constructVpcProps: { + enableDnsHostnames: true, + enableDnsSupport: true, + }, + }); + + const app = () => { + // Helper declaration + new LambdaToKinesisStreams(stack, 'test-lambda-kinesisstreams', { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler' + }, + deployVpc: true, + existingVpc: vpc + }); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToKinesisStreamsProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToKinesisStreams(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); + +test('Confirm call to CheckKinesisStreamProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + + const props: LambdaToKinesisStreamsProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingStreamObj: new kinesis.Stream(stack, 'test', {}), + kinesisStreamProps: {} + }; + const app = () => { + new LambdaToKinesisStreams(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/lib/index.ts index af3bee054..ca1228cd7 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/lib/index.ts @@ -107,7 +107,9 @@ export class LambdaToOpenSearch extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToOpenSearchProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); + defaults.CheckOpenSearchProps(props); if (props.vpcProps && !props.deployVpc) { throw new Error("Error - deployVpc must be true when defining vpcProps"); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.cluster-config.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.cluster-config.expected.json index f301d04d5..451416bce 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.cluster-config.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.cluster-config.expected.json @@ -139,12 +139,6 @@ }, "S3Key": "abbc4eca9e7ddabc31da3ce83159e6eee8e72e2c358ab8af0711044514c41290.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -157,6 +151,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -242,9 +242,6 @@ "testlambdaopensearchCognitoUserPoolClient39C21D94": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -262,7 +259,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" + } } }, "testlambdaopensearchCognitoIdentityPool0B1FB311": { @@ -618,9 +618,9 @@ "testlambdaopensearchStatusRedAlarm1627144D": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -631,9 +631,9 @@ "testlambdaopensearchStatusYellowAlarm57139CF0": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -644,9 +644,9 @@ "testlambdaopensearchFreeStorageSpaceTooLowAlarm6A5E1E96": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -657,9 +657,9 @@ "testlambdaopensearchIndexWritesBlockedTooHighAlarmD2E041A3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -670,9 +670,9 @@ "testlambdaopensearchAutomatedSnapshotFailureTooHighAlarm9A4D0B1F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -683,9 +683,9 @@ "testlambdaopensearchCPUUtilizationTooHighAlarmC4850758": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -696,9 +696,9 @@ "testlambdaopensearchJVMMemoryPressureTooHighAlarmEFB09A7C": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -709,9 +709,9 @@ "testlambdaopensearchMasterCPUUtilizationTooHighAlarm124D5748": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -722,9 +722,9 @@ "testlambdaopensearchMasterJVMMemoryPressureTooHighAlarmBC9524D3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -750,9 +750,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -769,21 +766,24 @@ "Key": "Name", "Value": "cluster-config/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "cluster-config/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -800,9 +800,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -819,21 +816,24 @@ "Key": "Name", "Value": "cluster-config/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "cluster-config/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -865,7 +865,7 @@ "Tags": [ { "Key": "Name", - "Value": "cluster-config/Vpc" + "Value": "cluster-config/Vpc/FlowLog" } ] } @@ -917,7 +917,7 @@ "Tags": [ { "Key": "Name", - "Value": "cluster-config/Vpc" + "Value": "cluster-config/Vpc/FlowLog" } ] }, @@ -937,10 +937,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -951,10 +947,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "cluster-config/Vpc" + "Value": "cluster-config/Vpc/FlowLog" } ], "TrafficType": "ALL" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.disabled-zone-awareness.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.disabled-zone-awareness.expected.json index 6e7f1368a..bacca0a29 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.disabled-zone-awareness.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.disabled-zone-awareness.expected.json @@ -139,12 +139,6 @@ }, "S3Key": "abbc4eca9e7ddabc31da3ce83159e6eee8e72e2c358ab8af0711044514c41290.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -157,6 +151,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -238,9 +238,6 @@ "testlambdaopensearchCognitoUserPoolClient39C21D94": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -258,7 +255,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" + } } }, "testlambdaopensearchCognitoIdentityPool0B1FB311": { @@ -608,9 +608,9 @@ "testlambdaopensearchStatusRedAlarm1627144D": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -621,9 +621,9 @@ "testlambdaopensearchStatusYellowAlarm57139CF0": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -634,9 +634,9 @@ "testlambdaopensearchFreeStorageSpaceTooLowAlarm6A5E1E96": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -647,9 +647,9 @@ "testlambdaopensearchIndexWritesBlockedTooHighAlarmD2E041A3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -660,9 +660,9 @@ "testlambdaopensearchAutomatedSnapshotFailureTooHighAlarm9A4D0B1F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -673,9 +673,9 @@ "testlambdaopensearchCPUUtilizationTooHighAlarmC4850758": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -686,9 +686,9 @@ "testlambdaopensearchJVMMemoryPressureTooHighAlarmEFB09A7C": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -699,9 +699,9 @@ "testlambdaopensearchMasterCPUUtilizationTooHighAlarm124D5748": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -712,9 +712,9 @@ "testlambdaopensearchMasterJVMMemoryPressureTooHighAlarmBC9524D3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -740,9 +740,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -759,21 +756,24 @@ "Key": "Name", "Value": "disabled-zone-awareness/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "disabled-zone-awareness/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -805,7 +805,7 @@ "Tags": [ { "Key": "Name", - "Value": "disabled-zone-awareness/Vpc" + "Value": "disabled-zone-awareness/Vpc/FlowLog" } ] } @@ -857,7 +857,7 @@ "Tags": [ { "Key": "Name", - "Value": "disabled-zone-awareness/Vpc" + "Value": "disabled-zone-awareness/Vpc/FlowLog" } ] }, @@ -877,10 +877,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -891,10 +887,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "disabled-zone-awareness/Vpc" + "Value": "disabled-zone-awareness/Vpc/FlowLog" } ], "TrafficType": "ALL" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.domain-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.domain-arguments.expected.json index a62047ffa..997380f00 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.domain-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.domain-arguments.expected.json @@ -98,12 +98,6 @@ }, "S3Key": "abbc4eca9e7ddabc31da3ce83159e6eee8e72e2c358ab8af0711044514c41290.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -116,6 +110,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -181,9 +181,6 @@ "testlambdaopensearchCognitoUserPoolClient39C21D94": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -201,7 +198,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" + } } }, "testlambdaopensearchCognitoIdentityPool0B1FB311": { @@ -539,9 +539,9 @@ "testlambdaopensearchStatusRedAlarm1627144D": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -552,9 +552,9 @@ "testlambdaopensearchStatusYellowAlarm57139CF0": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -565,9 +565,9 @@ "testlambdaopensearchFreeStorageSpaceTooLowAlarm6A5E1E96": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -578,9 +578,9 @@ "testlambdaopensearchIndexWritesBlockedTooHighAlarmD2E041A3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -591,9 +591,9 @@ "testlambdaopensearchAutomatedSnapshotFailureTooHighAlarm9A4D0B1F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -604,9 +604,9 @@ "testlambdaopensearchCPUUtilizationTooHighAlarmC4850758": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -617,9 +617,9 @@ "testlambdaopensearchJVMMemoryPressureTooHighAlarmEFB09A7C": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -630,9 +630,9 @@ "testlambdaopensearchMasterCPUUtilizationTooHighAlarm124D5748": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -643,9 +643,9 @@ "testlambdaopensearchMasterJVMMemoryPressureTooHighAlarmBC9524D3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.existing-vpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.existing-vpc.expected.json index d15057b56..3115d78a4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.existing-vpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.existing-vpc.expected.json @@ -18,9 +18,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -37,7 +34,10 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -53,15 +53,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -78,12 +78,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -105,15 +105,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -129,9 +129,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -148,7 +145,10 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -164,15 +164,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -189,12 +189,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -216,15 +216,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -240,9 +240,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -259,7 +256,10 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -275,15 +275,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -300,12 +300,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -327,15 +327,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -351,9 +351,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -370,21 +367,24 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -401,21 +401,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -432,21 +429,24 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -463,21 +463,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -494,21 +491,24 @@ "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "existing-vpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -525,12 +525,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -548,11 +548,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -574,7 +574,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-vpc/Vpc" + "Value": "existing-vpc/Vpc/FlowLog" } ] } @@ -626,7 +626,7 @@ "Tags": [ { "Key": "Name", - "Value": "existing-vpc/Vpc" + "Value": "existing-vpc/Vpc/FlowLog" } ] }, @@ -646,10 +646,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -660,10 +656,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "existing-vpc/Vpc" + "Value": "existing-vpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -806,12 +806,6 @@ "S3Bucket": "cdk-hnb659fds-assets-12345678-test-region", "S3Key": "abbc4eca9e7ddabc31da3ce83159e6eee8e72e2c358ab8af0711044514c41290.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaelasticsearchkibana4LambdaFunctionServiceRoleA52BB7F9", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -824,6 +818,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaelasticsearchkibana4LambdaFunctionServiceRoleA52BB7F9", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -916,9 +916,6 @@ "testlambdaelasticsearchkibana4CognitoUserPoolClientABBF34C4": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaelasticsearchkibana4CognitoUserPool37A5CDE1" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -936,7 +933,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaelasticsearchkibana4CognitoUserPool37A5CDE1" + } } }, "testlambdaelasticsearchkibana4CognitoIdentityPool76EE9793": { @@ -1295,9 +1295,9 @@ "testlambdaelasticsearchkibana4StatusRedAlarm56DEE5C7": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -1308,9 +1308,9 @@ "testlambdaelasticsearchkibana4StatusYellowAlarm810B4F9E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -1321,9 +1321,9 @@ "testlambdaelasticsearchkibana4FreeStorageSpaceTooLowAlarmF3FB31EA": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -1334,9 +1334,9 @@ "testlambdaelasticsearchkibana4IndexWritesBlockedTooHighAlarmF2968C92": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -1347,9 +1347,9 @@ "testlambdaelasticsearchkibana4AutomatedSnapshotFailureTooHighAlarm53EB1ABB": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -1360,9 +1360,9 @@ "testlambdaelasticsearchkibana4CPUUtilizationTooHighAlarm29B67D10": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -1373,9 +1373,9 @@ "testlambdaelasticsearchkibana4JVMMemoryPressureTooHighAlarm9DDED711": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -1386,9 +1386,9 @@ "testlambdaelasticsearchkibana4MasterCPUUtilizationTooHighAlarmE66867F2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -1399,9 +1399,9 @@ "testlambdaelasticsearchkibana4MasterJVMMemoryPressureTooHighAlarm83E1822E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.no-arguments.expected.json index 92867fabe..bb4aceef8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.no-arguments.expected.json @@ -98,12 +98,6 @@ }, "S3Key": "abbc4eca9e7ddabc31da3ce83159e6eee8e72e2c358ab8af0711044514c41290.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -116,6 +110,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -181,9 +181,6 @@ "testlambdaopensearchCognitoUserPoolClient39C21D94": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -201,7 +198,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" + } } }, "testlambdaopensearchCognitoIdentityPool0B1FB311": { @@ -539,9 +539,9 @@ "testlambdaopensearchStatusRedAlarm1627144D": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -552,9 +552,9 @@ "testlambdaopensearchStatusYellowAlarm57139CF0": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -565,9 +565,9 @@ "testlambdaopensearchFreeStorageSpaceTooLowAlarm6A5E1E96": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -578,9 +578,9 @@ "testlambdaopensearchIndexWritesBlockedTooHighAlarmD2E041A3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -591,9 +591,9 @@ "testlambdaopensearchAutomatedSnapshotFailureTooHighAlarm9A4D0B1F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -604,9 +604,9 @@ "testlambdaopensearchCPUUtilizationTooHighAlarmC4850758": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -617,9 +617,9 @@ "testlambdaopensearchJVMMemoryPressureTooHighAlarmEFB09A7C": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -630,9 +630,9 @@ "testlambdaopensearchMasterCPUUtilizationTooHighAlarm124D5748": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -643,9 +643,9 @@ "testlambdaopensearchMasterJVMMemoryPressureTooHighAlarmBC9524D3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.vpc-props.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.vpc-props.expected.json index d19b26bde..21ebb11c4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.vpc-props.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/integ.vpc-props.expected.json @@ -137,12 +137,6 @@ "S3Bucket": "cdk-hnb659fds-assets-12345678-test-region", "S3Key": "abbc4eca9e7ddabc31da3ce83159e6eee8e72e2c358ab8af0711044514c41290.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -155,6 +149,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdaopensearchLambdaFunctionServiceRole4722AB8A", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -244,9 +244,6 @@ "testlambdaopensearchCognitoUserPoolClient39C21D94": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { - "UserPoolId": { - "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" - }, "AllowedOAuthFlows": [ "implicit", "code" @@ -264,7 +261,10 @@ ], "SupportedIdentityProviders": [ "COGNITO" - ] + ], + "UserPoolId": { + "Ref": "testlambdaopensearchCognitoUserPoolA09096F9" + } } }, "testlambdaopensearchCognitoIdentityPool0B1FB311": { @@ -623,9 +623,9 @@ "testlambdaopensearchStatusRedAlarm1627144D": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one primary shard and its replicas are not allocated to a node. ", "MetricName": "ClusterStatus.red", "Namespace": "AWS/ES", "Period": 60, @@ -636,9 +636,9 @@ "testlambdaopensearchStatusYellowAlarm57139CF0": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "At least one replica shard is not allocated to a node.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "At least one replica shard is not allocated to a node.", "MetricName": "ClusterStatus.yellow", "Namespace": "AWS/ES", "Period": 60, @@ -649,9 +649,9 @@ "testlambdaopensearchFreeStorageSpaceTooLowAlarm6A5E1E96": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "ComparisonOperator": "LessThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "A node in your cluster is down to 20 GiB of free storage space.", "MetricName": "FreeStorageSpace", "Namespace": "AWS/ES", "Period": 60, @@ -662,9 +662,9 @@ "testlambdaopensearchIndexWritesBlockedTooHighAlarmD2E041A3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Your cluster is blocking write requests.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Your cluster is blocking write requests.", "MetricName": "ClusterIndexWritesBlocked", "Namespace": "AWS/ES", "Period": 300, @@ -675,9 +675,9 @@ "testlambdaopensearchAutomatedSnapshotFailureTooHighAlarm9A4D0B1F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "An automated snapshot failed. This failure is often the result of a red cluster health status.", "MetricName": "AutomatedSnapshotFailure", "Namespace": "AWS/ES", "Period": 60, @@ -688,9 +688,9 @@ "testlambdaopensearchCPUUtilizationTooHighAlarmC4850758": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "100% CPU utilization is not uncommon, but sustained high usage is problematic. Consider using larger instance types or adding instances.", "MetricName": "CPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -701,9 +701,9 @@ "testlambdaopensearchJVMMemoryPressureTooHighAlarmEFB09A7C": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "JVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -714,9 +714,9 @@ "testlambdaopensearchMasterCPUUtilizationTooHighAlarm124D5748": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 3, - "AlarmDescription": "Average CPU utilization over last 45 minutes too high. Consider using larger instance types for your dedicated master nodes.", "MetricName": "MasterCPUUtilization", "Namespace": "AWS/ES", "Period": 900, @@ -727,9 +727,9 @@ "testlambdaopensearchMasterJVMMemoryPressureTooHighAlarmBC9524D3": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "EvaluationPeriods": 1, - "AlarmDescription": "Average JVM memory pressure over last 15 minutes too high. Consider scaling vertically.", "MetricName": "MasterJVMMemoryPressure", "Namespace": "AWS/ES", "Period": 900, @@ -755,9 +755,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/18", "MapPublicIpOnLaunch": false, @@ -774,21 +771,24 @@ "Key": "Name", "Value": "vpc-props/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpc-props/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -805,9 +805,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.64.0/18", "MapPublicIpOnLaunch": false, @@ -824,21 +821,24 @@ "Key": "Name", "Value": "vpc-props/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpc-props/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -855,9 +855,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.128.0/18", "MapPublicIpOnLaunch": false, @@ -874,21 +871,24 @@ "Key": "Name", "Value": "vpc-props/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "vpc-props/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -920,7 +920,7 @@ "Tags": [ { "Key": "Name", - "Value": "vpc-props/Vpc" + "Value": "vpc-props/Vpc/FlowLog" } ] } @@ -972,7 +972,7 @@ "Tags": [ { "Key": "Name", - "Value": "vpc-props/Vpc" + "Value": "vpc-props/Vpc/FlowLog" } ] }, @@ -992,10 +992,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1006,10 +1002,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "vpc-props/Vpc" + "Value": "vpc-props/Vpc/FlowLog" } ], "TrafficType": "ALL" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/lambda-opensearch.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/lambda-opensearch.test.ts index a3620631e..1c75c121b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/lambda-opensearch.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-opensearch/test/lambda-opensearch.test.ts @@ -69,6 +69,25 @@ test('Check properties with no CloudWatch alarms ', () => { expect(construct.openSearchRole).toBeDefined(); }); +test('Check that TLS 1.2 is the default', () => { + const stack = new cdk.Stack(); + + const props: LambdaToOpenSearchProps = { + lambdaFunctionProps: getDefaultTestLambdaProps(), + openSearchDomainName: 'test-domain', + createCloudWatchAlarms: false + }; + + new LambdaToOpenSearch(stack, 'test-lambda-opensearch-stack', props); + const template = Template.fromStack(stack); + template.hasResourceProperties("AWS::OpenSearchService::Domain", { + DomainEndpointOptions: { + EnforceHTTPS: true, + TLSSecurityPolicy: "Policy-Min-TLS-1-2-2019-07" + }, + }); +}); + test('Check for an existing Lambda object', () => { const stack = new cdk.Stack(); @@ -548,7 +567,7 @@ test('Test error for Lambda function VPC props', () => { expect(app).toThrowError("Error - Define VPC using construct parameters not Lambda function props"); }); -test('Test error for the OpenSearch domain VPC props', () => { +test('Confirm CheckOpenSearchProps is called', () => { const stack = new cdk.Stack(); const app = () => { @@ -581,3 +600,53 @@ test('Test error for missing existingLambdaObj or lambdaFunctionProps', () => { expect(e).toBeInstanceOf(Error); } }); + +test('Confirm CheckVpcProps is being called', () => { + const stack = new cdk.Stack(); + const vpc = defaults.buildVpc(stack, { + defaultVpcProps: defaults.DefaultIsolatedVpcProps(), + constructVpcProps: { + enableDnsHostnames: true, + enableDnsSupport: true, + }, + }); + + const app = () => { + new LambdaToOpenSearch(stack, 'test-lambda-opensearch', { + lambdaFunctionProps: getDefaultTestLambdaProps(), + openSearchDomainName: "test", + vpcProps: { + vpcName: "existing-vpc-test" + }, + deployVpc: true, + existingVpc: vpc + }); + }; + + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToOpenSearchProps = { + openSearchDomainName: 'name', + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToOpenSearch(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/README.md index 911720e6b..40a8fa9d6 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/README.md @@ -86,7 +86,7 @@ new LambdaToS3(this, "LambdaToS3Pattern", new LambdaToS3Props.Builder() |bucketProps?|[`s3.BucketProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html)|Optional user provided props to override the default props for the S3 Bucket.| |bucketPermissions?|`string[]`|Optional bucket permissions to grant to the Lambda function. One or more of the following may be specified: `Delete`, `Put`, `Read`, `ReadWrite`, `Write`.| |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for Amazon S3. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| |bucketEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the name of the bucket. Default: S3_BUCKET_NAME | |loggingBucketProps?|[`s3.BucketProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html)|Optional user provided props to override the default props for the S3 Logging Bucket.| diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/lib/index.ts index 92c805d0d..8985f7ed8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/lib/index.ts @@ -79,110 +79,119 @@ export interface LambdaToS3Props { * * @default - Default props are used */ - readonly loggingBucketProps?: s3.BucketProps + readonly loggingBucketProps?: s3.BucketProps /** * Whether to turn on Access Logs for the S3 bucket with the associated storage costs. * Enabling Access Logging is a best practice. * * @default - true */ - readonly logS3AccessLogs?: boolean; + readonly logS3AccessLogs?: boolean; } /** * @summary The LambdaToS3 class. */ export class LambdaToS3 extends Construct { - public readonly lambdaFunction: lambda.Function; - public readonly s3Bucket?: s3.Bucket; - public readonly s3LoggingBucket?: s3.Bucket; - public readonly vpc?: ec2.IVpc; - public readonly s3BucketInterface: s3.IBucket; - - /** - * @summary Constructs a new instance of the LambdaToS3 class. - * @param {cdk.App} scope - represents the scope for all the resources. - * @param {string} id - this is a a scope-unique id. - * @param {LambdaToS3Props} props - user provided props for the construct. - * @since 0.8.0 - * @access public - */ - constructor(scope: Construct, id: string, props: LambdaToS3Props) { - super(scope, id); - - // All our tests are based upon this behavior being on, so we're setting - // context here rather than assuming the client will set it - this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - - defaults.CheckProps(props); - - if (props.bucketPermissions) { - defaults.CheckListValues(['Delete', 'Put', 'Read', 'ReadWrite', 'Write'], props.bucketPermissions, 'bucket permission'); - } - - let bucket: s3.IBucket; - - if (props.deployVpc || props.existingVpc) { - this.vpc = defaults.buildVpc(scope, { - defaultVpcProps: defaults.DefaultIsolatedVpcProps(), - existingVpc: props.existingVpc, - userVpcProps: props.vpcProps, - constructVpcProps: { - enableDnsHostnames: true, - enableDnsSupport: true, - }, - }); - - defaults.AddAwsServiceEndpoint(scope, this.vpc, defaults.ServiceEndpointTypes.S3); - } - - // Setup the Lambda function - this.lambdaFunction = defaults.buildLambdaFunction(this, { - existingLambdaObj: props.existingLambdaObj, - lambdaFunctionProps: props.lambdaFunctionProps, - vpc: this.vpc, + public readonly lambdaFunction: lambda.Function; + public readonly s3Bucket?: s3.Bucket; + public readonly s3LoggingBucket?: s3.Bucket; + public readonly vpc?: ec2.IVpc; + public readonly s3BucketInterface: s3.IBucket; + + /** + * @summary Constructs a new instance of the LambdaToS3 class. + * @param {cdk.App} scope - represents the scope for all the resources. + * @param {string} id - this is a a scope-unique id. + * @param {LambdaToS3Props} props - user provided props for the construct. + * @since 0.8.0 + * @access public + */ + constructor(scope: Construct, id: string, props: LambdaToS3Props) { + super(scope, id); + + // All our tests are based upon this behavior being on, so we're setting + // context here rather than assuming the client will set it + this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); + + defaults.CheckS3Props(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); + + if (props.bucketPermissions) { + defaults.CheckListValues(['Delete', 'Put', 'Read', 'ReadWrite', 'Write'], props.bucketPermissions, 'bucket permission'); + } + + let bucket: s3.IBucket; + + if (props.deployVpc || props.existingVpc) { + this.vpc = defaults.buildVpc(scope, { + defaultVpcProps: defaults.DefaultIsolatedVpcProps(), + existingVpc: props.existingVpc, + userVpcProps: props.vpcProps, + constructVpcProps: { + enableDnsHostnames: true, + enableDnsSupport: true, + }, + }); + + defaults.AddAwsServiceEndpoint(scope, this.vpc, defaults.ServiceEndpointTypes.S3); + } + + // Setup the Lambda function + this.lambdaFunction = defaults.buildLambdaFunction(this, { + existingLambdaObj: props.existingLambdaObj, + lambdaFunctionProps: props.lambdaFunctionProps, + vpc: this.vpc, + }); + + // Setup S3 Bucket + if (!props.existingBucketObj) { + const buildS3BucketResponse = defaults.buildS3Bucket(this, { + bucketProps: props.bucketProps, + loggingBucketProps: props.loggingBucketProps, + logS3AccessLogs: props.logS3AccessLogs }); + this.s3Bucket = buildS3BucketResponse.bucket; + this.s3LoggingBucket = buildS3BucketResponse.loggingBucket; - // Setup S3 Bucket - if (!props.existingBucketObj) { - const buildS3BucketResponse = defaults.buildS3Bucket(this, { - bucketProps: props.bucketProps, - loggingBucketProps: props.loggingBucketProps, - logS3AccessLogs: props.logS3AccessLogs - }); - this.s3Bucket = buildS3BucketResponse.bucket; - this.s3LoggingBucket = buildS3BucketResponse.loggingBucket; - - bucket = this.s3Bucket; - } else { - bucket = props.existingBucketObj; - } - - this.s3BucketInterface = bucket; - - // Configure environment variables - const bucketEnvironmentVariableName = props.bucketEnvironmentVariableName || 'S3_BUCKET_NAME'; - this.lambdaFunction.addEnvironment(bucketEnvironmentVariableName, bucket.bucketName); - - // Add the requested or default bucket permissions - if (props.bucketPermissions) { - if (props.bucketPermissions.includes('Delete')) { - bucket.grantDelete(this.lambdaFunction.grantPrincipal); - } - if (props.bucketPermissions.includes('Put')) { - bucket.grantPut(this.lambdaFunction.grantPrincipal); - } - if (props.bucketPermissions.includes('Read')) { - bucket.grantRead(this.lambdaFunction.grantPrincipal); - } - if (props.bucketPermissions.includes('ReadWrite')) { - bucket.grantReadWrite(this.lambdaFunction.grantPrincipal); - } - if (props.bucketPermissions.includes('Write')) { - bucket.grantWrite(this.lambdaFunction.grantPrincipal); - } - } else { - bucket.grantReadWrite(this.lambdaFunction.grantPrincipal); - } + bucket = this.s3Bucket; + } else { + bucket = props.existingBucketObj; + } + + this.s3BucketInterface = bucket; + + // Configure environment variables + const bucketEnvironmentVariableName = props.bucketEnvironmentVariableName || 'S3_BUCKET_NAME'; + this.lambdaFunction.addEnvironment(bucketEnvironmentVariableName, bucket.bucketName); + + // Add the requested or default bucket permissions + if (props.bucketPermissions) { + this.AssignAppropriatePrivileges(props, bucket, this.lambdaFunction); + } else { + bucket.grantReadWrite(this.lambdaFunction.grantPrincipal); + } + } + + private AssignAppropriatePrivileges(props: LambdaToS3Props, bucket: s3.IBucket, clientFunction: lambda.Function) { + if (!props.bucketPermissions) { + throw new Error('bucketPermissions required here'); + } + if (props.bucketPermissions.includes('Delete')) { + bucket.grantDelete(clientFunction.grantPrincipal); + } + if (props.bucketPermissions.includes('Put')) { + bucket.grantPut(clientFunction.grantPrincipal); + } + if (props.bucketPermissions.includes('Read')) { + bucket.grantRead(clientFunction.grantPrincipal); + } + if (props.bucketPermissions.includes('ReadWrite')) { + bucket.grantReadWrite(clientFunction.grantPrincipal); + } + if (props.bucketPermissions.includes('Write')) { + bucket.grantWrite(clientFunction.grantPrincipal); } + } } \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.customLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.customLoggingBucket.expected.json index 37e83bd90..486e68be1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.customLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.customLoggingBucket.expected.json @@ -135,12 +135,6 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdas3LambdaFunctionServiceRole72E20379", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -150,6 +144,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdas3LambdaFunctionServiceRole72E20379", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.deployFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.deployFunction.expected.json index b9545b2ce..c0a10dbae 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.deployFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.deployFunction.expected.json @@ -136,12 +136,6 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdas3LambdaFunctionServiceRole72E20379", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -151,6 +145,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdas3LambdaFunctionServiceRole72E20379", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.deployFunctionWithVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.deployFunctionWithVpc.expected.json index 058678598..299acbe25 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.deployFunctionWithVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.deployFunctionWithVpc.expected.json @@ -177,12 +177,6 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdas3LambdaFunctionServiceRole72E20379", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -192,6 +186,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdas3LambdaFunctionServiceRole72E20379", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -357,9 +357,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -376,21 +373,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -407,9 +407,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -426,21 +423,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -457,9 +457,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -476,21 +473,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -522,7 +522,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] } @@ -574,7 +574,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] }, @@ -594,10 +594,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -608,10 +604,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -620,6 +620,17 @@ "VpcS3A5408339": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "RouteTableIds": [ + { + "Ref": "VpcisolatedSubnet1RouteTableE442650B" + }, + { + "Ref": "VpcisolatedSubnet2RouteTable334F9764" + }, + { + "Ref": "VpcisolatedSubnet3RouteTableA2F6BBC0" + } + ], "ServiceName": { "Fn::Join": [ "", @@ -632,21 +643,10 @@ ] ] }, + "VpcEndpointType": "Gateway", "VpcId": { "Ref": "Vpc8378EB38" - }, - "RouteTableIds": [ - { - "Ref": "VpcisolatedSubnet1RouteTableE442650B" - }, - { - "Ref": "VpcisolatedSubnet2RouteTable334F9764" - }, - { - "Ref": "VpcisolatedSubnet3RouteTableA2F6BBC0" - } - ], - "VpcEndpointType": "Gateway" + } } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.existingFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.existingFunction.expected.json index 36099ea36..fa52e013d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.existingFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.existingFunction.expected.json @@ -136,12 +136,6 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -151,6 +145,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.pre-existing-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.pre-existing-bucket.expected.json index 141f895da..03aafe278 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.pre-existing-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/integ.pre-existing-bucket.expected.json @@ -143,18 +143,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -336,12 +336,6 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdas3preexistingbucketLambdaFunctionServiceRole9AC7CED0", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -351,6 +345,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdas3preexistingbucketLambdaFunctionServiceRole9AC7CED0", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -380,109 +380,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/lambda-s3.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/lambda-s3.test.ts index a8c51de75..031ce1242 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/lambda-s3.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-s3/test/lambda-s3.test.ts @@ -16,13 +16,10 @@ import { Stack, RemovalPolicy } from "aws-cdk-lib"; import * as lambda from "aws-cdk-lib/aws-lambda"; import * as ec2 from "aws-cdk-lib/aws-ec2"; import * as s3 from "aws-cdk-lib/aws-s3"; -import { LambdaToS3 } from '../lib'; -import { CreateScrapBucket } from '@aws-solutions-constructs/core'; +import { LambdaToS3, LambdaToS3Props } from '../lib'; +import * as defaults from '@aws-solutions-constructs/core'; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Test the getter methods -// -------------------------------------------------------------- test('Test the properties', () => { // Stack const stack = new Stack(); @@ -37,16 +34,13 @@ test('Test the properties', () => { }); // Assertion 1 const func = pattern.lambdaFunction; - expect(func !== null); + expect(func).toBeDefined(); // Assertion 2 const bucket = pattern.s3Bucket; - expect(bucket !== null); - expect(pattern.s3LoggingBucket !== null); + expect(bucket).toBeDefined(); + expect(pattern.s3LoggingBucket).toBeDefined(); }); -// -------------------------------------------------------------- -// Test the bucketProps override -// -------------------------------------------------------------- test('Test the bucketProps override', () => { // Stack const stack = new Stack(); @@ -69,9 +63,6 @@ test('Test the bucketProps override', () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC without vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC without vpcProps", () => { // Stack const stack = new Stack(); @@ -120,9 +111,6 @@ test("Test minimal deployment that deploys a VPC without vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC w/vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC w/vpcProps", () => { // Stack const stack = new Stack(); @@ -177,9 +165,6 @@ test("Test minimal deployment that deploys a VPC w/vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC", () => { // Stack const stack = new Stack(); @@ -223,12 +208,6 @@ test("Test minimal deployment with an existing VPC", () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC and existing Lambda function not in a VPC -// -// buildLambdaFunction should throw an error if the Lambda function is not -// attached to a VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC and existing Lambda function not in a VPC", () => { // Stack const stack = new Stack(); @@ -243,7 +222,8 @@ test("Test minimal deployment with an existing VPC and existing Lambda function // Helper declaration const app = () => { - // Helper declaration + // buildLambdaFunction should throw an error if the Lambda function is not + // attached to a VPC new LambdaToS3(stack, "lambda-to-s3-stack", { existingLambdaObj: testLambdaFunction, existingVpc: testVpc, @@ -255,40 +235,12 @@ test("Test minimal deployment with an existing VPC and existing Lambda function }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { - // Stack - const stack = new Stack(); - - const testVpc = new ec2.Vpc(stack, "test-vpc", {}); - - const app = () => { - // Helper declaration - new LambdaToS3(stack, "lambda-to-s3-stack", { - lambdaFunctionProps: { - runtime: lambda.Runtime.NODEJS_16_X, - handler: "index.handler", - code: lambda.Code.fromAsset(`${__dirname}/lambda`), - }, - existingVpc: testVpc, - deployVpc: true, - }); - }; - // Assertion - expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); -}); - -// -------------------------------------------------------------- -// Test lambda function custom environment variable -// -------------------------------------------------------------- test('Test lambda function custom environment variable', () => { // Stack const stack = new Stack(); // Helper declaration - const existingBucket = CreateScrapBucket(stack, {}); + const existingBucket = defaults.CreateScrapBucket(stack, {}); const mybucket: s3.IBucket = s3.Bucket.fromBucketName(stack, 'mybucket', existingBucket.bucketName); new LambdaToS3(stack, 'lambda-to-s3-stack', { existingBucketObj: mybucket, @@ -319,7 +271,7 @@ test('Test lambda function custom environment variable', () => { // -------------------------------------------------------------- // Test bad call with existingBucket and bucketProps // -------------------------------------------------------------- -test("Test bad call with existingBucket and bucketProps", () => { +test("Confirm that CheckS3Props is being called", () => { // Stack const stack = new Stack(); @@ -340,7 +292,7 @@ test("Test bad call with existingBucket and bucketProps", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); }); test('Test that CheckProps() is flagging errors correctly', () => { @@ -371,9 +323,6 @@ test('Test that CheckProps() is flagging errors correctly', () => { }); -// -------------------------------------------------------------- -// s3 bucket with bucket, loggingBucket, and auto delete objects -// -------------------------------------------------------------- test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { const stack = new Stack(); @@ -408,9 +357,6 @@ test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { }); }); -// -------------------------------------------------------------- -// s3 bucket with one content bucket and no logging bucket -// -------------------------------------------------------------- test('s3 bucket with one content bucket and no logging bucket', () => { const stack = new Stack(); @@ -452,3 +398,57 @@ test('Test bad bucket permission', () => { expect(alb).toThrowError('Invalid bucket permission submitted - Reed'); }); + +test("Confirm that CheckVpcProps is being called", () => { + // Stack + const stack = new Stack(); + const vpc = defaults.buildVpc(stack, { + defaultVpcProps: defaults.DefaultIsolatedVpcProps(), + constructVpcProps: { + enableDnsHostnames: true, + enableDnsSupport: true, + }, + }); + + const app = () => { + // Helper declaration + new LambdaToS3(stack, "bad-s3-args", { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + bucketProps: { + removalPolicy: RemovalPolicy.DESTROY + }, + deployVpc: true, + existingVpc: vpc, + }); + }; + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToS3Props = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToS3(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/README.md index fcb6bc26c..4320a0cae 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/README.md @@ -123,12 +123,12 @@ new LambdaToSagemakerEndpoint(this, "LambdaToSagemakerEndpointPattern", |:-------------|:----------------|-----------------| |existingLambdaObj?|[`lambda.Function`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html)|An optional, existing Lambda function to be used instead of the default function. Providing both this and `lambdaFunctionProps` will cause an error.| |lambdaFunctionProps?|[`lambda.FunctionProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.FunctionProps.html)|Optional user-provided properties to override the default properties for the Lambda function.| -|existingSagemakerEndpointObj?|[`sagemaker.CfnEndpoint`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sagemaker.CfnEndpoint.html)|An optional, existing SageMaker Enpoint to be used. Providing both this and `endpointProps?` will cause an error.| +|existingSagemakerEndpointObj?|[`sagemaker.CfnEndpoint`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sagemaker.CfnEndpoint.html)|An optional, existing SageMaker Endpoint to be used. Providing both this and `endpointProps?` will cause an error.| |modelProps?|[`sagemaker.CfnModelProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sagemaker.CfnModelProps.html) \| `any`|User-provided properties to override the default properties for the SageMaker Model. At least `modelProps?.primaryContainer` must be provided to create a model. By default, the pattern will create a role with the minimum required permissions, but the client can provide a custom role with additional capabilities using `modelProps?.executionRoleArn`.| |endpointConfigProps?|[`sagemaker.CfnEndpointConfigProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sagemaker.CfnEndpointConfigProps.html)|Optional user-provided properties to override the default properties for the SageMaker Endpoint Config. | |endpointProps?|[`sagemaker.CfnEndpointProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sagemaker.CfnEndpointProps.html)| Optional user-provided properties to override the default properties for the SageMaker Endpoint Config. | |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this construct should be deployed. When deployed in a VPC, the Lambda function and Sagemaker Endpoint will use ENIs in the VPC to access network resources. An Interface Endpoint will be created in the VPC for Amazon SageMaker Runtime, and Amazon S3 VPC Endpoint. If an existing VPC is provided, the `deployVpc?` property cannot be `true`.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the Construct, so any values for those properties supplied here will be overrriden. If `deployVpc?` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the Construct, so any values for those properties supplied here will be overridden. If `deployVpc?` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| |sagemakerEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the name of the SageMaker endpoint. Default: SAGEMAKER_ENDPOINT_NAME | diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/lib/index.ts index a59c19713..e5233aaa0 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/lib/index.ts @@ -36,7 +36,7 @@ export interface LambdaToSagemakerEndpointProps { */ readonly lambdaFunctionProps?: lambda.FunctionProps; /** - * Existing SageMaker Enpoint object, providing both this and endpointProps will cause an error. + * Existing SageMaker Endpoint object, providing both this and endpointProps will cause an error. * * @default - None */ @@ -105,12 +105,11 @@ export class LambdaToSagemakerEndpoint extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToSagemakerEndpointProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); + defaults.CheckSagemakerProps(props); if (props.deployVpc || props.existingVpc) { - if (props.deployVpc && props.existingVpc) { - throw new Error('More than 1 VPC specified in the properties'); - } // create the VPC this.vpc = defaults.buildVpc(scope, { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/aws-lambda-sagemakerendpoint.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/aws-lambda-sagemakerendpoint.test.ts index b2b2599b2..ac1eaa3b8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/aws-lambda-sagemakerendpoint.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/aws-lambda-sagemakerendpoint.test.ts @@ -240,7 +240,7 @@ test('Pattern deployment with new Lambda function, new Sagemaker endpoint, deplo // --------------------------------------------------------------------------------- // Test for error when existing Lambda function does not have vpc and deployVpc = true // --------------------------------------------------------------------------------- -test('Test for errot when existing Lambda function does not have vpc and deployVpc = true ', () => { +test('Test for error when existing Lambda function does not have vpc and deployVpc = true ', () => { // Initial Setup const stack = new Stack(); @@ -286,9 +286,9 @@ test('Pattern deployment with existing Lambda function (with VPC), new Sagemaker }, }); - // Add S3 VPC Gateway Endpint, required by Sagemaker to access Models artifacts via AWS private network + // Add S3 VPC Gateway Endpoint, required by Sagemaker to access Models artifacts via AWS private network defaults.AddAwsServiceEndpoint(stack, vpc, defaults.ServiceEndpointTypes.S3); - // Add SAGEMAKER_RUNTIME VPC Interface Endpint, required by the lambda function to invoke the SageMaker endpoint + // Add SAGEMAKER_RUNTIME VPC Interface Endpoint, required by the lambda function to invoke the SageMaker endpoint defaults.AddAwsServiceEndpoint(stack, vpc, defaults.ServiceEndpointTypes.SAGEMAKER_RUNTIME); // deploy lambda function @@ -360,7 +360,7 @@ test('Test for error with existingLambdaObj/lambdaFunctionProps=undefined (not s // -------------------------------------------------------------------- // Test for error with (props.deployVpc && props.existingVpc) is true // -------------------------------------------------------------------- -test('Test for error with (props.deployVpc && props.existingVpc) is true', () => { +test('confirm CheckVpcProps is called', () => { // Initial Setup const stack = new Stack(); @@ -372,9 +372,9 @@ test('Test for error with (props.deployVpc && props.existingVpc) is true', () => }, }); - // Add S3 VPC Gateway Endpint, required by Sagemaker to access Models artifacts via AWS private network + // Add S3 VPC Gateway Endpoint, required by Sagemaker to access Models artifacts via AWS private network defaults.AddAwsServiceEndpoint(stack, vpc, defaults.ServiceEndpointTypes.S3); - // Add SAGEMAKER_RUNTIME VPC Interface Endpint, required by the lambda function to invoke the SageMaker endpoint + // Add SAGEMAKER_RUNTIME VPC Interface Endpoint, required by the lambda function to invoke the SageMaker endpoint defaults.AddAwsServiceEndpoint(stack, vpc, defaults.ServiceEndpointTypes.SAGEMAKER_RUNTIME); const constructProps: LambdaToSagemakerEndpointProps = { @@ -384,6 +384,13 @@ test('Test for error with (props.deployVpc && props.existingVpc) is true', () => modelDataUrl: 's3:////model.tar.gz', }, }, + lambdaFunctionProps: { + runtime: lambda.Runtime.PYTHON_3_8, + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + handler: 'index.handler', + timeout: Duration.minutes(5), + memorySize: 128, + }, deployVpc: true, existingVpc: vpc, }; @@ -391,7 +398,7 @@ test('Test for error with (props.deployVpc && props.existingVpc) is true', () => new LambdaToSagemakerEndpoint(stack, 'test-lambda-sagemaker', constructProps); }; // Assertion 1 - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); }); // ---------------------------------------------------------------------------------------------------------- @@ -437,9 +444,9 @@ test('Test getter methods: existing Lambda function (with VPC), new Sagemaker en }, }); - // Add S3 VPC Gateway Endpint, required by Sagemaker to access Models artifacts via AWS private network + // Add S3 VPC Gateway Endpoint, required by Sagemaker to access Models artifacts via AWS private network defaults.AddAwsServiceEndpoint(stack, vpc, defaults.ServiceEndpointTypes.S3); - // Add SAGEMAKER_RUNTIME VPC Interface Endpint, required by the lambda function to invoke the SageMaker endpoint + // Add SAGEMAKER_RUNTIME VPC Interface Endpoint, required by the lambda function to invoke the SageMaker endpoint defaults.AddAwsServiceEndpoint(stack, vpc, defaults.ServiceEndpointTypes.SAGEMAKER_RUNTIME); // deploy lambda function @@ -585,3 +592,61 @@ test('Test lambda function custom environment variable', () => { } }); }); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToSagemakerEndpointProps = { + modelProps: { + primaryContainer: { + image: '.dkr.ecr..amazonaws.com/linear-learner:latest', + modelDataUrl: 's3:////model.tar.gz', + }, + }, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToSagemakerEndpoint(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); + +test('Confirm call to CheckSagemakerProps', () => { + // Initial Setup + const stack = new Stack(); + const deploySagemakerEndpointResponse = defaults.deploySagemakerEndpoint(stack, { + modelProps: { + primaryContainer: { + image: '.dkr.ecr..amazonaws.com/linear-learner:latest', + modelDataUrl: 's3:////model.tar.gz', + }, + }, + }); + + const props: LambdaToSagemakerEndpointProps = { + existingSagemakerEndpointObj: deploySagemakerEndpointResponse.endpoint, + endpointProps: { endpointConfigName: 'test' }, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + }; + const app = () => { + new LambdaToSagemakerEndpoint(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide endpointProps or existingSagemakerEndpointObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.deployFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.deployFunction.expected.json index eb40642ed..30b692a1f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.deployFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.deployFunction.expected.json @@ -336,6 +336,7 @@ "testlambdasagemakerEncryptionKey2AACF9E0": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -363,8 +364,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" @@ -372,6 +372,9 @@ "testlambdasagemakerSagemakerEndpointConfig6BABA334": { "Type": "AWS::SageMaker::EndpointConfig", "Properties": { + "KmsKeyId": { + "Ref": "testlambdasagemakerEncryptionKey2AACF9E0" + }, "ProductionVariants": [ { "InitialInstanceCount": 1, @@ -385,10 +388,7 @@ }, "VariantName": "AllTraffic" } - ], - "KmsKeyId": { - "Ref": "testlambdasagemakerEncryptionKey2AACF9E0" - } + ] }, "DependsOn": [ "testlambdasagemakerSagemakerModelEC3E4E39" @@ -513,12 +513,6 @@ }, "S3Key": "d894a15aa0242919d44274cbb8ddd33f39cce242789e85e67e642da0a2926e15.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasagemakerLambdaFunctionServiceRole4BA038CB", - "Arn" - ] - }, "Environment": { "Variables": { "SAGEMAKER_ENDPOINT_NAME": { @@ -531,6 +525,12 @@ }, "Handler": "index.handler", "MemorySize": 128, + "Role": { + "Fn::GetAtt": [ + "testlambdasagemakerLambdaFunctionServiceRole4BA038CB", + "Arn" + ] + }, "Runtime": "python3.8", "Timeout": 300, "TracingConfig": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.existingFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.existingFunction.expected.json index e0e998e75..f47a7676d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.existingFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.existingFunction.expected.json @@ -106,12 +106,6 @@ }, "S3Key": "d894a15aa0242919d44274cbb8ddd33f39cce242789e85e67e642da0a2926e15.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "SAGEMAKER_ENDPOINT_NAME": { @@ -124,6 +118,12 @@ }, "Handler": "index.handler", "MemorySize": 128, + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "python3.8", "Timeout": 300, "TracingConfig": { @@ -421,6 +421,7 @@ "testlambdasagemakerEncryptionKey2AACF9E0": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -448,8 +449,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" @@ -457,6 +457,9 @@ "testlambdasagemakerSagemakerEndpointConfig6BABA334": { "Type": "AWS::SageMaker::EndpointConfig", "Properties": { + "KmsKeyId": { + "Ref": "testlambdasagemakerEncryptionKey2AACF9E0" + }, "ProductionVariants": [ { "InitialInstanceCount": 1, @@ -470,10 +473,7 @@ }, "VariantName": "AllTraffic" } - ], - "KmsKeyId": { - "Ref": "testlambdasagemakerEncryptionKey2AACF9E0" - } + ] }, "DependsOn": [ "testlambdasagemakerSagemakerModelEC3E4E39" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.existingSageMakerEndpoint.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.existingSageMakerEndpoint.expected.json index 78d3e1f8f..4625b41a5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.existingSageMakerEndpoint.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sagemakerendpoint/test/integ.existingSageMakerEndpoint.expected.json @@ -336,6 +336,7 @@ "EncryptionKey1B843E66": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -363,8 +364,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" @@ -372,6 +372,9 @@ "SagemakerEndpointConfig": { "Type": "AWS::SageMaker::EndpointConfig", "Properties": { + "KmsKeyId": { + "Ref": "EncryptionKey1B843E66" + }, "ProductionVariants": [ { "InitialInstanceCount": 1, @@ -385,10 +388,7 @@ }, "VariantName": "AllTraffic" } - ], - "KmsKeyId": { - "Ref": "EncryptionKey1B843E66" - } + ] }, "DependsOn": [ "SagemakerModel" @@ -513,12 +513,6 @@ }, "S3Key": "d894a15aa0242919d44274cbb8ddd33f39cce242789e85e67e642da0a2926e15.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasagemakerLambdaFunctionServiceRole4BA038CB", - "Arn" - ] - }, "Environment": { "Variables": { "SAGEMAKER_ENDPOINT_NAME": { @@ -531,6 +525,12 @@ }, "Handler": "index.handler", "MemorySize": 128, + "Role": { + "Fn::GetAtt": [ + "testlambdasagemakerLambdaFunctionServiceRole4BA038CB", + "Arn" + ] + }, "Runtime": "python3.8", "Timeout": 300, "TracingConfig": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/README.md index e3e184713..9ed75c85b 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/README.md @@ -94,7 +94,7 @@ new LambdaToSecretsmanager(this, "test-lambda-secretsmanager-stack", new LambdaT |grantWriteAccess?|`string`|Optional Access granted to the Lambda function for the secret. 'Read' or 'ReadWrite". Default is "Read" |secretEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the ARN of the secret. Default: SECRET_ARN. | |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for AWS Secrets Manager. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| ## Pattern Properties diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/lib/index.ts index 79060aed8..966f04f1b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/lib/index.ts @@ -70,7 +70,7 @@ export interface LambdaToSecretsmanagerProps { * Optional secret permissions to grant to the Lambda function. * One of the following may be specified: "Read" or "ReadWrite". * - * @default - Read only acess is given to the Lambda function if no value is specified. + * @default - Read only access is given to the Lambda function if no value is specified. */ readonly grantWriteAccess?: string; } @@ -92,12 +92,11 @@ export class LambdaToSecretsmanager extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToSecretsmanagerProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); + defaults.CheckSecretsManagerProps(props); if (props.deployVpc || props.existingVpc) { - if (props.deployVpc && props.existingVpc) { - throw new Error("More than 1 VPC specified in the properties"); - } this.vpc = defaults.buildVpc(scope, { defaultVpcProps: defaults.DefaultIsolatedVpcProps(), diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunction.expected.json index abd995aa7..856fc754b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunction.expected.json @@ -109,12 +109,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasecretsmanagerLambdaFunctionServiceRole92CE007F", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -124,6 +118,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasecretsmanagerLambdaFunctionServiceRole92CE007F", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunctionWithExistingVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunctionWithExistingVpc.expected.json index 8d0505d94..00399cbea 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunctionWithExistingVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunctionWithExistingVpc.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,17 +657,31 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSECRETSMANAGERF52907C2": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "deployFunctionWithExistingVpcSECRETSMANAGERsecuritygroupB20BA3EB", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -685,18 +694,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "deployFunctionWithExistingVpcSECRETSMANAGERsecuritygroupB20BA3EB", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -708,7 +705,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testlambdasecretsmanagerstackLambdaFunctionServiceRole4FE7A9C6": { @@ -860,12 +860,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasecretsmanagerstackLambdaFunctionServiceRole4FE7A9C6", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -875,6 +869,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasecretsmanagerstackLambdaFunctionServiceRole4FE7A9C6", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunctionWithVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunctionWithVpc.expected.json index b613ac9e0..14093b327 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunctionWithVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.deployFunctionWithVpc.expected.json @@ -150,12 +150,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasecretsmanagerLambdaFunctionServiceRole92CE007F", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -165,6 +159,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasecretsmanagerLambdaFunctionServiceRole92CE007F", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -253,9 +253,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -272,21 +269,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -303,9 +303,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -322,21 +319,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -353,9 +353,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -372,21 +369,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -418,7 +418,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] } @@ -470,7 +470,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] }, @@ -490,11 +490,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -505,17 +500,31 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSECRETSMANAGERF52907C2": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "deployFunctionWithVpcSECRETSMANAGERsecuritygroup140A8C59", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -528,18 +537,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "deployFunctionWithVpcSECRETSMANAGERsecuritygroup140A8C59", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -551,7 +548,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "deployFunctionWithVpcSECRETSMANAGERsecuritygroup140A8C59": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.existingFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.existingFunction.expected.json index 377c92c56..b8a7d80e2 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.existingFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/integ.existingFunction.expected.json @@ -109,12 +109,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -124,6 +118,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/lambda-secretsmanager.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/lambda-secretsmanager.test.ts index e693e5891..ec7ff2c75 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/lambda-secretsmanager.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-secretsmanager/test/lambda-secretsmanager.test.ts @@ -14,15 +14,12 @@ // Imports import { RemovalPolicy, Stack } from "aws-cdk-lib"; import * as lambda from "aws-cdk-lib/aws-lambda"; -import { Secret } from 'aws-cdk-lib/aws-secretsmanager'; +import * as secrets from 'aws-cdk-lib/aws-secretsmanager'; import * as ec2 from "aws-cdk-lib/aws-ec2"; -import { LambdaToSecretsmanager } from '../lib'; +import { LambdaToSecretsmanager, LambdaToSecretsmanagerProps } from '../lib'; import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from "@aws-solutions-constructs/core"; -// -------------------------------------------------------------- -// Test the getter methods -// -------------------------------------------------------------- test('Test the properties', () => { // Stack const stack = new Stack(); @@ -43,14 +40,11 @@ test('Test the properties', () => { expect(secret).toBeDefined(); }); -// -------------------------------------------------------------- -// Test deployment w/ existing secret -// -------------------------------------------------------------- test('Test deployment w/ existing secret', () => { // Stack const stack = new Stack(); // Helper declaration - const existingSecret = new Secret(stack, 'secret', {}); + const existingSecret = new secrets.Secret(stack, 'secret', {}); const pattern = new LambdaToSecretsmanager(stack, 'lambda-to-secretsmanager-stack', { lambdaFunctionProps: { runtime: lambda.Runtime.NODEJS_16_X, @@ -68,9 +62,6 @@ test('Test deployment w/ existing secret', () => { expect(pattern.secret).toBe(existingSecret); }); -// -------------------------------------------------------------- -// Test deployment w/ existing function -// -------------------------------------------------------------- test('Test deployment w/ existing function', () => { // Stack const stack = new Stack(); @@ -95,9 +86,6 @@ test('Test deployment w/ existing function', () => { expect(pattern.lambdaFunction).toBe(existingFunction); }); -// -------------------------------------------------------------- -// Test minimal deployment with write access to Secret -// -------------------------------------------------------------- test('Test minimal deployment write access to Secret', () => { // Stack const stack = new Stack(); @@ -119,9 +107,6 @@ test('Test minimal deployment write access to Secret', () => { }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC without vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC without vpcProps", () => { // Stack const stack = new Stack(); @@ -171,9 +156,6 @@ test("Test minimal deployment that deploys a VPC without vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC w/vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC w/vpcProps", () => { // Stack const stack = new Stack(); @@ -229,9 +211,6 @@ test("Test minimal deployment that deploys a VPC w/vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC", () => { // Stack const stack = new Stack(); @@ -276,13 +255,7 @@ test("Test minimal deployment with an existing VPC", () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC and existing Lambda function not in a VPC -// -// buildLambdaFunction should throw an error if the Lambda function is not -// attached to a VPC -// -------------------------------------------------------------- -test("Test minimal deployment with an existing VPC and existing Lambda function not in a VPC", () => { +test("Check error when existing lambda function is not in VPC and construct is in VPC", () => { // Stack const stack = new Stack(); @@ -296,7 +269,8 @@ test("Test minimal deployment with an existing VPC and existing Lambda function // Helper declaration const app = () => { - // Helper declaration + // buildLambdaFunction should throw an error if the Lambda function is not + // attached to a VPC new LambdaToSecretsmanager(stack, "lambda-to-secretsmanager-stack", { existingLambdaObj: testLambdaFunction, existingVpc: testVpc, @@ -309,10 +283,7 @@ test("Test minimal deployment with an existing VPC and existing Lambda function }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { +test("Confirm CheckVpcProps is called", () => { // Stack const stack = new Stack(); @@ -332,12 +303,9 @@ test("Test bad call with existingVpc and deployVpc", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); }); -// -------------------------------------------------------------- -// Test lambda function custom environment variable -// -------------------------------------------------------------- test('Test lambda function custom environment variable', () => { // Stack const stack = new Stack(); @@ -372,9 +340,6 @@ test('Test lambda function custom environment variable', () => { }); }); -// -------------------------------------------------------------- -// Test overriding secretProps to pass a customer provided CMK -// -------------------------------------------------------------- test('Test overriding secretProps to pass a customer provided CMK', () => { // Stack const stack = new Stack(); @@ -430,3 +395,49 @@ test('Test overriding secretProps to pass a customer provided CMK', () => { EnableKeyRotation: true }); }); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToSecretsmanagerProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToSecretsmanager(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); + +test('Confirm call to CheckSecretsManagerProps', () => { + // Initial Setup + const stack = new Stack(); + + const props: LambdaToSecretsmanagerProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + secretProps: { + secretName: 'test' + }, + existingSecretObj: new secrets.Secret(stack, 'test', {}), + }; + const app = () => { + new LambdaToSecretsmanager(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide secretProps or existingSecretObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/README.md index d7034ad76..44f691972 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/README.md @@ -86,7 +86,7 @@ new LambdaToSns(this, "test-lambda-sns-stack", new LambdaToSnsProps.Builder() |existingTopicObj?|[`sns.Topic`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html)|Existing instance of SNS Topic object, providing both this and `topicProps` will cause an error.| |topicProps?|[`sns.TopicProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sns.TopicProps.html)|Optional user provided properties to override the default properties for the SNS topic.| |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for Amazon SNS. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| |topicArnEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the arn of the topic. Default: SNS_TOPIC_ARN | |topicNameEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the name of the topic. Default: SNS_TOPIC_NAME | diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/lib/index.ts index eb3072a10..7996f9638 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/lib/index.ts @@ -113,7 +113,9 @@ export class LambdaToSns extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToSnsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckSnsProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); if (props.deployVpc || props.existingVpc) { this.vpc = defaults.buildVpc(scope, { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.deployFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.deployFunction.expected.json index 5b7927327..a9056a16a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.deployFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.deployFunction.expected.json @@ -106,12 +106,6 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasnsLambdaFunctionServiceRole9C412F74", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -127,6 +121,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasnsLambdaFunctionServiceRole9C412F74", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.deployFunctionWithVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.deployFunctionWithVpc.expected.json index c9e10345b..fac38e6c5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.deployFunctionWithVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.deployFunctionWithVpc.expected.json @@ -147,12 +147,6 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasnsLambdaFunctionServiceRole9C412F74", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -168,6 +162,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasnsLambdaFunctionServiceRole9C412F74", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -347,9 +347,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -366,21 +363,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -397,9 +397,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -416,21 +413,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -447,9 +447,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -466,21 +463,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -512,7 +512,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] } @@ -564,7 +564,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] }, @@ -584,11 +584,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -599,17 +594,31 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSNS5B664381": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "deployFunctionWithVpcSNSsecuritygroup5E54C413", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -622,18 +631,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "deployFunctionWithVpcSNSsecuritygroup5E54C413", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -645,7 +642,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "deployFunctionWithVpcSNSsecuritygroup5E54C413": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.existingFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.existingFunction.expected.json index 26ac8d886..a543e3041 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.existingFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/integ.existingFunction.expected.json @@ -106,12 +106,6 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -127,6 +121,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/lambda-sns.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/lambda-sns.test.ts index 9cb585c4c..f7ac58de7 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/lambda-sns.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/lambda-sns.test.ts @@ -20,9 +20,6 @@ import * as ec2 from "aws-cdk-lib/aws-ec2"; import { LambdaToSns, LambdaToSnsProps } from '../lib'; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Test deployment with new Lambda function -// -------------------------------------------------------------- test('Test deployment with new Lambda function', () => { // Stack const stack = new Stack(); @@ -80,9 +77,6 @@ test('Test deployment with new Lambda function', () => { }); }); -// -------------------------------------------------------------- -// Test deployment with existing existingTopicObj -// -------------------------------------------------------------- test('Test deployment with existing existingTopicObj', () => { // Stack const stack = new Stack(); @@ -110,9 +104,6 @@ test('Test deployment with existing existingTopicObj', () => { }); }); -// -------------------------------------------------------------- -// Test deployment with imported encryption key -// -------------------------------------------------------------- test('override topicProps', () => { const stack = new Stack(); @@ -135,9 +126,6 @@ test('override topicProps', () => { }); }); -// -------------------------------------------------------------- -// Test the getter methods -// -------------------------------------------------------------- test('Test the properties', () => { // Stack const stack = new Stack(); @@ -157,9 +145,6 @@ test('Test the properties', () => { expect(topic).toBeDefined(); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC without vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC without vpcProps", () => { // Stack const stack = new Stack(); @@ -208,9 +193,6 @@ test("Test minimal deployment that deploys a VPC without vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC w/vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC w/vpcProps", () => { // Stack const stack = new Stack(); @@ -265,9 +247,6 @@ test("Test minimal deployment that deploys a VPC w/vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC", () => { // Stack const stack = new Stack(); @@ -311,12 +290,6 @@ test("Test minimal deployment with an existing VPC", () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC and existing Lambda function not in a VPC -// -// buildLambdaFunction should throw an error if the Lambda function is not -// attached to a VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC and existing Lambda function not in a VPC", () => { // Stack const stack = new Stack(); @@ -331,7 +304,8 @@ test("Test minimal deployment with an existing VPC and existing Lambda function // Helper declaration const app = () => { - // Helper declaration + // buildLambdaFunction should throw an error if the Lambda function is not + // attached to a VPC new LambdaToSns(stack, "lambda-to-sns-stack", { existingLambdaObj: testLambdaFunction, existingVpc: testVpc, @@ -343,34 +317,6 @@ test("Test minimal deployment with an existing VPC and existing Lambda function }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { - // Stack - const stack = new Stack(); - - const testVpc = new ec2.Vpc(stack, "test-vpc", {}); - - const app = () => { - // Helper declaration - new LambdaToSns(stack, "lambda-to-sns-stack", { - lambdaFunctionProps: { - runtime: lambda.Runtime.NODEJS_16_X, - handler: "index.handler", - code: lambda.Code.fromAsset(`${__dirname}/lambda`), - }, - existingVpc: testVpc, - deployVpc: true, - }); - }; - // Assertion - expect(app).toThrowError(); -}); - -// -------------------------------------------------------------- -// Test lambda function custom environment variable -// -------------------------------------------------------------- test('Test lambda function custom environment variable', () => { // Stack const stack = new Stack(); @@ -464,7 +410,7 @@ test('Topic is encrypted with imported CMK when set on topicProps.masterKey prop }); }); -test('Topic is encrypted with provided encrytionKeyProps', () => { +test('Topic is encrypted with provided encryptionKeyProps', () => { const stack = new Stack(); new LambdaToSns(stack, 'test-construct', { @@ -567,7 +513,7 @@ test('Topic is encrypted with customer managed KMS Key when enable encryption fl }); }); -test('Error is thrown when conflicting VPC information is provided', () => { +test('Confirm CheckVpcProps is called', () => { const stack = new Stack(); const app = () => { @@ -577,5 +523,56 @@ test('Error is thrown when conflicting VPC information is provided', () => { }); }; - expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.'); -}); \ No newline at end of file + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Test that CheckSnsProps is getting called', () => { + const stack = new Stack(); + + const topic = new sns.Topic(stack, 'MyTopic', { + topicName: "custom-topic" + }); + + const props: LambdaToSnsProps = { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, + existingTopicObj: topic, + topicProps: { + topicName: 'topic-name' + }, + }; + + const app = () => { + new LambdaToSns(stack, 'test-lambda-dynamodb-stack', props); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide topicProps or existingTopicObj, but not both.\n/); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToSnsProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToSns(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/README.md index 5ce3c4efa..4a8ca705b 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/README.md @@ -111,7 +111,7 @@ new LambdaToSqsToLambda(this, "LambdaToSqsToLambdaPattern", new LambdaToSqsToLam |queueEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the URL of the queue. Default: SQS_QUEUE_URL | |sqsEventSourceProps?| [`SqsEventSourceProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_event_sources.SqsEventSourceProps.html)|Optional user provided properties for the queue event source.| |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for Amazon SQS. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| ## Pattern Properties diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/lib/index.ts index 13eda1f42..b14523652 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/lib/index.ts @@ -20,7 +20,6 @@ import { SqsToLambda } from '@aws-solutions-constructs/aws-sqs-lambda'; import { Construct } from 'constructs'; import { SqsEventSourceProps } from 'aws-cdk-lib/aws-lambda-event-sources'; import * as ec2 from "aws-cdk-lib/aws-ec2"; -import * as defaults from '@aws-solutions-constructs/core'; /** * @summary The properties for the LambdaToSqsToLambda class. @@ -131,7 +130,6 @@ export class LambdaToSqsToLambda extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToSqsToLambdaProps) { super(scope, id); - defaults.CheckProps(props); // Setup the aws-lambda-sqs pattern const lambdaToSqs = new LambdaToSqs(this, 'lambda-to-sqs', { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.defaultDeployment.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.defaultDeployment.expected.json index ebdcef715..d1e2e4d6e 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.defaultDeployment.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.defaultDeployment.expected.json @@ -113,12 +113,6 @@ }, "S3Key": "075b2d402078d97c329028d1af17df69ef86062dc7ace374b10a10022db6fb8d.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqslambdalambdatosqsLambdaFunctionServiceRoleAE4A8DCD", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -128,6 +122,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqslambdalambdatosqsLambdaFunctionServiceRoleAE4A8DCD", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -437,18 +437,18 @@ }, "S3Key": "d685d4fad1e8a913557eb007ae16e135281d3f192a6b557c471e160e3cc557a6.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqslambdasqstolambdaLambdaFunctionServiceRole785979D2", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqslambdasqstolambdaLambdaFunctionServiceRole785979D2", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -480,14 +480,14 @@ "testlambdasqslambdasqstolambdaLambdaFunctionSqsEventSourcedefaultDeploymenttestlambdasqslambdalambdatosqsqueue5E928C6A3AD18AD6": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testlambdasqslambdasqstolambdaLambdaFunction81308327" - }, "EventSourceArn": { "Fn::GetAtt": [ "testlambdasqslambdalambdatosqsqueueF2ED40D2", "Arn" ] + }, + "FunctionName": { + "Ref": "testlambdasqslambdasqstolambdaLambdaFunction81308327" } } } diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.deployProducerFunctionWithVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.deployProducerFunctionWithVpc.expected.json index 40b1ad280..0118c94c6 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.deployProducerFunctionWithVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.deployProducerFunctionWithVpc.expected.json @@ -154,12 +154,6 @@ }, "S3Key": "075b2d402078d97c329028d1af17df69ef86062dc7ace374b10a10022db6fb8d.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqslambdatosqsLambdaFunctionServiceRole9A15D8F5", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -169,6 +163,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqslambdatosqsLambdaFunctionServiceRole9A15D8F5", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -406,9 +406,6 @@ "testlambdasqsVpcisolatedSubnet1Subnet75F315F8": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "testlambdasqsVpc85322AF3" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -425,21 +422,24 @@ "Key": "Name", "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "testlambdasqsVpc85322AF3" + } } }, "testlambdasqsVpcisolatedSubnet1RouteTable9070A207": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "testlambdasqsVpc85322AF3" - }, "Tags": [ { "Key": "Name", "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "testlambdasqsVpc85322AF3" + } } }, "testlambdasqsVpcisolatedSubnet1RouteTableAssociation270A37E8": { @@ -456,9 +456,6 @@ "testlambdasqsVpcisolatedSubnet2Subnet320D7431": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "testlambdasqsVpc85322AF3" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -475,21 +472,24 @@ "Key": "Name", "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "testlambdasqsVpc85322AF3" + } } }, "testlambdasqsVpcisolatedSubnet2RouteTable1C5B9E86": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "testlambdasqsVpc85322AF3" - }, "Tags": [ { "Key": "Name", "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "testlambdasqsVpc85322AF3" + } } }, "testlambdasqsVpcisolatedSubnet2RouteTableAssociation723A8A06": { @@ -506,9 +506,6 @@ "testlambdasqsVpcisolatedSubnet3Subnet34633573": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "testlambdasqsVpc85322AF3" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -525,21 +522,24 @@ "Key": "Name", "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "testlambdasqsVpc85322AF3" + } } }, "testlambdasqsVpcisolatedSubnet3RouteTable7AB1A8FF": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "testlambdasqsVpc85322AF3" - }, "Tags": [ { "Key": "Name", "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "testlambdasqsVpc85322AF3" + } } }, "testlambdasqsVpcisolatedSubnet3RouteTableAssociation41766676": { @@ -571,7 +571,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc" + "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc/FlowLog" } ] } @@ -623,7 +623,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc" + "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc/FlowLog" } ] }, @@ -643,11 +643,6 @@ "testlambdasqsVpcFlowLogEECF2763": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "testlambdasqsVpc85322AF3" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "testlambdasqsVpcFlowLogIAMRole79FE4957", @@ -658,17 +653,31 @@ "LogGroupName": { "Ref": "testlambdasqsVpcFlowLogLogGroup5E27ADE6" }, + "ResourceId": { + "Ref": "testlambdasqsVpc85322AF3" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc" + "Value": "deployProducerFunctionWithVpc/test-lambda-sqs/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "testlambdasqsVpcSQS13B88BE1": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "testlambdasqstestlambdasqsSQSsecuritygroupBDBA458D", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -681,18 +690,6 @@ ] ] }, - "VpcId": { - "Ref": "testlambdasqsVpc85322AF3" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "testlambdasqstestlambdasqsSQSsecuritygroupBDBA458D", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "testlambdasqsVpcisolatedSubnet1Subnet75F315F8" @@ -704,7 +701,10 @@ "Ref": "testlambdasqsVpcisolatedSubnet3Subnet34633573" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "testlambdasqsVpc85322AF3" + } } }, "testlambdasqstestlambdasqsSQSsecuritygroupBDBA458D": { @@ -879,18 +879,18 @@ }, "S3Key": "d685d4fad1e8a913557eb007ae16e135281d3f192a6b557c471e160e3cc557a6.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqssqstolambdaLambdaFunctionServiceRoleB914400A", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqssqstolambdaLambdaFunctionServiceRoleB914400A", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -922,14 +922,14 @@ "testlambdasqssqstolambdaLambdaFunctionSqsEventSourcedeployProducerFunctionWithVpctestlambdasqslambdatosqsqueueA1382C56CEF2BFAB": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testlambdasqssqstolambdaLambdaFunctionDE6481E6" - }, "EventSourceArn": { "Fn::GetAtt": [ "testlambdasqslambdatosqsqueue5A401298", "Arn" ] + }, + "FunctionName": { + "Ref": "testlambdasqssqstolambdaLambdaFunctionDE6481E6" } } } diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingConsumerFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingConsumerFunction.expected.json index ce8eeeb53..f3c39b316 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingConsumerFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingConsumerFunction.expected.json @@ -115,18 +115,18 @@ }, "S3Key": "d685d4fad1e8a913557eb007ae16e135281d3f192a6b557c471e160e3cc557a6.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -158,14 +158,14 @@ "LambdaFunctionSqsEventSourceexistingConsumerFunctiontestlambdasqslambdalambdatosqsqueue06632F2BBBBAB968": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "LambdaFunctionBF21E41F" - }, "EventSourceArn": { "Fn::GetAtt": [ "testlambdasqslambdalambdatosqsqueueF2ED40D2", "Arn" ] + }, + "FunctionName": { + "Ref": "LambdaFunctionBF21E41F" } } }, @@ -281,12 +281,6 @@ }, "S3Key": "075b2d402078d97c329028d1af17df69ef86062dc7ace374b10a10022db6fb8d.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqslambdalambdatosqsLambdaFunctionServiceRoleAE4A8DCD", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -296,6 +290,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqslambdalambdatosqsLambdaFunctionServiceRoleAE4A8DCD", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingProducerFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingProducerFunction.expected.json index 8c957b531..db615ee83 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingProducerFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingProducerFunction.expected.json @@ -113,12 +113,6 @@ }, "S3Key": "075b2d402078d97c329028d1af17df69ef86062dc7ace374b10a10022db6fb8d.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -128,6 +122,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -437,18 +437,18 @@ }, "S3Key": "d685d4fad1e8a913557eb007ae16e135281d3f192a6b557c471e160e3cc557a6.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqslambdasqstolambdaLambdaFunctionServiceRole785979D2", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqslambdasqstolambdaLambdaFunctionServiceRole785979D2", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -480,14 +480,14 @@ "testlambdasqslambdasqstolambdaLambdaFunctionSqsEventSourceexistingProducerFunctiontestlambdasqslambdalambdatosqsqueue9043AC9D03EA33DA": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testlambdasqslambdasqstolambdaLambdaFunction81308327" - }, "EventSourceArn": { "Fn::GetAtt": [ "testlambdasqslambdalambdatosqsqueueF2ED40D2", "Arn" ] + }, + "FunctionName": { + "Ref": "testlambdasqslambdasqstolambdaLambdaFunction81308327" } } } diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingQueue.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingQueue.expected.json index f8cfe92f8..0adc3d1f2 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingQueue.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/integ.existingQueue.expected.json @@ -192,12 +192,6 @@ }, "S3Key": "075b2d402078d97c329028d1af17df69ef86062dc7ace374b10a10022db6fb8d.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqslambdalambdatosqsLambdaFunctionServiceRoleAE4A8DCD", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -207,6 +201,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqslambdalambdatosqsLambdaFunctionServiceRoleAE4A8DCD", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -349,18 +349,18 @@ }, "S3Key": "d685d4fad1e8a913557eb007ae16e135281d3f192a6b557c471e160e3cc557a6.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqslambdasqstolambdaLambdaFunctionServiceRole785979D2", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqslambdasqstolambdaLambdaFunctionServiceRole785979D2", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -392,14 +392,14 @@ "testlambdasqslambdasqstolambdaLambdaFunctionSqsEventSourceexistingQueueexistingsqsqueue05DEA3674B910AAB": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testlambdasqslambdasqstolambdaLambdaFunction81308327" - }, "EventSourceArn": { "Fn::GetAtt": [ "existingsqsqueue6AE880F4", "Arn" ] + }, + "FunctionName": { + "Ref": "testlambdasqslambdasqstolambdaLambdaFunction81308327" } } } diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/lambda-sqs-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/lambda-sqs-lambda.test.ts index b95479002..2c049c915 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/lambda-sqs-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs-lambda/test/lambda-sqs-lambda.test.ts @@ -14,14 +14,12 @@ // Imports import { Stack } from "aws-cdk-lib"; import * as lambda from "aws-cdk-lib/aws-lambda"; +import * as sqs from "aws-cdk-lib/aws-sqs"; import * as ec2 from "aws-cdk-lib/aws-ec2"; import * as defaults from '@aws-solutions-constructs/core'; import { LambdaToSqsToLambda, LambdaToSqsToLambdaProps } from '../lib'; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Test minimal deployment -// -------------------------------------------------------------- test('Test minimal deployment', () => { // Stack const stack = new Stack(); @@ -117,9 +115,6 @@ test('Test minimal deployment', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ existing producer function -// -------------------------------------------------------------- test('Test deployment w/ existing producer function', () => { // Stack const stack = new Stack(); @@ -155,9 +150,6 @@ test('Test deployment w/ existing producer function', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ existing consumer function -// -------------------------------------------------------------- test('Test deployment w/ existing consumer function', () => { // Stack const stack = new Stack(); @@ -193,9 +185,6 @@ test('Test deployment w/ existing consumer function', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ existing queue -// -------------------------------------------------------------- test('Test deployment w/ existing queue', () => { // Stack const stack = new Stack(); @@ -230,9 +219,6 @@ test('Test deployment w/ existing queue', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ DLQ explicitly disabled -// -------------------------------------------------------------- test('Test deployment w/ DLQ explicitly disabled', () => { // Stack const stack = new Stack(); @@ -261,9 +247,6 @@ test('Test deployment w/ DLQ explicitly disabled', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ DLQ explicitly enabled and w/ MRC override -// -------------------------------------------------------------- test('Test deployment w/ DLQ explicitly enabled and w/ MRC override', () => { // Stack const stack = new Stack(); @@ -299,9 +282,6 @@ test('Test deployment w/ DLQ explicitly enabled and w/ MRC override', () => { }); }); -// -------------------------------------------------------------- -// Test overrides for producer and consumer functions -// -------------------------------------------------------------- test('Test overrides for producer and consumer functions', () => { // Stack const stack = new Stack(); @@ -333,9 +313,6 @@ test('Test overrides for producer and consumer functions', () => { }); }); -// -------------------------------------------------------------- -// Test the public pattern props -// -------------------------------------------------------------- test('Test the public pattern props', () => { // Stack const stack = new Stack(); @@ -365,9 +342,6 @@ test('Test the public pattern props', () => { expect(pattern.consumerLambdaFunction).toBeDefined(); }); -// -------------------------------------------------------------- -// Test lambda function custom environment variable -// -------------------------------------------------------------- test('Test lambda function custom environment variable', () => { // Stack const stack = new Stack(); @@ -405,9 +379,6 @@ test('Test lambda function custom environment variable', () => { }); }); -// -------------------------------------------------------------- -// Pattern deployment w/ batch size -// -------------------------------------------------------------- test('Pattern deployment w/ batch size', () => { const stack = new Stack(); const props: LambdaToSqsToLambdaProps = { @@ -435,9 +406,6 @@ test('Pattern deployment w/ batch size', () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC without vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC without vpcProps", () => { // Stack const stack = new Stack(); @@ -493,9 +461,6 @@ test("Test minimal deployment that deploys a VPC without vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC w/vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC w/vpcProps", () => { // Stack const stack = new Stack(); @@ -557,9 +522,6 @@ test("Test minimal deployment that deploys a VPC w/vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC", () => { // Stack const stack = new Stack(); @@ -610,9 +572,6 @@ test("Test minimal deployment with an existing VPC", () => { }); }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- test("Test bad call with existingVpc and deployVpc", () => { // Stack const stack = new Stack(); @@ -640,4 +599,58 @@ test("Test bad call with existingVpc and deployVpc", () => { }; // Assertion expect(app).toThrowError(); -}); \ No newline at end of file +}); + +test('Confirm CheckSqsProps is being called', () => { + // NOTE: CheckSqsProps is called from both lambda-sqs and sqs-lambda internally + // Stack + const stack = new Stack(); + // Helper declaration + const props: LambdaToSqsToLambdaProps = { + producerLambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`) + }, + consumerLambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`) + }, + queueProps: {}, + existingQueueObj: new sqs.Queue(stack, 'test', {}) + }; + + const app = () => { + new LambdaToSqsToLambda(stack, 'test-eventbridge-sqs', props); + }; + expect(app).toThrowError("Error - Either provide queueProps or existingQueueObj, but not both.\n"); +}); + +test('Confirm CheckLambdaProps is being called', () => { + const stack = new Stack(); + const existingLambdaObj = new lambda.Function(stack, 'ExistingLambda', { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToSqsToLambdaProps = { + existingProducerLambdaObj: existingLambdaObj, + producerLambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + consumerLambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + }; + + const app = () => { + new LambdaToSqsToLambda(stack, 'test-lambda-sqs-lambda', props); + }; + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/README.md index 502a8123d..ce9e3dbbf 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/README.md @@ -90,7 +90,7 @@ new LambdaToSqs(this, "test-lambda-sqs-stack", new LambdaToSqsProps.Builder() |deadLetterQueueProps?|[`sqs.QueueProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.QueueProps.html)|Optional user-provided props to override the default props for the dead letter queue. Only used if the `deployDeadLetterQueue` property is set to true.| |maxReceiveCount?|`number`|The number of times a message can be unsuccessfully dequeued before being moved to the dead letter queue. Defaults to `15`.| |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for Amazon SQS. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| |queueEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the URL of the queue. Default: SQS_QUEUE_URL | |enableEncryptionWithCustomerManagedKey?|`boolean`|If no key is provided, this flag determines whether the queue is encrypted with a new CMK or an AWS managed key. This flag is ignored if any of the following are defined: queueProps.encryptionMasterKey, encryptionKey or encryptionKeyProps.| diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/lib/index.ts index cfa860bb0..5fa88501e 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/lib/index.ts @@ -131,7 +131,9 @@ export class LambdaToSqs extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToSqsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckSqsProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); if (props.deployVpc || props.existingVpc) { this.vpc = defaults.buildVpc(scope, { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.deployFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.deployFunction.expected.json index 966e2d9e8..511e39032 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.deployFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.deployFunction.expected.json @@ -113,12 +113,6 @@ }, "S3Key": "42887c62b1163d790cdb42902037c9f639feb35681616a16826e400c8d1a4435.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqsLambdaFunctionServiceRoleC0430CA8", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -128,6 +122,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqsLambdaFunctionServiceRoleC0430CA8", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.deployFunctionWithVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.deployFunctionWithVpc.expected.json index d54428b69..3aea6b351 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.deployFunctionWithVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.deployFunctionWithVpc.expected.json @@ -154,12 +154,6 @@ }, "S3Key": "42887c62b1163d790cdb42902037c9f639feb35681616a16826e400c8d1a4435.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdasqsLambdaFunctionServiceRoleC0430CA8", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -169,6 +163,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdasqsLambdaFunctionServiceRoleC0430CA8", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -406,9 +406,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -425,21 +422,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -456,9 +456,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -475,21 +472,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -506,9 +506,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -525,21 +522,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -571,7 +571,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] } @@ -623,7 +623,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] }, @@ -643,11 +643,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -658,17 +653,31 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSQSDF166A88": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "deployFunctionWithVpcSQSsecuritygroup2E4E2685", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -681,18 +690,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "deployFunctionWithVpcSQSsecuritygroup2E4E2685", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -704,7 +701,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "deployFunctionWithVpcSQSsecuritygroup2E4E2685": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.existingFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.existingFunction.expected.json index 9944b622e..c566207bc 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.existingFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.existingFunction.expected.json @@ -113,12 +113,6 @@ }, "S3Key": "42887c62b1163d790cdb42902037c9f639feb35681616a16826e400c8d1a4435.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -128,6 +122,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/lambda-sqs.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/lambda-sqs.test.ts index 43e48f02e..2942a5d6b 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/lambda-sqs.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/lambda-sqs.test.ts @@ -12,16 +12,14 @@ */ // Imports -import { Stack } from "aws-cdk-lib"; +import { Stack, RemovalPolicy } from "aws-cdk-lib"; +import * as sqs from 'aws-cdk-lib/aws-sqs'; import * as kms from 'aws-cdk-lib/aws-kms'; import * as lambda from "aws-cdk-lib/aws-lambda"; import * as ec2 from "aws-cdk-lib/aws-ec2"; -import { LambdaToSqs } from '../lib'; +import { LambdaToSqs, LambdaToSqsProps } from '../lib'; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Test the getter methods -// -------------------------------------------------------------- test('Test the properties', () => { // Stack const stack = new Stack(); @@ -44,9 +42,6 @@ test('Test the properties', () => { expect(dlq).toBeDefined(); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC without vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC without vpcProps", () => { // Stack const stack = new Stack(); @@ -95,9 +90,6 @@ test("Test minimal deployment that deploys a VPC without vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC w/vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC w/vpcProps", () => { // Stack const stack = new Stack(); @@ -152,9 +144,6 @@ test("Test minimal deployment that deploys a VPC w/vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC", () => { // Stack const stack = new Stack(); @@ -198,12 +187,6 @@ test("Test minimal deployment with an existing VPC", () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC and existing Lambda function not in a VPC -// -// buildLambdaFunction should throw an error if the Lambda function is not -// attached to a VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC and existing Lambda function not in a VPC", () => { // Stack const stack = new Stack(); @@ -230,10 +213,7 @@ test("Test minimal deployment with an existing VPC and existing Lambda function }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { +test("Confirm CheckVpcProps is called", () => { // Stack const stack = new Stack(); @@ -252,12 +232,9 @@ test("Test bad call with existingVpc and deployVpc", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); }); -// -------------------------------------------------------------- -// Test lambda function custom environment variable -// -------------------------------------------------------------- test('Test lambda function custom environment variable', () => { // Stack const stack = new Stack(); @@ -344,7 +321,7 @@ test('Queue is encrypted with imported CMK when set on queueProps.encryptionMast }); }); -test('Queue is encrypted with provided encrytionKeyProps', () => { +test('Queue is encrypted with provided encryptionKeyProps', () => { const stack = new Stack(); new LambdaToSqs(stack, 'test-construct', { @@ -428,19 +405,6 @@ test('Queue is encrypted with customer managed KMS Key when enable encryption fl }); }); -test('Error is thrown when conflicting VPC information is provided', () => { - const stack = new Stack(); - - const app = () => { - new LambdaToSqs(stack, 'test-construct', { - existingVpc: new ec2.Vpc(stack, "test-vpc", {}), - deployVpc: true - }); - }; - - expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.'); -}); - test('Queue purging flag grants correct permissions', () => { const stack = new Stack(); @@ -523,4 +487,50 @@ test('Queue purging flag grants correct permissions', () => { } ] }); -}); \ No newline at end of file +}); + +test('Confirm CheckSqsProps is being called', () => { + // Stack + const stack = new Stack(); + // Helper declaration + const props = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`) + }, + queueProps: { + removalPolicy: RemovalPolicy.DESTROY, + }, + existingQueueObj: new sqs.Queue(stack, 'test', {}) + }; + + const app = () => { + new LambdaToSqs(stack, 'test-eventbridge-sqs', props); + }; + expect(app).toThrowError("Error - Either provide queueProps or existingQueueObj, but not both.\n"); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToSqsProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToSqs(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/README.md index aed870756..d360c0e7a 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/README.md @@ -102,7 +102,7 @@ new LambdaToSsmstringparameter(this, "test-lambda-ssmstringparameter-stack", |stringParameterProps?|[`ssm.StringParameterProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameterProps.html)|Optional user provided props to override the default props for SSM String parameter. If existingStringParameterObj is not set stringParameterProps is required. The only supported [`ssm.StringParameterProps.type`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameterProps.html#type) is [`STRING`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.ParameterType.html#string) if a different value is provided it will be overridden.| |stringParameterEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the name of the parameter. Default: SSM_STRING_PARAMETER_NAME | |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for AWS Systems Manager Parameter. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| |stringParameterPermissions|`string`|Optional SSM String parameter permissions to grant to the Lambda function. One of the following may be specified: "Read", "ReadWrite". diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/lib/index.ts index 01d038773..ef7d0279e 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/lib/index.ts @@ -94,7 +94,8 @@ export class LambdaToSsmstringparameter extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToSsmstringparameterProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); // This should have been an array, we will make it an array for validation if (props.stringParameterPermissions) { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunction.expected.json index d891590f7..882f39597 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunction.expected.json @@ -131,12 +131,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdassmstringparameterLambdaFunctionServiceRole0E6B5916", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -146,6 +140,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdassmstringparameterLambdaFunctionServiceRole0E6B5916", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunctionWithExistingVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunctionWithExistingVpc.expected.json index cb2ca1af1..47c986943 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunctionWithExistingVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunctionWithExistingVpc.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithExistingVpc/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,17 +657,31 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithExistingVpc/Vpc" + "Value": "deployFunctionWithExistingVpc/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSSM173B3B5B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "deployFunctionWithExistingVpcSSMsecuritygroupC287F479", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -685,18 +694,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "deployFunctionWithExistingVpcSSMsecuritygroupC287F479", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcPrivateSubnet1Subnet536B997A" @@ -708,7 +705,10 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "testlambdassmstringparameterLambdaFunctionServiceRole0E6B5916": { @@ -882,12 +882,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdassmstringparameterLambdaFunctionServiceRole0E6B5916", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -897,6 +891,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdassmstringparameterLambdaFunctionServiceRole0E6B5916", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunctionWithVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunctionWithVpc.expected.json index ac2fa43fa..785fe73e6 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunctionWithVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.deployFunctionWithVpc.expected.json @@ -172,12 +172,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdassmstringparameterLambdaFunctionServiceRole0E6B5916", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -187,6 +181,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdassmstringparameterLambdaFunctionServiceRole0E6B5916", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -264,9 +264,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -283,21 +280,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -314,9 +314,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -333,21 +330,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -364,9 +364,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -383,21 +380,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -429,7 +429,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] } @@ -481,7 +481,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] }, @@ -501,11 +501,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -516,17 +511,31 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "VpcSSM173B3B5B": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "deployFunctionWithVpcSSMsecuritygroup918CB15C", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -539,18 +548,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "deployFunctionWithVpcSSMsecuritygroup918CB15C", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -562,7 +559,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "deployFunctionWithVpcSSMsecuritygroup918CB15C": { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.existingFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.existingFunction.expected.json index c8bcfc575..0d209b92d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.existingFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.existingFunction.expected.json @@ -131,12 +131,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -146,6 +140,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.existingStringParameter.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.existingStringParameter.expected.json index 6e184391f..56d6d5a33 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.existingStringParameter.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/integ.existingStringParameter.expected.json @@ -138,12 +138,6 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdassmstringparameterLambdaFunctionServiceRole0E6B5916", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -153,6 +147,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdassmstringparameterLambdaFunctionServiceRole0E6B5916", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/lambda-ssmstringparameter.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/lambda-ssmstringparameter.test.ts index db3f570b9..33609ffaf 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/lambda-ssmstringparameter.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-ssmstringparameter/test/lambda-ssmstringparameter.test.ts @@ -15,14 +15,11 @@ import { Stack } from "aws-cdk-lib"; import * as lambda from "aws-cdk-lib/aws-lambda"; import * as ec2 from "aws-cdk-lib/aws-ec2"; -import { LambdaToSsmstringparameter } from '../lib'; +import { LambdaToSsmstringparameter, LambdaToSsmstringparameterProps } from '../lib'; import { Template } from 'aws-cdk-lib/assertions'; import { StringParameter } from "aws-cdk-lib/aws-ssm"; import * as defaults from "@aws-solutions-constructs/core"; -// -------------------------------------------------------------- -// Test lambda function custom environment variable -// -------------------------------------------------------------- test('Test lambda function custom environment variable', () => { // Stack const stack = new Stack(); @@ -57,9 +54,6 @@ test('Test lambda function custom environment variable', () => { }); }); -// -------------------------------------------------------------- -// Test the getter methods -// -------------------------------------------------------------- test('Test the properties', () => { // Stack const stack = new Stack(); @@ -80,9 +74,6 @@ test('Test the properties', () => { expect(stringParam).toBeDefined(); }); -// -------------------------------------------------------------- -// Test deployment w/ existing String Parameter -// -------------------------------------------------------------- test('Test deployment w/ existing String Parameter', () => { // Stack const stack = new Stack(); @@ -107,9 +98,6 @@ test('Test deployment w/ existing String Parameter', () => { expect(pattern.stringParameter).toBe(existingStringParam); }); -// -------------------------------------------------------------- -// Test deployment w/ existing function -// -------------------------------------------------------------- test('Test deployment w/ existing function', () => { // Stack const stack = new Stack(); @@ -135,9 +123,6 @@ test('Test deployment w/ existing function', () => { expect(pattern.lambdaFunction).toBe(existingFunction); }); -// -------------------------------------------------------------- -// Test minimal deployment with write access to String Parameter. -// -------------------------------------------------------------- test('Test minimal deployment write access to String Parameter ', () => { // Stack const stack = new Stack(); @@ -160,9 +145,6 @@ test('Test minimal deployment write access to String Parameter ', () => { }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC without vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC without vpcProps", () => { // Stack const stack = new Stack(); @@ -212,9 +194,6 @@ test("Test minimal deployment that deploys a VPC without vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC w/vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC w/vpcProps", () => { // Stack const stack = new Stack(); @@ -270,9 +249,6 @@ test("Test minimal deployment that deploys a VPC w/vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC", () => { // Stack const stack = new Stack(); @@ -317,12 +293,6 @@ test("Test minimal deployment with an existing VPC", () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC and existing Lambda function not in a VPC -// -// buildLambdaFunction should throw an error if the Lambda function is not -// attached to a VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC and existing Lambda function not in a VPC", () => { // Stack const stack = new Stack(); @@ -337,7 +307,8 @@ test("Test minimal deployment with an existing VPC and existing Lambda function // Helper declaration const app = () => { - // Helper declaration + // buildLambdaFunction should throw an error if the Lambda function is not + // attached to a VPC new LambdaToSsmstringparameter(stack, "lambda-to-ssm-stack", { existingLambdaObj: testLambdaFunction, existingVpc: testVpc, @@ -350,10 +321,7 @@ test("Test minimal deployment with an existing VPC and existing Lambda function }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { +test("Confirm that CheckVpcProps is called", () => { // Stack const stack = new Stack(); @@ -373,7 +341,7 @@ test("Test bad call with existingVpc and deployVpc", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); }); test("Test bad call with invalid string parameter permission", () => { @@ -396,3 +364,28 @@ test("Test bad call with invalid string parameter permission", () => { // Assertion expect(app).toThrowError('Invalid String Parameter permission submitted - Reed'); }); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: LambdaToSsmstringparameterProps = { + stringParameterProps: { stringValue: "test-string-value" }, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToSsmstringparameter(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/README.md b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/README.md index 79294aa63..7d8b983fe 100755 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/README.md @@ -106,7 +106,7 @@ new LambdaToStepfunctions(this, "test-lambda-stepfunctions-stack", |logGroupProps?|[`logs.LogGroupProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_logs.LogGroupProps.html)|User provided props to override the default props for for the CloudWatchLogs LogGroup.| |stateMachineEnvironmentVariableName?|`string`|Optional Name for the Lambda function environment variable set to the ARN of the state machine. Default: STATE_MACHINE_ARN | |existingVpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html)|An optional, existing VPC into which this pattern should be deployed. When deployed in a VPC, the Lambda function will use ENIs in the VPC to access network resources and an Interface Endpoint will be created in the VPC for Amazon Step Functions. If an existing VPC is provided, the `deployVpc` property cannot be `true`. This uses `ec2.IVpc` to allow clients to supply VPCs that exist outside the stack using the [`ec2.Vpc.fromLookup()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) method.| -|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overrriden. If `deployVpc` is not `true` then this property will be ignored.| +|vpcProps?|[`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html)|Optional user-provided properties to override the default properties for the new VPC. `enableDnsHostnames`, `enableDnsSupport`, `natGateways` and `subnetConfiguration` are set by the pattern, so any values for those properties supplied here will be overridden. If `deployVpc` is not `true` then this property will be ignored.| |deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:
  • One isolated subnet in each Availability Zone used by the CDK program
  • `enableDnsHostnames` and `enableDnsSupport` will both be set to true
If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.| diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/lib/index.ts index 9f6406460..ab1cd7da8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/lib/index.ts @@ -97,13 +97,11 @@ export class LambdaToStepfunctions extends Construct { */ constructor(scope: Construct, id: string, props: LambdaToStepfunctionsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckVpcProps(props); + defaults.CheckLambdaProps(props); // Setup vpc if (props.deployVpc || props.existingVpc) { - if (props.deployVpc && props.existingVpc) { - throw new Error("More than 1 VPC specified in the properties"); - } this.vpc = defaults.buildVpc(scope, { defaultVpcProps: defaults.DefaultIsolatedVpcProps(), diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.deploy-lambda.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.deploy-lambda.expected.json index 5d32965b4..251c1aca8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.deploy-lambda.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.deploy-lambda.expected.json @@ -135,12 +135,6 @@ "testlambdastepfunctionsconstructStateMachineE1526513": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "testlambdastepfunctionsconstructStateMachineRoleD2891199", - "Arn" - ] - }, "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", "LoggingConfiguration": { "Destinations": [ @@ -156,6 +150,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "testlambdastepfunctionsconstructStateMachineRoleD2891199", + "Arn" + ] } }, "DependsOn": [ @@ -270,12 +270,6 @@ }, "S3Key": "fd7a741674eeef7951675d2a57f0459376e046d88e5bee9aab601d8f5a704c93.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdastepfunctionsconstructLambdaFunctionServiceRole2D3C3FD0", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -285,6 +279,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdastepfunctionsconstructLambdaFunctionServiceRole2D3C3FD0", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -316,9 +316,8 @@ "testlambdastepfunctionsconstructExecutionFailedAlarm47C759E2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -327,6 +326,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -337,9 +337,8 @@ "testlambdastepfunctionsconstructExecutionThrottledAlarm23275AB5": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -348,6 +347,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -358,9 +358,8 @@ "testlambdastepfunctionsconstructExecutionAbortedAlarm6DBA2A2E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -369,6 +368,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -409,6 +409,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -442,6 +445,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.deployFunctionWithVpc.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.deployFunctionWithVpc.expected.json index 818d0a749..4f7f845e8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.deployFunctionWithVpc.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.deployFunctionWithVpc.expected.json @@ -116,12 +116,6 @@ "testlambdastepfunctionsStateMachine807F0A77": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "testlambdastepfunctionsStateMachineRoleAC728CE7", - "Arn" - ] - }, "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", "LoggingConfiguration": { "Destinations": [ @@ -137,6 +131,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "testlambdastepfunctionsStateMachineRoleAC728CE7", + "Arn" + ] } }, "DependsOn": [ @@ -292,12 +292,6 @@ }, "S3Key": "fd7a741674eeef7951675d2a57f0459376e046d88e5bee9aab601d8f5a704c93.zip" }, - "Role": { - "Fn::GetAtt": [ - "testlambdastepfunctionsLambdaFunctionServiceRoleA33E2E9C", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -307,6 +301,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testlambdastepfunctionsLambdaFunctionServiceRoleA33E2E9C", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -362,9 +362,8 @@ "testlambdastepfunctionsExecutionFailedAlarm41073C3F": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -373,6 +372,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -383,9 +383,8 @@ "testlambdastepfunctionsExecutionThrottledAlarm62EABDFD": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -394,6 +393,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -404,9 +404,8 @@ "testlambdastepfunctionsExecutionAbortedAlarmC9CB5C2D": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -415,6 +414,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -440,9 +440,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -459,21 +456,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -490,9 +490,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -509,21 +506,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -540,9 +540,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -559,21 +556,24 @@ "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployFunctionWithVpc/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -605,7 +605,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] } @@ -657,7 +657,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ] }, @@ -677,10 +677,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -691,10 +687,14 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployFunctionWithVpc/Vpc" + "Value": "deployFunctionWithVpc/Vpc/FlowLog" } ], "TrafficType": "ALL" @@ -703,6 +703,15 @@ "VpcSTEPFUNCTIONS550F8CB6": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "deployFunctionWithVpcSTEPFUNCTIONSsecuritygroupA9CFA360", + "GroupId" + ] + } + ], "ServiceName": { "Fn::Join": [ "", @@ -715,18 +724,6 @@ ] ] }, - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "PrivateDnsEnabled": true, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "deployFunctionWithVpcSTEPFUNCTIONSsecuritygroupA9CFA360", - "GroupId" - ] - } - ], "SubnetIds": [ { "Ref": "VpcisolatedSubnet1SubnetE62B1B9B" @@ -738,7 +735,10 @@ "Ref": "VpcisolatedSubnet3Subnet44F2537D" } ], - "VpcEndpointType": "Interface" + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "deployFunctionWithVpcSTEPFUNCTIONSsecuritygroupA9CFA360": { @@ -832,6 +832,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -865,6 +868,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.existing-function.expected.json b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.existing-function.expected.json index 1d02f85e7..76331499d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.existing-function.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/integ.existing-function.expected.json @@ -105,12 +105,6 @@ }, "S3Key": "fd7a741674eeef7951675d2a57f0459376e046d88e5bee9aab601d8f5a704c93.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -120,6 +114,12 @@ } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -263,12 +263,6 @@ "testlambdastepfunctionsconstructStateMachineE1526513": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "testlambdastepfunctionsconstructStateMachineRoleD2891199", - "Arn" - ] - }, "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", "LoggingConfiguration": { "Destinations": [ @@ -284,6 +278,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "testlambdastepfunctionsconstructStateMachineRoleD2891199", + "Arn" + ] } }, "DependsOn": [ @@ -296,9 +296,8 @@ "testlambdastepfunctionsconstructExecutionFailedAlarm47C759E2": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -307,6 +306,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -317,9 +317,8 @@ "testlambdastepfunctionsconstructExecutionThrottledAlarm23275AB5": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -328,6 +327,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -338,9 +338,8 @@ "testlambdastepfunctionsconstructExecutionAbortedAlarm6DBA2A2E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -349,6 +348,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -389,6 +389,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -422,6 +425,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/lambda-stepfunctions.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/lambda-stepfunctions.test.ts index cf9fbc33b..b1d14f0c1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/lambda-stepfunctions.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-stepfunctions/test/lambda-stepfunctions.test.ts @@ -17,12 +17,9 @@ import * as lambda from "aws-cdk-lib/aws-lambda"; import * as defaults from '@aws-solutions-constructs/core'; import * as stepfunctions from 'aws-cdk-lib/aws-stepfunctions'; import * as ec2 from "aws-cdk-lib/aws-ec2"; -import { LambdaToStepfunctions } from '../lib'; +import { LambdaToStepfunctions, LambdaToStepfunctionsProps } from '../lib'; import { Template } from "aws-cdk-lib/assertions"; -// -------------------------------------------------------------- -// Test deployment with new Lambda function -// -------------------------------------------------------------- test('Test deployment with new Lambda function', () => { // Stack const stack = new Stack(); @@ -90,9 +87,6 @@ test('Test deployment with existing Lambda function', () => { }); }); -// -------------------------------------------------------------- -// Test invocation permissions -// -------------------------------------------------------------- test('Test invocation permissions', () => { // Stack const stack = new Stack(); @@ -140,9 +134,6 @@ test('Test invocation permissions', () => { }); }); -// -------------------------------------------------------------- -// Test the properties -// -------------------------------------------------------------- test('Test the properties', () => { // Stack const stack = new Stack(); @@ -173,9 +164,6 @@ test('Test the properties', () => { expect(pattern.stateMachineLogGroup).toBeDefined(); }); -// -------------------------------------------------------------- -// Test the properties -// -------------------------------------------------------------- test('Test the properties with no CW Alarms', () => { // Stack const stack = new Stack(); @@ -204,9 +192,6 @@ test('Test the properties with no CW Alarms', () => { expect(pattern.stateMachineLogGroup).toBeDefined(); }); -// -------------------------------------------------------------- -// Test lambda function custom environment variable -// -------------------------------------------------------------- test('Test lambda function custom environment variable', () => { // Stack const stack = new Stack(); @@ -241,9 +226,6 @@ test('Test lambda function custom environment variable', () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment that deploys a VPC without vpcProps -// -------------------------------------------------------------- test("Test minimal deployment that deploys a VPC without vpcProps", () => { // Stack const stack = new Stack(); @@ -357,9 +339,6 @@ test("Test minimal deployment that deploys a VPC w/vpcProps", () => { template.resourceCountIs("AWS::EC2::InternetGateway", 0); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC", () => { // Stack const stack = new Stack(); @@ -406,12 +385,6 @@ test("Test minimal deployment with an existing VPC", () => { }); }); -// -------------------------------------------------------------- -// Test minimal deployment with an existing VPC and existing Lambda function not in a VPC -// -// buildLambdaFunction should throw an error if the Lambda function is not -// attached to a VPC -// -------------------------------------------------------------- test("Test minimal deployment with an existing VPC and existing Lambda function not in a VPC", () => { // Stack const stack = new Stack(); @@ -427,7 +400,8 @@ test("Test minimal deployment with an existing VPC and existing Lambda function // Helper declaration const app = () => { - // Helper declaration + // buildLambdaFunction should throw an error if the Lambda function is not + // attached to a VPC new LambdaToStepfunctions(stack, "lambda-to-stepfunctions-stack", { existingLambdaObj: testLambdaFunction, stateMachineProps: { @@ -442,10 +416,7 @@ test("Test minimal deployment with an existing VPC and existing Lambda function }); -// -------------------------------------------------------------- -// Test bad call with existingVpc and deployVpc -// -------------------------------------------------------------- -test("Test bad call with existingVpc and deployVpc", () => { +test("Confirm CheckVpcProps is called", () => { // Stack const stack = new Stack(); const startState = new stepfunctions.Pass(stack, 'StartState'); @@ -467,5 +438,33 @@ test("Test bad call with existingVpc and deployVpc", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const startState = new stepfunctions.Pass(stack, 'StartState'); + const props: LambdaToStepfunctionsProps = { + stateMachineProps: { + definition: startState + }, + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new LambdaToStepfunctions(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); }); diff --git a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/README.md b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/README.md index df299b0b3..804cebaac 100755 --- a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/README.md +++ b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/README.md @@ -20,7 +20,7 @@ ## Overview -This AWS Solutions Construct implements an Amazon API Gateway REST API defined by an OpenAPI specificiation file connected to an AWS Lambda function. +This AWS Solutions Construct implements an Amazon API Gateway REST API defined by an OpenAPI specification file connected to an AWS Lambda function. Here is a minimal deployable pattern definition: @@ -97,7 +97,7 @@ import java.util.Collections; import static software.amazon.awscdk.services.lambda.Runtime.NODEJS_18_X; -final Asset apiDefintionAsset = new Asset(this, "ApiDefinition", AssetProps.builder().path("openapispec.yaml").build()); +final Asset apiDefinitionAsset = new Asset(this, "ApiDefinition", AssetProps.builder().path("openapispec.yaml").build()); final ApiIntegration apiIntegration = ApiIntegration.builder() .id("MessagesHandler") @@ -109,7 +109,7 @@ final ApiIntegration apiIntegration = ApiIntegration.builder() .build(); new OpenApiGatewayToLambda(this, "OpenApiGatewayToLambda", OpenApiGatewayToLambdaProps.builder() - .apiDefinitionAsset(apiDefintionAsset) + .apiDefinitionAsset(apiDefinitionAsset) .apiIntegrations(Collections.singletonList(apiIntegration)) .build()); ``` @@ -218,4 +218,4 @@ Out of the box implementation of the Construct without any override will set the ![Architecture Diagram](architecture.png) *** -© Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. \ No newline at end of file +© Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/lib/index.ts index 1261fde3d..06a7c4a40 100644 --- a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/lib/index.ts @@ -144,26 +144,18 @@ export class OpenApiGatewayToLambda extends Construct { constructor(scope: Construct, id: string, props: OpenApiGatewayToLambdaProps) { super(scope, id); - - if (props.apiDefinitionAsset && (props.apiDefinitionBucket || props.apiDefinitionKey)) { - throw new Error('Either apiDefinitionBucket/apiDefinitionKey or apiDefinitionAsset must be specified, but not both'); - } + CheckOpenapiProps(props); const apiDefinitionBucket = props.apiDefinitionBucket ?? props.apiDefinitionAsset?.bucket; const apiDefinitionKey = props.apiDefinitionKey ?? props.apiDefinitionAsset?.s3ObjectKey; - if (apiDefinitionBucket === undefined || apiDefinitionKey === undefined) { - throw new Error('Either apiDefinitionBucket/apiDefinitionKey or apiDefinitionAsset must be specified'); - } - - if (props.apiIntegrations === undefined || props.apiIntegrations.length < 1) { - throw new Error('At least one ApiIntegration must be specified in the apiIntegrations property'); - } - // store a counter to be able to uniquely name lambda functions to avoid naming collisions let lambdaCounter = 0; this.apiLambdaFunctions = props.apiIntegrations.map(apiIntegration => { + if (apiIntegration.existingLambdaObj && apiIntegration.lambdaFunctionProps) { + throw new Error(`Error - Cannot provide both lambdaFunctionProps and existingLambdaObj in an ApiIntegrationfor the api integration with id: ${apiIntegration.id}`); + } if (apiIntegration.existingLambdaObj || apiIntegration.lambdaFunctionProps) { return { id: apiIntegration.id, @@ -193,8 +185,9 @@ export class OpenApiGatewayToLambda extends Construct { // This custom resource will overwrite the string placeholders in the openapi definition with the resolved values of the lambda URIs const apiDefinitionWriter = resources.createTemplateWriterCustomResource(this, 'Api', { - templateBucket: apiDefinitionBucket, - templateKey: apiDefinitionKey, + // CheckAlbProps() has confirmed the existence of these values + templateBucket: apiDefinitionBucket!, + templateKey: apiDefinitionKey!, templateValues: apiIntegrationUris, timeout: props.internalTransformTimeout ?? cdk.Duration.minutes(1), memorySize: props.internalTransformMemorySize ?? 1024 @@ -226,3 +219,32 @@ export class OpenApiGatewayToLambda extends Construct { }); } } + +function CheckOpenapiProps(props: OpenApiGatewayToLambdaProps) { + + let errorMessages = ''; + let errorFound = false; + + if (props.apiDefinitionAsset && (props.apiDefinitionBucket || props.apiDefinitionKey)) { + errorMessages += 'Either apiDefinitionBucket/apiDefinitionKey or apiDefinitionAsset must be specified, but not both\n'; + errorFound = true; + } + + const apiDefinitionBucket = props.apiDefinitionBucket ?? props.apiDefinitionAsset?.bucket; + const apiDefinitionKey = props.apiDefinitionKey ?? props.apiDefinitionAsset?.s3ObjectKey; + + if (apiDefinitionBucket === undefined || apiDefinitionKey === undefined) { + errorMessages += 'Either apiDefinitionBucket/apiDefinitionKey or apiDefinitionAsset must be specified\n'; + errorFound = true; + } + + if (props.apiIntegrations === undefined || props.apiIntegrations.length < 1) { + errorMessages += 'At least one ApiIntegration must be specified in the apiIntegrations property\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } + +} \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetExistingLambdaFunctions.expected.json b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetExistingLambdaFunctions.expected.json index 1732135d5..90ce56cf6 100644 --- a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetExistingLambdaFunctions.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetExistingLambdaFunctions.expected.json @@ -99,13 +99,13 @@ }, "S3Key": "8ce85d10dcd7b8e6d43ffd909827afc76802ad40fcd7908886ff825cbe8e15df.zip" }, + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "LambdaFunctionServiceRole0C4CDE0B", "Arn" ] }, - "Handler": "index.handler", "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -269,14 +269,14 @@ }, "S3Key": "654d49d4ea47a6be417d57b94dc0310933d0e971a3e48a3080c3e48487af3e50.zip" }, + "FunctionName": "PhotosLambdaTestFromAsset", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "PhotosLambdaTestFromAssetServiceRoleE0B4776B", "Arn" ] }, - "FunctionName": "PhotosLambdaTestFromAsset", - "Handler": "index.handler", "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -552,14 +552,14 @@ }, "S3Key": "96f7d2d4f45b57a586d030966d31e06bc622b5f20258ca38d605fef38e6b9a17.zip" }, + "Handler": "index.handler", + "MemorySize": 1024, "Role": { "Fn::GetAtt": [ "OpenApiGatewayToLambdaApiTemplateWriterLambdaRoleCBDA4014", "Arn" ] }, - "Handler": "index.handler", - "MemorySize": 1024, "Runtime": "nodejs18.x", "Timeout": 60, "TracingConfig": { @@ -669,13 +669,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "8e3d635893ea17fa3158623489cd42c680fad925b38de1ef51cb10d84f6e245e.zip" - }, - "Role": { - "Fn::GetAtt": [ - "OpenApiGatewayToLambdaApiTemplateWriterProviderframeworkonEventServiceRoleFEE201A1", - "Arn" - ] + "S3Key": "7382a0addb9f34974a1ea6c6c9b063882af874828f366f5c93b2b7b64db15c94.zip" }, "Description": "AWS CDK resource provider framework - onEvent (apiFromAssetExistingLambdaFunctions/OpenApiGatewayToLambda/ApiTemplateWriterProvider)", "Environment": { @@ -689,7 +683,13 @@ } }, "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", + "Role": { + "Fn::GetAtt": [ + "OpenApiGatewayToLambdaApiTemplateWriterProviderframeworkonEventServiceRoleFEE201A1", + "Arn" + ] + }, + "Runtime": "nodejs18.x", "Timeout": 900 }, "DependsOn": [ @@ -832,17 +832,17 @@ "OpenApiGatewayToLambdaSpecRestApiDeploymentC8BD0775114a8d1d0c9bf9b9d904a22f099d1d64": { "Type": "AWS::ApiGateway::Deployment", "Properties": { + "Description": "Automatically created by the RestApi construct", "RestApiId": { "Ref": "OpenApiGatewayToLambdaSpecRestApi27C18064" - }, - "Description": "Automatically created by the RestApi construct" + } }, "Metadata": { "cfn_nag": { "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -851,9 +851,6 @@ "OpenApiGatewayToLambdaSpecRestApiDeploymentStageprodB962CBBB": { "Type": "AWS::ApiGateway::Stage", "Properties": { - "RestApiId": { - "Ref": "OpenApiGatewayToLambdaSpecRestApi27C18064" - }, "AccessLogSetting": { "DestinationArn": { "Fn::GetAtt": [ @@ -874,6 +871,9 @@ "ResourcePath": "/*" } ], + "RestApiId": { + "Ref": "OpenApiGatewayToLambdaSpecRestApi27C18064" + }, "StageName": "prod", "TracingEnabled": true } diff --git a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetNewLambdaFunctions.expected.json b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetNewLambdaFunctions.expected.json index 8af032032..22cc311a0 100644 --- a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetNewLambdaFunctions.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetNewLambdaFunctions.expected.json @@ -99,13 +99,13 @@ }, "S3Key": "8ce85d10dcd7b8e6d43ffd909827afc76802ad40fcd7908886ff825cbe8e15df.zip" }, + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "OpenApiGatewayToLambdaMessagesHandlerApiFunction0ServiceRoleB5DC63A9", "Arn" ] }, - "Handler": "index.handler", "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -269,13 +269,13 @@ }, "S3Key": "654d49d4ea47a6be417d57b94dc0310933d0e971a3e48a3080c3e48487af3e50.zip" }, + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "OpenApiGatewayToLambdaPhotosHandlerApiFunction1ServiceRoleA572C749", "Arn" ] }, - "Handler": "index.handler", "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -551,14 +551,14 @@ }, "S3Key": "96f7d2d4f45b57a586d030966d31e06bc622b5f20258ca38d605fef38e6b9a17.zip" }, + "Handler": "index.handler", + "MemorySize": 1024, "Role": { "Fn::GetAtt": [ "OpenApiGatewayToLambdaApiTemplateWriterLambdaRoleCBDA4014", "Arn" ] }, - "Handler": "index.handler", - "MemorySize": 1024, "Runtime": "nodejs18.x", "Timeout": 60, "TracingConfig": { @@ -668,13 +668,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "8e3d635893ea17fa3158623489cd42c680fad925b38de1ef51cb10d84f6e245e.zip" - }, - "Role": { - "Fn::GetAtt": [ - "OpenApiGatewayToLambdaApiTemplateWriterProviderframeworkonEventServiceRoleFEE201A1", - "Arn" - ] + "S3Key": "7382a0addb9f34974a1ea6c6c9b063882af874828f366f5c93b2b7b64db15c94.zip" }, "Description": "AWS CDK resource provider framework - onEvent (apiFromAssetNewLambdaFunctions/OpenApiGatewayToLambda/ApiTemplateWriterProvider)", "Environment": { @@ -688,7 +682,13 @@ } }, "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", + "Role": { + "Fn::GetAtt": [ + "OpenApiGatewayToLambdaApiTemplateWriterProviderframeworkonEventServiceRoleFEE201A1", + "Arn" + ] + }, + "Runtime": "nodejs18.x", "Timeout": 900 }, "DependsOn": [ @@ -831,17 +831,17 @@ "OpenApiGatewayToLambdaSpecRestApiDeploymentC8BD0775c586d865ce613dde0b09710274a96485": { "Type": "AWS::ApiGateway::Deployment", "Properties": { + "Description": "Automatically created by the RestApi construct", "RestApiId": { "Ref": "OpenApiGatewayToLambdaSpecRestApi27C18064" - }, - "Description": "Automatically created by the RestApi construct" + } }, "Metadata": { "cfn_nag": { "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -850,9 +850,6 @@ "OpenApiGatewayToLambdaSpecRestApiDeploymentStageprodB962CBBB": { "Type": "AWS::ApiGateway::Stage", "Properties": { - "RestApiId": { - "Ref": "OpenApiGatewayToLambdaSpecRestApi27C18064" - }, "AccessLogSetting": { "DestinationArn": { "Fn::GetAtt": [ @@ -873,6 +870,9 @@ "ResourcePath": "/*" } ], + "RestApiId": { + "Ref": "OpenApiGatewayToLambdaSpecRestApi27C18064" + }, "StageName": "prod", "TracingEnabled": true } diff --git a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetWithCognitoAuth.expected.json b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetWithCognitoAuth.expected.json index 1f3a617a5..c888345b9 100644 --- a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetWithCognitoAuth.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/integ.apiFromAssetWithCognitoAuth.expected.json @@ -99,13 +99,13 @@ }, "S3Key": "8ce85d10dcd7b8e6d43ffd909827afc76802ad40fcd7908886ff825cbe8e15df.zip" }, + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "OpenApiGatewayToLambdaMessagesHandlerApiFunction0ServiceRoleB5DC63A9", "Arn" ] }, - "Handler": "index.handler", "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -269,13 +269,13 @@ }, "S3Key": "654d49d4ea47a6be417d57b94dc0310933d0e971a3e48a3080c3e48487af3e50.zip" }, + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "OpenApiGatewayToLambdaPhotosHandlerApiFunction1ServiceRoleA572C749", "Arn" ] }, - "Handler": "index.handler", "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -551,14 +551,14 @@ }, "S3Key": "96f7d2d4f45b57a586d030966d31e06bc622b5f20258ca38d605fef38e6b9a17.zip" }, + "Handler": "index.handler", + "MemorySize": 1024, "Role": { "Fn::GetAtt": [ "OpenApiGatewayToLambdaApiTemplateWriterLambdaRoleCBDA4014", "Arn" ] }, - "Handler": "index.handler", - "MemorySize": 1024, "Runtime": "nodejs18.x", "Timeout": 60, "TracingConfig": { @@ -668,13 +668,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "8e3d635893ea17fa3158623489cd42c680fad925b38de1ef51cb10d84f6e245e.zip" - }, - "Role": { - "Fn::GetAtt": [ - "OpenApiGatewayToLambdaApiTemplateWriterProviderframeworkonEventServiceRoleFEE201A1", - "Arn" - ] + "S3Key": "7382a0addb9f34974a1ea6c6c9b063882af874828f366f5c93b2b7b64db15c94.zip" }, "Description": "AWS CDK resource provider framework - onEvent (apiFromAssetWithCognitoAuth/OpenApiGatewayToLambda/ApiTemplateWriterProvider)", "Environment": { @@ -688,7 +682,13 @@ } }, "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", + "Role": { + "Fn::GetAtt": [ + "OpenApiGatewayToLambdaApiTemplateWriterProviderframeworkonEventServiceRoleFEE201A1", + "Arn" + ] + }, + "Runtime": "nodejs18.x", "Timeout": 900 }, "DependsOn": [ @@ -831,17 +831,17 @@ "OpenApiGatewayToLambdaSpecRestApiDeploymentC8BD0775d25e717744ab7d508aee3a1c3b7aa9b2": { "Type": "AWS::ApiGateway::Deployment", "Properties": { + "Description": "Automatically created by the RestApi construct", "RestApiId": { "Ref": "OpenApiGatewayToLambdaSpecRestApi27C18064" - }, - "Description": "Automatically created by the RestApi construct" + } }, "Metadata": { "cfn_nag": { "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -850,9 +850,6 @@ "OpenApiGatewayToLambdaSpecRestApiDeploymentStageprodB962CBBB": { "Type": "AWS::ApiGateway::Stage", "Properties": { - "RestApiId": { - "Ref": "OpenApiGatewayToLambdaSpecRestApi27C18064" - }, "AccessLogSetting": { "DestinationArn": { "Fn::GetAtt": [ @@ -873,6 +870,9 @@ "ResourcePath": "/*" } ], + "RestApiId": { + "Ref": "OpenApiGatewayToLambdaSpecRestApi27C18064" + }, "StageName": "prod", "TracingEnabled": true } diff --git a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/test.openapigateway-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/test.openapigateway-lambda.test.ts index 5f80a68ea..82baf379d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/test.openapigateway-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-openapigateway-lambda/test/test.openapigateway-lambda.test.ts @@ -438,3 +438,37 @@ test('Confirm API definition uri is added to function name', () => { })).toBeTruthy(); }); + +test('Confirm that providing both lambdaFunction and functionProps is an error', () => { + const stack = new Stack(); + const existingLambdaObj = new lambda.Function(stack, 'ExistingLambda', { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + functionName: 'ExistingLambdaFunction', + code: lambda.Code.fromAsset(`${__dirname}/messages-lambda`), + }); + + const apiDefinitionAsset = new Asset(stack, 'OpenApiAsset', { + path: path.join(__dirname, 'openapi/apiDefinition.yaml') + }); + + const props = { + apiDefinitionAsset, + apiIntegrations: [ + { + id: 'MessagesHandler', + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/messages-lambda`), + }, + existingLambdaObj + } + ] + }; + + const app = () => { + new OpenApiGatewayToLambda(stack, 'test-apigateway-lambda', props); + }; + expect(app).toThrowError(`Error - Cannot provide both lambdaFunctionProps and existingLambdaObj in an ApiIntegrationfor the api integration with id: MessagesHandler`); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-route53-alb/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-route53-alb/lib/index.ts index 60a80a31e..2130e99b2 100644 --- a/source/patterns/@aws-solutions-constructs/aws-route53-alb/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-route53-alb/lib/index.ts @@ -103,17 +103,9 @@ export class Route53ToAlb extends Construct { */ constructor(scope: Construct, id: string, props: Route53ToAlbProps) { super(scope, id); - defaults.CheckProps(props); - // NOTE: We don't call CheckAlbProps() here, because this construct creates an ALB // with no listener or target, so some of those checks don't apply - if (props?.loadBalancerProps?.vpc) { - throw new Error('Specify any existing VPC at the construct level, not within loadBalancerProps.'); - } - - if (props.existingLoadBalancerObj && !props.existingVpc) { - throw new Error('An existing ALB already exists in a VPC, so that VPC must be passed to the construct in props.existingVpc'); - } + this.PropsCustomCheck(props); if (props.existingHostedZoneInterface && !props.publicApi && !props.existingVpc) { throw new Error('An existing Private Hosted Zone already exists in a VPC, so that VPC must be passed to the construct in props.existingVpc'); @@ -167,4 +159,14 @@ export class Route53ToAlb extends Construct { // Before turning off SonarQube for the line, reduce the line to it's minimum new r53.ARecord(this, arecordId, arecordProps); // NOSONAR } + + private PropsCustomCheck(props: Route53ToAlbProps) { + if (props?.loadBalancerProps?.vpc) { + throw new Error('Specify any existing VPC at the construct level, not within loadBalancerProps.'); + } + + if (props.existingLoadBalancerObj && !props.existingVpc) { + throw new Error('An existing ALB already exists in a VPC, so that VPC must be passed to the construct in props.existingVpc'); + } + } } diff --git a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPrivateApi.expected.json b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPrivateApi.expected.json index 7cc0131dc..5d0d3bb46 100644 --- a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPrivateApi.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPrivateApi.expected.json @@ -326,8 +326,6 @@ "privateapistackprivateapistackalias54E3713F": { "Type": "AWS::Route53::RecordSet", "Properties": { - "Name": "www.example.com.", - "Type": "A", "AliasTarget": { "DNSName": { "Fn::Join": [ @@ -352,7 +350,9 @@ }, "HostedZoneId": { "Ref": "privateapistackprivateapistackzone3E5194E7" - } + }, + "Name": "www.example.com.", + "Type": "A" } }, "Vpc8378EB38": { @@ -373,9 +373,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -392,21 +389,24 @@ "Key": "Name", "Value": "deployPrivateApi/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPrivateApi/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -423,9 +423,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -442,21 +439,24 @@ "Key": "Name", "Value": "deployPrivateApi/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPrivateApi/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -473,9 +473,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -492,21 +489,24 @@ "Key": "Name", "Value": "deployPrivateApi/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPrivateApi/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -538,7 +538,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployPrivateApi/Vpc" + "Value": "deployPrivateApi/Vpc/FlowLog" } ] } @@ -590,7 +590,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployPrivateApi/Vpc" + "Value": "deployPrivateApi/Vpc/FlowLog" } ] }, @@ -610,11 +610,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -625,12 +620,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployPrivateApi/Vpc" + "Value": "deployPrivateApi/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { @@ -662,18 +662,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e57c1acaa363d7d2b81736776007a7091bc73dff4aeb8135627c4511a51e7dca.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", diff --git a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPrivateApiExistingZone.expected.json b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPrivateApiExistingZone.expected.json index 2d1df8163..3a56327aa 100644 --- a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPrivateApiExistingZone.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPrivateApiExistingZone.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPrivateApiExistingZone/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployPrivateApiExistingZone/Vpc" + "Value": "deployPrivateApiExistingZone/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployPrivateApiExistingZone/Vpc" + "Value": "deployPrivateApiExistingZone/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,12 +657,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployPrivateApiExistingZone/Vpc" + "Value": "deployPrivateApiExistingZone/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "newzone1D011936": { @@ -995,8 +995,6 @@ "existingzonestackexistingzonestackalias77D2E65D": { "Type": "AWS::Route53::RecordSet", "Properties": { - "Name": "www.test-example.com.", - "Type": "A", "AliasTarget": { "DNSName": { "Fn::Join": [ @@ -1021,7 +1019,9 @@ }, "HostedZoneId": { "Ref": "newzone1D011936" - } + }, + "Name": "www.test-example.com.", + "Type": "A" } }, "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { @@ -1053,18 +1053,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e57c1acaa363d7d2b81736776007a7091bc73dff4aeb8135627c4511a51e7dca.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", diff --git a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPublicApiExistingAlb.expected.json b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPublicApiExistingAlb.expected.json index 6bc4a720c..b9cf81aa1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPublicApiExistingAlb.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPublicApiExistingAlb.expected.json @@ -19,9 +19,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -38,7 +35,10 @@ "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -54,15 +54,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -79,12 +79,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -106,15 +106,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -130,9 +130,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -149,7 +146,10 @@ "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -165,15 +165,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -190,12 +190,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -217,15 +217,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -241,9 +241,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -260,7 +257,10 @@ "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -276,15 +276,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -301,12 +301,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -328,15 +328,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -352,9 +352,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -371,21 +368,24 @@ "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -402,21 +402,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -433,21 +430,24 @@ "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -464,21 +464,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -495,21 +492,24 @@ "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiExistingAlb/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -526,12 +526,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -549,11 +549,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -575,7 +575,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployPublicApiExistingAlb/Vpc" + "Value": "deployPublicApiExistingAlb/Vpc/FlowLog" } ] } @@ -627,7 +627,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployPublicApiExistingAlb/Vpc" + "Value": "deployPublicApiExistingAlb/Vpc/FlowLog" } ] }, @@ -647,11 +647,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -662,12 +657,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployPublicApiExistingAlb/Vpc" + "Value": "deployPublicApiExistingAlb/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "newzone1D011936": { @@ -749,8 +749,6 @@ "publicapistackpublicapistackalias4096038C": { "Type": "AWS::Route53::RecordSet", "Properties": { - "Name": "www.test-example.com.", - "Type": "A", "AliasTarget": { "DNSName": { "Fn::Join": [ @@ -775,7 +773,9 @@ }, "HostedZoneId": { "Ref": "newzone1D011936" - } + }, + "Name": "www.test-example.com.", + "Type": "A" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPublicApiNewAlb.expected.json b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPublicApiNewAlb.expected.json index 9e5b5818b..609c4a6d2 100644 --- a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPublicApiNewAlb.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployPublicApiNewAlb.expected.json @@ -324,8 +324,6 @@ "newalbstacknewalbstackalias05E0DF53": { "Type": "AWS::Route53::RecordSet", "Properties": { - "Name": "www.test-example.com.", - "Type": "A", "AliasTarget": { "DNSName": { "Fn::Join": [ @@ -350,7 +348,9 @@ }, "HostedZoneId": { "Ref": "newzone1D011936" - } + }, + "Name": "www.test-example.com.", + "Type": "A" } }, "Vpc8378EB38": { @@ -371,9 +371,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/19", "MapPublicIpOnLaunch": true, @@ -390,7 +387,10 @@ "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -406,15 +406,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -431,12 +431,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -458,15 +458,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -482,9 +482,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.32.0/19", "MapPublicIpOnLaunch": true, @@ -501,7 +498,10 @@ "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -517,15 +517,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -542,12 +542,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -569,15 +569,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -593,9 +593,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.64.0/19", "MapPublicIpOnLaunch": true, @@ -612,7 +609,10 @@ "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -628,15 +628,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -653,12 +653,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -680,15 +680,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -704,9 +704,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.96.0/19", "MapPublicIpOnLaunch": false, @@ -723,21 +720,24 @@ "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -754,21 +754,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.128.0/19", "MapPublicIpOnLaunch": false, @@ -785,21 +782,24 @@ "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -816,21 +816,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.160.0/19", "MapPublicIpOnLaunch": false, @@ -847,21 +844,24 @@ "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployPublicApiNewAlb/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -878,12 +878,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -901,11 +901,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -927,7 +927,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployPublicApiNewAlb/Vpc" + "Value": "deployPublicApiNewAlb/Vpc/FlowLog" } ] } @@ -979,7 +979,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployPublicApiNewAlb/Vpc" + "Value": "deployPublicApiNewAlb/Vpc/FlowLog" } ] }, @@ -999,11 +999,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -1014,12 +1009,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployPublicApiNewAlb/Vpc" + "Value": "deployPublicApiNewAlb/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { @@ -1051,18 +1051,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e57c1acaa363d7d2b81736776007a7091bc73dff4aeb8135627c4511a51e7dca.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", diff --git a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployWithoutLogging.expected.json b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployWithoutLogging.expected.json index 2c42249ee..47d84e1f8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployWithoutLogging.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/integ.deployWithoutLogging.expected.json @@ -88,8 +88,6 @@ "nologgingstacknologgingstackalias0D6EE5FC": { "Type": "AWS::Route53::RecordSet", "Properties": { - "Name": "www.example.com.", - "Type": "A", "AliasTarget": { "DNSName": { "Fn::Join": [ @@ -114,7 +112,9 @@ }, "HostedZoneId": { "Ref": "nologgingstacknologgingstackzoneE11B9175" - } + }, + "Name": "www.example.com.", + "Type": "A" } }, "Vpc8378EB38": { @@ -135,9 +135,6 @@ "VpcisolatedSubnet1SubnetE62B1B9B": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": false, @@ -154,21 +151,24 @@ "Key": "Name", "Value": "deployWithoutLogging/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableE442650B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployWithoutLogging/Vpc/isolatedSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet1RouteTableAssociationD259E31A": { @@ -185,9 +185,6 @@ "VpcisolatedSubnet2Subnet39217055": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": false, @@ -204,21 +201,24 @@ "Key": "Name", "Value": "deployWithoutLogging/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTable334F9764": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployWithoutLogging/Vpc/isolatedSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet2RouteTableAssociation25A4716F": { @@ -235,9 +235,6 @@ "VpcisolatedSubnet3Subnet44F2537D": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "10.0.128.0/18", "MapPublicIpOnLaunch": false, @@ -254,21 +251,24 @@ "Key": "Name", "Value": "deployWithoutLogging/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableA2F6BBC0": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "deployWithoutLogging/Vpc/isolatedSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcisolatedSubnet3RouteTableAssociationDC010BEB": { @@ -300,7 +300,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployWithoutLogging/Vpc" + "Value": "deployWithoutLogging/Vpc/FlowLog" } ] } @@ -352,7 +352,7 @@ "Tags": [ { "Key": "Name", - "Value": "deployWithoutLogging/Vpc" + "Value": "deployWithoutLogging/Vpc/FlowLog" } ] }, @@ -372,11 +372,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -387,12 +382,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "deployWithoutLogging/Vpc" + "Value": "deployWithoutLogging/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/route53-alb.test.ts b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/route53-alb.test.ts index d1747bc10..5c6a0b098 100644 --- a/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/route53-alb.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-route53-alb/test/route53-alb.test.ts @@ -247,6 +247,7 @@ test('Check that passing an existing hosted Zone without passing an existingVPC }); test('Check that passing an existing Load Balancer without passing an existingVPC is an error', () => { + // This also confirms CheckAlbProps is properly working const stack = new Stack(); const testExistingVpc = defaults.getTestVpc(stack); @@ -267,7 +268,7 @@ test('Check that passing an existing Load Balancer without passing an existingVP new Route53ToAlb(stack, 'test-error', props); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError("An existing ALB already exists in a VPC, so that VPC must be passed to the construct in props.existingVpc"); }); diff --git a/source/patterns/@aws-solutions-constructs/aws-route53-apigateway/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-route53-apigateway/lib/index.ts index bb1c001e4..1c18e8284 100755 --- a/source/patterns/@aws-solutions-constructs/aws-route53-apigateway/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-route53-apigateway/lib/index.ts @@ -61,7 +61,7 @@ export interface Route53ToApiGatewayProps { /** * An existing AWS Certificate Manager certificate for your custom domain name. * - * @defualt - None + * @default - None */ readonly existingCertificateInterface: certificatemanager.ICertificate; } @@ -84,7 +84,6 @@ export class Route53ToApiGateway extends Construct { */ constructor(scope: Construct, id: string, props: Route53ToApiGatewayProps) { super(scope, id); - defaults.CheckProps(props); this.certificate = props.existingCertificateInterface; @@ -95,32 +94,12 @@ export class Route53ToApiGateway extends Construct { // Existing Public or Private Hosted Zone if (props.existingHostedZoneInterface) { this.hostedZone = props.existingHostedZoneInterface; + this.ExistingHostedZonePropCheck(props); - if (props.existingVpc) { - throw new Error('Cannot provide an existing VPC to an existing Private Hosted Zone.'); - } - if (props.privateHostedZoneProps) { - throw new Error('Must provide either existingHostedZoneInterface or privateHostedZoneProps, but not both.'); - } } else { // Creating a Private Hosted Zone - if (props.publicApi) { - throw new Error('Public APIs require an existingHostedZone be passed in the Props object.'); - } else { - if (!props.privateHostedZoneProps) { - throw new Error('Must provide either existingHostedZoneInterface or privateHostedZoneProps.'); - } - if (props.privateHostedZoneProps.vpc) { - throw new Error('All VPC specs must be provided at the Construct level in Route53ToApiGatewayProps.'); - } - if (!props.privateHostedZoneProps.zoneName) { - throw new Error('Must supply zoneName for Private Hosted Zone Props.'); - } - if ( !this.vpc ) { - throw new Error('Must specify an existingVPC for the Private Hosted Zone in the construct props.'); - } - const manufacturedProps: route53.PrivateHostedZoneProps = defaults.overrideProps(props.privateHostedZoneProps, { vpc: this.vpc }); - this.hostedZone = new route53.PrivateHostedZone(this, `${id}-zone`, manufacturedProps); - } + this.PrivateHostedZonePropsChecks(props); + const manufacturedProps: route53.PrivateHostedZoneProps = defaults.overrideProps(props.privateHostedZoneProps, { vpc: this.vpc }); + this.hostedZone = new route53.PrivateHostedZone(this, `${id}-zone`, manufacturedProps); } // Convert IRestApi to RestApi @@ -140,4 +119,31 @@ export class Route53ToApiGateway extends Construct { // Create A Record in custom domain to route traffic to API Gateway new route53.ARecord(this, 'CustomDomainAliasRecord', arecordProps); // NOSONAR } -} \ No newline at end of file + + private ExistingHostedZonePropCheck(props: Route53ToApiGatewayProps) { + if (props.existingVpc) { + throw new Error('Cannot provide an existing VPC to an existing Private Hosted Zone.'); + } + if (props.privateHostedZoneProps) { + throw new Error('Must provide either existingHostedZoneInterface or privateHostedZoneProps, but not both.'); + } + } + + private PrivateHostedZonePropsChecks(props: Route53ToApiGatewayProps) { + if (props.publicApi) { + throw new Error('Public APIs require an existingHostedZone be passed in the Props object.'); + } + if (!props.privateHostedZoneProps) { + throw new Error('Must provide either existingHostedZoneInterface or privateHostedZoneProps.'); + } + if (props.privateHostedZoneProps.vpc) { + throw new Error('All VPC specs must be provided at the Construct level in Route53ToApiGatewayProps.'); + } + if (!props.privateHostedZoneProps.zoneName) { + throw new Error('Must supply zoneName for Private Hosted Zone Props.'); + } + if (!this.vpc) { + throw new Error('Must specify an existingVPC for the Private Hosted Zone in the construct props.'); + } + } +} diff --git a/source/patterns/@aws-solutions-constructs/aws-route53-apigateway/test/integ.dummyTest.expected.json b/source/patterns/@aws-solutions-constructs/aws-route53-apigateway/test/integ.dummyTest.expected.json index 175a173b4..5d969b002 100644 --- a/source/patterns/@aws-solutions-constructs/aws-route53-apigateway/test/integ.dummyTest.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-route53-apigateway/test/integ.dummyTest.expected.json @@ -47,7 +47,7 @@ "rules_to_suppress": [ { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource" + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource" } ] } @@ -254,4 +254,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-s3-lambda/lib/index.ts index ba1d1a59e..b334bcccd 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-s3-lambda/lib/index.ts @@ -89,7 +89,8 @@ export class S3ToLambda extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); + defaults.CheckS3Props(props); + defaults.CheckLambdaProps(props); let bucket: s3.Bucket; diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/integ.existing-s3-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/integ.existing-s3-bucket.expected.json index 78f15a1ef..dfad072b0 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/integ.existing-s3-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/integ.existing-s3-bucket.expected.json @@ -197,18 +197,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -342,18 +342,18 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "tests3lambdaLambdaFunctionServiceRoleA74F4427", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "tests3lambdaLambdaFunctionServiceRoleA74F4427", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -485,109 +485,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/integ.no-arguments.expected.json index c60da90fa..400d8c050 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/integ.no-arguments.expected.json @@ -98,18 +98,18 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "tests3lambdaLambdaFunctionServiceRoleA74F4427", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "tests3lambdaLambdaFunctionServiceRoleA74F4427", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/s3-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/s3-lambda.test.ts index 6a1a3ea8d..e8c707bb1 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/s3-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-s3-lambda/test/s3-lambda.test.ts @@ -38,15 +38,12 @@ test('check properties', () => { const construct: S3ToLambda = deployNewFunc(stack); - expect(construct.lambdaFunction !== null); - expect(construct.s3Bucket !== null); - expect(construct.s3LoggingBucket !== null); + expect(construct.lambdaFunction).toBeDefined(); + expect(construct.s3Bucket).toBeDefined(); + expect(construct.s3LoggingBucket).toBeDefined(); }); -// -------------------------------------------------------------- -// Test bad call with existingBucket and bucketProps -// -------------------------------------------------------------- -test("Test bad call with existingBucket and bucketProps", () => { +test("Confirm CheckS3Props is being called", () => { // Stack const stack = new cdk.Stack(); @@ -55,6 +52,11 @@ test("Test bad call with existingBucket and bucketProps", () => { const app = () => { // Helper declaration new S3ToLambda(stack, "bad-s3-args", { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, existingBucketObj: testBucket, bucketProps: { removalPolicy: cdk.RemovalPolicy.DESTROY @@ -62,12 +64,9 @@ test("Test bad call with existingBucket and bucketProps", () => { }); }; // Assertion - expect(app).toThrowError(); + expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); }); -// -------------------------------------------------------------- -// s3 bucket with bucket, loggingBucket, and auto delete objects -// -------------------------------------------------------------- test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { const stack = new cdk.Stack(); @@ -102,9 +101,6 @@ test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { }); }); -// -------------------------------------------------------------- -// s3 bucket with one content bucket and no logging bucket -// -------------------------------------------------------------- test('s3 bucket with one content bucket and no logging bucket', () => { const stack = new cdk.Stack(); @@ -139,4 +135,28 @@ test('check properties with existing S3 bucket', () => { expect(construct.s3Bucket).toEqual(undefined); expect(construct.s3BucketInterface).not.toEqual(undefined); expect(construct.s3LoggingBucket).toEqual(undefined); -}); \ No newline at end of file +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: S3ToLambdaProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new S3ToLambda(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sns/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-s3-sns/lib/index.ts index 207622f86..5c522a454 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sns/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sns/lib/index.ts @@ -129,7 +129,8 @@ export class S3ToSns extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); + defaults.CheckSnsProps(props); + defaults.CheckS3Props(props); // If the enableEncryptionWithCustomerManagedKey is undefined, default it to true const enableEncryptionParam = props.enableEncryptionWithCustomerManagedKey === false ? false : true; diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.customLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.customLoggingBucket.expected.json index a47e32a2a..678527ff8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.customLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.customLoggingBucket.expected.json @@ -242,6 +242,7 @@ "tests3snsEncryptionKey6C553584": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -280,8 +281,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.existingS3Bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.existingS3Bucket.expected.json index ff8376880..a21e54624 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.existingS3Bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.existingS3Bucket.expected.json @@ -173,18 +173,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -223,6 +223,7 @@ "tests3snsEncryptionKey6C553584": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -261,8 +262,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" @@ -486,109 +486,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.existingSnsTopic.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.existingSnsTopic.expected.json index 2182fa528..354335412 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.existingSnsTopic.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.existingSnsTopic.expected.json @@ -3,6 +3,7 @@ "EncryptionKey1B843E66": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -41,8 +42,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.newTopicFromProps.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.newTopicFromProps.expected.json index fe7840adc..da9251c4a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.newTopicFromProps.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.newTopicFromProps.expected.json @@ -242,6 +242,7 @@ "tests3snsEncryptionKey6C553584": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -280,8 +281,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.noArguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.noArguments.expected.json index a47e32a2a..678527ff8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.noArguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.noArguments.expected.json @@ -242,6 +242,7 @@ "tests3snsEncryptionKey6C553584": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -280,8 +281,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.s3EventTypesAndFilters.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.s3EventTypesAndFilters.expected.json index 1608bdc30..618503467 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.s3EventTypesAndFilters.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/integ.s3EventTypesAndFilters.expected.json @@ -256,6 +256,7 @@ "tests3snsEncryptionKey6C553584": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -294,8 +295,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/test.s3-sns.test.ts b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/test.s3-sns.test.ts index 7a45685ad..13acbc083 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/test.s3-sns.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sns/test/test.s3-sns.test.ts @@ -24,11 +24,11 @@ test('All get methods return non-null objects', () => { const app = new S3ToSns(stack, 'test-s3-sns', { }); - expect(app.snsTopic !== null); - expect(app.s3Bucket !== null); - expect(app.s3LoggingBucket !== null); - expect(app.encryptionKey !== null); - expect(app.s3BucketInterface !== null); + expect(app.snsTopic).toBeDefined(); + expect(app.s3Bucket).toBeDefined(); + expect(app.s3LoggingBucket).toBeDefined(); + expect(app.encryptionKey).toBeDefined(); + expect(app.s3BucketInterface).toBeDefined(); }); test('construct creates default event notification', () => { @@ -254,4 +254,41 @@ test('Construct does not override unencrypted topic when passed in existingTopic template.hasResourceProperties("AWS::SNS::Topic", { TopicName: 'existing-topic-name' }); -}); \ No newline at end of file +}); + +test('Confirm CheckSnsProps is being called', () => { + const stack = new Stack(); + + const topic = new sns.Topic(stack, "existing-topic-obj", { + topicName: 'existing-topic-obj' + }); + + const app = () => { + new S3ToSns(stack, 'test-s3-sns', { + existingTopicObj: topic, + topicProps: { + topicName: 'topic-name' + }, + }); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide topicProps or existingTopicObj, but not both.\n/); +}); + +test('Confirm CheckS3Props is being called', () => { + const stack = new Stack(); + + const app = () => { + new S3ToSns(stack, 'test-s3-sns', { + topicProps: { + topicName: 'topic-name' + }, + bucketProps: {}, + existingBucketObj: new s3.Bucket(stack, 'test-bucket', {}), + }); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide bucketProps or existingBucketObj, but not both.\n/); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/lib/index.ts index cd41a50e0..cebd96705 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/lib/index.ts @@ -139,7 +139,8 @@ export class S3ToSqs extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); + defaults.CheckSqsProps(props); + defaults.CheckS3Props(props); let bucket: s3.Bucket; let enableEncryptionParam = props.enableEncryptionWithCustomerManagedKey; diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.creatingNewQueue.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.creatingNewQueue.expected.json index c839ae628..34cf2729f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.creatingNewQueue.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.creatingNewQueue.expected.json @@ -4,6 +4,7 @@ "ImportedEncryptionKeyBE10B2FC": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -65,8 +66,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.customLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.customLoggingBucket.expected.json index 2406f51ef..a6927de0a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.customLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.customLoggingBucket.expected.json @@ -325,6 +325,7 @@ "tests3sqsEncryptionKeyFD4D5946": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -386,8 +387,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingLoggingBucket.expected.json index 87a76dc7c..3e9c4bdc5 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingLoggingBucket.expected.json @@ -178,18 +178,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -494,6 +494,7 @@ "tests3sqstempEncryptionKey57CC85E2": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -555,8 +556,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" @@ -784,109 +784,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingQueue.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingQueue.expected.json index 80b3fd0ad..cd1ee5d07 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingQueue.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingQueue.expected.json @@ -3,6 +3,7 @@ "EncryptionKey1B843E66": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -64,8 +65,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingS3Bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingS3Bucket.expected.json index 8cf18e55b..c6b3e9b5b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingS3Bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.existingS3Bucket.expected.json @@ -176,18 +176,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -305,6 +305,7 @@ "tests3sqsEncryptionKeyFD4D5946": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -366,8 +367,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" @@ -595,109 +595,6 @@ } } }, - "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - } - }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.noArguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.noArguments.expected.json index 4df7ea0f0..1fe822f96 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.noArguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/integ.noArguments.expected.json @@ -324,6 +324,7 @@ "tests3sqsEncryptionKeyFD4D5946": { "Type": "AWS::KMS::Key", "Properties": { + "EnableKeyRotation": true, "KeyPolicy": { "Statement": [ { @@ -385,8 +386,7 @@ } ], "Version": "2012-10-17" - }, - "EnableKeyRotation": true + } }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/test.s3-sqs.test.ts b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/test.s3-sqs.test.ts index 34521e7ce..3536ea314 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/test.s3-sqs.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-s3-sqs/test/test.s3-sqs.test.ts @@ -20,9 +20,6 @@ import * as s3 from 'aws-cdk-lib/aws-s3'; import { Template } from 'aws-cdk-lib/assertions'; import * as defaults from '@aws-solutions-constructs/core'; -// -------------------------------------------------------------- -// Test the getter methods -// -------------------------------------------------------------- test('Test getter methods', () => { // Initial Setup const stack = new Stack(); @@ -36,16 +33,13 @@ test('Test getter methods', () => { }; const app = new S3ToSqs(stack, 'test-s3-sqs', props); // Assertion 1 - expect(app.sqsQueue !== null); + expect(app.sqsQueue).toBeDefined(); // Assertion 2 - expect(app.deadLetterQueue !== null); + expect(app.deadLetterQueue).toBeDefined(); // Assertion 3 - expect(app.s3Bucket !== null); + expect(app.s3Bucket).toBeDefined(); }); -// -------------------------------------------------------------- -// Test deployment w/ existing queue -// -------------------------------------------------------------- test('Test deployment w/ existing queue', () => { // Stack const stack = new Stack(); @@ -77,9 +71,6 @@ test('Test deployment w/ existing queue', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ existing s3 Bucket -// -------------------------------------------------------------- test('Test deployment w/ existing Bucket', () => { // Stack const stack = new Stack(); @@ -108,9 +99,6 @@ test('Test deployment w/ existing Bucket', () => { }); }); -// -------------------------------------------------------------- -// Pattern deployment w/ bucket block public access override -// -------------------------------------------------------------- test('Pattern deployment w/ bucket versioning turned off', () => { const stack = new Stack(); const props: S3ToSqsProps = { @@ -135,9 +123,6 @@ test('Pattern deployment w/ bucket versioning turned off', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ specific s3 event types -// -------------------------------------------------------------- test('Test deployment w/ s3 event types and filters', () => { // Stack const stack = new Stack(); @@ -187,9 +172,6 @@ test('Test deployment w/ s3 event types and filters', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ SSE encryption enabled using customer managed KMS CMK -// -------------------------------------------------------------- test('Test deployment w/ SSE encryption enabled using customer managed KMS CMK', () => { // Stack const stack = new Stack(); @@ -218,9 +200,6 @@ test('Test deployment w/ SSE encryption enabled using customer managed KMS CMK', }); }); -// -------------------------------------------------------------- -// Test bad call with existingBucket and bucketProps -// -------------------------------------------------------------- test("Test bad call with existingBucket and bucketProps", () => { // Stack const stack = new Stack(); @@ -240,9 +219,6 @@ test("Test bad call with existingBucket and bucketProps", () => { expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); }); -// -------------------------------------------------------------- -// s3 bucket with bucket, loggingBucket, and auto delete objects -// -------------------------------------------------------------- test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { const stack = new Stack(); @@ -272,9 +248,6 @@ test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => { }); }); -// -------------------------------------------------------------- -// s3 bucket with one content bucket and no logging bucket -// -------------------------------------------------------------- test('s3 bucket with one content bucket and no logging bucket', () => { const stack = new Stack(); @@ -382,4 +355,39 @@ test('Queue is encrypted with SQS-managed KMS Key when enable encryption flag is template.hasResourceProperties("AWS::SQS::Queue", { KmsMasterKeyId: "alias/aws/sqs" }); -}); \ No newline at end of file +}); + +test('Confirm CheckSqsProps is called', () => { + // Initial Setup + const stack = new Stack(); + const filter: s3.NotificationKeyFilter = { prefix: 'the/place', suffix: '*.mp3' }; + const props: S3ToSqsProps = { + deployDeadLetterQueue: true, + maxReceiveCount: 0, + s3EventTypes: [s3.EventType.OBJECT_REMOVED], + s3EventFilters: [filter], + queueProps: { + removalPolicy: RemovalPolicy.DESTROY, + }, + existingQueueObj: new sqs.Queue(stack, 'test', {}) + }; + + const app = () => { + new S3ToSqs(stack, 'test-s3-sqs', props); + }; + expect(app).toThrowError("Error - Either provide queueProps or existingQueueObj, but not both.\n"); +}); + +test('Confirm CheckS3Props is being called', () => { + const stack = new Stack(); + + const app = () => { + new S3ToSqs(stack, 'test-s3-sqs', { + bucketProps: {}, + existingBucketObj: new s3.Bucket(stack, 'test-bucket', {}), + }); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide bucketProps or existingBucketObj, but not both.\n/); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/lib/index.ts index cfe47d63c..83fac8004 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/lib/index.ts @@ -106,7 +106,7 @@ export class S3ToStepfunctions extends Construct { // context here rather than assuming the client will set it this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); - defaults.CheckProps(props); + defaults.CheckS3Props(props); let bucket: s3.IBucket; diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.customLoggingBucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.customLoggingBucket.expected.json index 11241541f..39116fa34 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.customLoggingBucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.customLoggingBucket.expected.json @@ -342,12 +342,6 @@ "tests3stepfunctionstests3stepfunctionseventrulestepfunctionconstructStateMachine67197269": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "tests3stepfunctionstests3stepfunctionseventrulestepfunctionconstructStateMachineRoleEAF485A9", - "Arn" - ] - }, "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", "LoggingConfiguration": { "Destinations": [ @@ -363,6 +357,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "tests3stepfunctionstests3stepfunctionseventrulestepfunctionconstructStateMachineRoleEAF485A9", + "Arn" + ] } }, "DependsOn": [ @@ -452,9 +452,8 @@ "tests3stepfunctionstests3stepfunctionseventrulestepfunctionconstructExecutionFailedAlarm9C7AF57A": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -463,6 +462,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -473,9 +473,8 @@ "tests3stepfunctionstests3stepfunctionseventrulestepfunctionconstructExecutionThrottledAlarm99D8FF54": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -484,6 +483,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -494,9 +494,8 @@ "tests3stepfunctionstests3stepfunctionseventrulestepfunctionconstructExecutionAbortedAlarm1689CFA6": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -505,6 +504,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -647,6 +647,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -680,6 +683,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.pre-existing-bucket.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.pre-existing-bucket.expected.json index 75e7f4052..d6d2e344a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.pre-existing-bucket.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.pre-existing-bucket.expected.json @@ -160,18 +160,18 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "350185a1069fa20a23a583e20c77f6844218bd73097902362dc94f1a108f5d89.zip" + "S3Key": "5194f926380567b6fdffc61629afdad2afc818614cb227df45e499c69db163a7.zip" }, "Timeout": 900, "MemorySize": 128, - "Handler": "__entrypoint__.handler", + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", "Arn" ] }, - "Runtime": "nodejs16.x", + "Runtime": "nodejs18.x", "Description": { "Fn::Join": [ "", @@ -424,12 +424,6 @@ "tests3stepfunctionspreexistingbucketconstructtests3stepfunctionspreexistingbucketconstructeventrulestepfunctionconstructStateMachine326BB1C1": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "tests3stepfunctionspreexistingbucketconstructtests3stepfunctionspreexistingbucketconstructeventrulestepfunctionconstructStateMachineRoleE56A7030", - "Arn" - ] - }, "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", "LoggingConfiguration": { "Destinations": [ @@ -445,6 +439,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "tests3stepfunctionspreexistingbucketconstructtests3stepfunctionspreexistingbucketconstructeventrulestepfunctionconstructStateMachineRoleE56A7030", + "Arn" + ] } }, "DependsOn": [ @@ -534,9 +534,8 @@ "tests3stepfunctionspreexistingbucketconstructtests3stepfunctionspreexistingbucketconstructeventrulestepfunctionconstructExecutionFailedAlarmAC11687E": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -545,6 +544,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -555,9 +555,8 @@ "tests3stepfunctionspreexistingbucketconstructtests3stepfunctionspreexistingbucketconstructeventrulestepfunctionconstructExecutionThrottledAlarm630846CA": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -566,6 +565,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -576,9 +576,8 @@ "tests3stepfunctionspreexistingbucketconstructtests3stepfunctionspreexistingbucketconstructeventrulestepfunctionconstructExecutionAbortedAlarmB47B3FC8": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -587,6 +586,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -596,107 +596,6 @@ } }, "Mappings": { - "DefaultCrNodeVersionMap": { - "af-south-1": { - "value": "nodejs16.x" - }, - "ap-east-1": { - "value": "nodejs16.x" - }, - "ap-northeast-1": { - "value": "nodejs16.x" - }, - "ap-northeast-2": { - "value": "nodejs16.x" - }, - "ap-northeast-3": { - "value": "nodejs16.x" - }, - "ap-south-1": { - "value": "nodejs16.x" - }, - "ap-south-2": { - "value": "nodejs16.x" - }, - "ap-southeast-1": { - "value": "nodejs16.x" - }, - "ap-southeast-2": { - "value": "nodejs16.x" - }, - "ap-southeast-3": { - "value": "nodejs16.x" - }, - "ca-central-1": { - "value": "nodejs16.x" - }, - "cn-north-1": { - "value": "nodejs16.x" - }, - "cn-northwest-1": { - "value": "nodejs16.x" - }, - "eu-central-1": { - "value": "nodejs16.x" - }, - "eu-central-2": { - "value": "nodejs16.x" - }, - "eu-north-1": { - "value": "nodejs16.x" - }, - "eu-south-1": { - "value": "nodejs16.x" - }, - "eu-south-2": { - "value": "nodejs16.x" - }, - "eu-west-1": { - "value": "nodejs16.x" - }, - "eu-west-2": { - "value": "nodejs16.x" - }, - "eu-west-3": { - "value": "nodejs16.x" - }, - "me-central-1": { - "value": "nodejs16.x" - }, - "me-south-1": { - "value": "nodejs16.x" - }, - "sa-east-1": { - "value": "nodejs16.x" - }, - "us-east-1": { - "value": "nodejs16.x" - }, - "us-east-2": { - "value": "nodejs16.x" - }, - "us-gov-east-1": { - "value": "nodejs16.x" - }, - "us-gov-west-1": { - "value": "nodejs16.x" - }, - "us-iso-east-1": { - "value": "nodejs14.x" - }, - "us-iso-west-1": { - "value": "nodejs14.x" - }, - "us-isob-east-1": { - "value": "nodejs14.x" - }, - "us-west-1": { - "value": "nodejs16.x" - }, - "us-west-2": { - "value": "nodejs16.x" - } - }, "ServiceprincipalMap": { "af-south-1": { "states": "states.af-south-1.amazonaws.com" @@ -728,6 +627,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -761,6 +663,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.s3-stepfunctions-no-argument.expected.json b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.s3-stepfunctions-no-argument.expected.json index c2d6d28e0..a0a1c4e60 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.s3-stepfunctions-no-argument.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/integ.s3-stepfunctions-no-argument.expected.json @@ -248,12 +248,6 @@ "tests3stepfunctionsconstructtests3stepfunctionsconstructeventrulestepfunctionconstructStateMachineCC5D0DD7": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "tests3stepfunctionsconstructtests3stepfunctionsconstructeventrulestepfunctionconstructStateMachineRole29FAFE92", - "Arn" - ] - }, "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", "LoggingConfiguration": { "Destinations": [ @@ -269,6 +263,12 @@ } ], "Level": "ERROR" + }, + "RoleArn": { + "Fn::GetAtt": [ + "tests3stepfunctionsconstructtests3stepfunctionsconstructeventrulestepfunctionconstructStateMachineRole29FAFE92", + "Arn" + ] } }, "DependsOn": [ @@ -358,9 +358,8 @@ "tests3stepfunctionsconstructtests3stepfunctionsconstructeventrulestepfunctionconstructExecutionFailedAlarm511B7A93": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -369,6 +368,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsFailed", "Namespace": "AWS/States", "Period": 300, @@ -379,9 +379,8 @@ "tests3stepfunctionsconstructtests3stepfunctionsconstructeventrulestepfunctionconstructExecutionThrottledAlarmF97ADDFF": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -390,6 +389,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionThrottled", "Namespace": "AWS/States", "Period": 300, @@ -400,9 +400,8 @@ "tests3stepfunctionsconstructtests3stepfunctionsconstructeventrulestepfunctionconstructExecutionAbortedAlarm8B04A073": { "Type": "AWS::CloudWatch::Alarm", "Properties": { - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 1, "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { "Name": "StateMachineArn", @@ -411,6 +410,7 @@ } } ], + "EvaluationPeriods": 1, "MetricName": "ExecutionsAborted", "Namespace": "AWS/States", "Period": 300, @@ -553,6 +553,9 @@ "ap-southeast-3": { "states": "states.ap-southeast-3.amazonaws.com" }, + "ap-southeast-4": { + "states": "states.ap-southeast-4.amazonaws.com" + }, "ca-central-1": { "states": "states.ca-central-1.amazonaws.com" }, @@ -586,6 +589,9 @@ "eu-west-3": { "states": "states.eu-west-3.amazonaws.com" }, + "il-central-1": { + "states": "states.il-central-1.amazonaws.com" + }, "me-central-1": { "states": "states.me-central-1.amazonaws.com" }, diff --git a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/s3-stepfunctions.test.ts b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/s3-stepfunctions.test.ts index 927f09213..8a09b0be8 100644 --- a/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/s3-stepfunctions.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-s3-stepfunctions/test/s3-stepfunctions.test.ts @@ -98,17 +98,17 @@ test('check properties', () => { const construct: S3ToStepfunctions = deployNewStateMachine(stack); - expect(construct.stateMachine !== null); - expect(construct.s3Bucket !== null); - expect(construct.cloudwatchAlarms !== null); - expect(construct.stateMachineLogGroup !== null); - expect(construct.s3LoggingBucket !== null); + expect(construct.stateMachine).toBeDefined(); + expect(construct.s3Bucket).toBeDefined(); + expect(construct.cloudwatchAlarms).toBeDefined(); + expect(construct.stateMachineLogGroup).toBeDefined(); + expect(construct.s3LoggingBucket).toBeDefined(); }); // -------------------------------------------------------------- // Test bad call with existingBucket and bucketProps // -------------------------------------------------------------- -test("Test bad call with existingBucket and bucketProps", () => { +test("Confirm that CheckS3Props is getting called", () => { // Stack const stack = new cdk.Stack(); diff --git a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/lib/index.ts index 86ff8ea10..f419afeed 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/lib/index.ts @@ -85,7 +85,8 @@ export class SnsToLambda extends Construct { */ constructor(scope: Construct, id: string, props: SnsToLambdaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckSnsProps(props); + defaults.CheckLambdaProps(props); // Setup the Lambda function this.lambdaFunction = defaults.buildLambdaFunction(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/integ.no-arguments.expected.json index d96ac9479..0eea518ec 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/integ.no-arguments.expected.json @@ -99,18 +99,18 @@ }, "S3Key": "0c3255e93ffe7a906c7422e9f0e9cc4c7fd86ee996ee3bb302e2f134b38463c8.zip" }, - "Role": { - "Fn::GetAtt": [ - "testsnslambdaLambdaFunctionServiceRole23794781", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testsnslambdaLambdaFunctionServiceRole23794781", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -158,15 +158,15 @@ "testsnslambdaLambdaFunctionSnsTopic9C14F333": { "Type": "AWS::SNS::Subscription", "Properties": { - "Protocol": "lambda", - "TopicArn": { - "Ref": "testsnslambdaSnsTopic52CA159E" - }, "Endpoint": { "Fn::GetAtt": [ "testsnslambdaLambdaFunctionEE9A249B", "Arn" ] + }, + "Protocol": "lambda", + "TopicArn": { + "Ref": "testsnslambdaSnsTopic52CA159E" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/sns-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/sns-lambda.test.ts index 1e4f0b71c..ee8ba5c7c 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/sns-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/sns-lambda.test.ts @@ -35,8 +35,8 @@ test('check properties', () => { const construct: SnsToLambda = deployNewFunc(stack); - expect(construct.lambdaFunction !== null); - expect(construct.snsTopic !== null); + expect(construct.lambdaFunction).toBeDefined(); + expect(construct.snsTopic).toBeDefined(); }); test('override topicProps', () => { @@ -137,7 +137,7 @@ test('Topic is encrypted with imported CMK when set on topicProps.masterKey prop }); }); -test('Topic is encrypted with provided encrytionKeyProps', () => { +test('Topic is encrypted with provided encryptionKeyProps', () => { const stack = new cdk.Stack(); const props: SnsToLambdaProps = { @@ -236,3 +236,54 @@ test('Topic is encrypted with customer managed KMS Key when enable encryption fl }, }); }); + +test('Confirm CheckSnsProps is getting called', () => { + const stack = new cdk.Stack(); + + const topic = new sns.Topic(stack, 'MyTopic', { + topicName: "custom-topic" + }); + + const props: SnsToLambdaProps = { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, + existingTopicObj: topic, + topicProps: { + topicName: 'topic-name' + } + }; + + const app = () => { + new SnsToLambda(stack, 'test-sns-lambda', props); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide topicProps or existingTopicObj, but not both.\n/); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new cdk.Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: SnsToLambdaProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new SnsToLambda(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-sns-sqs/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-sns-sqs/lib/index.ts index 142c719e4..155ae4bf7 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sns-sqs/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sns-sqs/lib/index.ts @@ -115,7 +115,8 @@ export class SnsToSqs extends Construct { */ constructor(scope: Construct, id: string, props: SnsToSqsProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckSnsProps(props); + defaults.CheckSqsProps(props); // Setup the dead letter queue, if applicable this.deadLetterQueue = defaults.buildDeadLetterQueue(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-sns-sqs/test/sns-sqs.test.ts b/source/patterns/@aws-solutions-constructs/aws-sns-sqs/test/sns-sqs.test.ts index 86278f8bd..320fac669 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sns-sqs/test/sns-sqs.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sns-sqs/test/sns-sqs.test.ts @@ -12,17 +12,13 @@ */ // Imports -import { Stack } from "aws-cdk-lib"; +import { Stack, RemovalPolicy } from "aws-cdk-lib"; import { SnsToSqs, SnsToSqsProps } from "../lib"; import * as sqs from 'aws-cdk-lib/aws-sqs'; import * as sns from 'aws-cdk-lib/aws-sns'; import * as kms from 'aws-cdk-lib/aws-kms'; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Pattern deployment with new Topic, new Queue and -// default properties -// -------------------------------------------------------------- test('Pattern deployment w/ new Topic, new Queue and default props', () => { // Initial Setup const stack = new Stack(); @@ -65,10 +61,6 @@ test('Pattern deployment w/ new Topic, new Queue and default props', () => { }); }); -// -------------------------------------------------------------- -// Pattern deployment with new Topic, new Queue, and -// overridden properties -// -------------------------------------------------------------- test('Pattern deployment w/ new topic, new queue, and overridden props', () => { // Initial Setup const stack = new Stack(); @@ -110,9 +102,6 @@ test('Pattern deployment w/ new topic, new queue, and overridden props', () => { }); }); -// -------------------------------------------------------------- -// Test the getter methods -// -------------------------------------------------------------- test('Test getter methods', () => { // Initial Setup const stack = new Stack(); @@ -123,18 +112,15 @@ test('Test getter methods', () => { }; const app = new SnsToSqs(stack, 'test-sns-sqs', props); // Assertion 1 - expect(app.snsTopic !== null); + expect(app.snsTopic).toBeDefined(); // Assertion 2 - expect(app.encryptionKey !== null); + expect(app.encryptionKey).toBeDefined(); // Assertion 3 - expect(app.sqsQueue !== null); + expect(app.sqsQueue).toBeDefined(); // Assertion 4 - expect(app.deadLetterQueue !== null); + expect(app.deadLetterQueue).toBeDefined(); }); -// -------------------------------------------------------------- -// Test deployment with existing queue, and topic -// -------------------------------------------------------------- test('Test deployment w/ existing queue, and topic', () => { // Stack const stack = new Stack(); @@ -150,7 +136,7 @@ test('Test deployment w/ existing queue, and topic', () => { existingQueueObj: queue }); // Assertion 2 - expect(app.snsTopic !== null); + expect(app.snsTopic).toBeDefined(); // Assertion 3 const template = Template.fromStack(stack); template.hasResourceProperties("AWS::SNS::Topic", { @@ -162,9 +148,6 @@ test('Test deployment w/ existing queue, and topic', () => { }); }); -// -------------------------------------------------------------- -// Test deployment with imported encryption key -// -------------------------------------------------------------- test('Test deployment with imported encryption key', () => { // Stack const stack = new Stack(); @@ -193,9 +176,6 @@ test('Test deployment with imported encryption key', () => { }); }); -// -------------------------------------------------------------- -// Test deployment with SNS managed KMS key -// -------------------------------------------------------------- test('Test deployment with SNS managed KMS key', () => { // Stack const stack = new Stack(); @@ -244,9 +224,6 @@ test('Test deployment with SNS managed KMS key', () => { }); }); -// -------------------------------------------------------------- -// Test deployment with CMK encrypted SNS Topic -// -------------------------------------------------------------- test('Test deployment with CMK encrypted SNS Topic', () => { // Stack const stack = new Stack(); @@ -269,9 +246,6 @@ test('Test deployment with CMK encrypted SNS Topic', () => { }); }); -// -------------------------------------------------------------- -// Pattern deployment with existing Topic and FIFO queues -// -------------------------------------------------------------- test('Pattern deployment w/ existing topic and FIFO queue', () => { // Initial Setup const stack = new Stack(); @@ -314,9 +288,6 @@ test('Pattern deployment w/ existing topic and FIFO queue', () => { }); }); -// -------------------------------------------------------------- -// Pattern deployment with existing Topic and Standard queues -// -------------------------------------------------------------- test('Pattern deployment w/ existing topic and Standard queue', () => { // Initial Setup const stack = new Stack(); @@ -499,4 +470,46 @@ test('Construct does not override unencrypted topic when passed in existingTopic expect(testConstruct.snsTopic).toBeDefined(); expect(testConstruct.encryptionKey).not.toBeDefined(); +}); + +test('Confirm that CheckSnsProps is called', () => { + // Stack + const stack = new Stack(); + // Helper declaration + const topic = new sns.Topic(stack, "existing-topic-obj", { + topicName: 'existing-topic-obj' + }); + const queue = new sqs.Queue(stack, 'existing-queue-obj', { + queueName: 'existing-queue-obj' + }); + + const app = () => { + new SnsToSqs(stack, 'sns-to-sqs-stack', { + existingTopicObj: topic, + topicProps: { + topicName: 'topic-name' + }, + existingQueueObj: queue + }); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide topicProps or existingTopicObj, but not both.\n/); +}); + +test('Confirm that CheckSqsProps is called', () => { + // Stack + const stack = new Stack(); + + const app = () => { + new SnsToSqs(stack, 'sns-to-sqs-stack', { + queueProps: { + removalPolicy: RemovalPolicy.DESTROY, + }, + existingQueueObj: new sqs.Queue(stack, 'test', {}) + }); + }; + + // Assertion + expect(app).toThrowError("Error - Either provide queueProps or existingQueueObj, but not both.\n"); }); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/lib/index.ts index 9d8093255..880b82c6a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/lib/index.ts @@ -111,7 +111,8 @@ export class SqsToLambda extends Construct { */ constructor(scope: Construct, id: string, props: SqsToLambdaProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckSqsProps(props); + defaults.CheckLambdaProps(props); // Setup the Lambda function this.lambdaFunction = defaults.buildLambdaFunction(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.deployFifoQueue.expected.json b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.deployFifoQueue.expected.json index b74d97aac..ffc3c0676 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.deployFifoQueue.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.deployFifoQueue.expected.json @@ -115,18 +115,18 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "testsqslambdafifoLambdaFunctionServiceRole74463822", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testsqslambdafifoLambdaFunctionServiceRole74463822", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -158,14 +158,14 @@ "testsqslambdafifoLambdaFunctionSqsEventSourcedeployFifoQueuetestsqslambdafifoqueue90CAB7D6AF891A0A": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testsqslambdafifoLambdaFunction0F3AE705" - }, "EventSourceArn": { "Fn::GetAtt": [ "testsqslambdafifoqueue45DD24D7", "Arn" ] + }, + "FunctionName": { + "Ref": "testsqslambdafifoLambdaFunction0F3AE705" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.deployFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.deployFunction.expected.json index 76909919a..dcc3a8016 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.deployFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.deployFunction.expected.json @@ -115,18 +115,18 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "testsqslambdaLambdaFunctionServiceRoleF623B438", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "testsqslambdaLambdaFunctionServiceRoleF623B438", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -158,14 +158,14 @@ "testsqslambdaLambdaFunctionSqsEventSourcedeployFunctiontestsqslambdaqueueC37BE757C660F26A": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "testsqslambdaLambdaFunction58720146" - }, "EventSourceArn": { "Fn::GetAtt": [ "testsqslambdaqueue601203B8", "Arn" ] + }, + "FunctionName": { + "Ref": "testsqslambdaLambdaFunction58720146" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.existingFunction.expected.json b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.existingFunction.expected.json index b573f41ee..8f53e1154 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.existingFunction.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/integ.existingFunction.expected.json @@ -115,18 +115,18 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, - "Role": { - "Fn::GetAtt": [ - "LambdaFunctionServiceRole0C4CDE0B", - "Arn" - ] - }, "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" } }, "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaFunctionServiceRole0C4CDE0B", + "Arn" + ] + }, "Runtime": "nodejs16.x", "TracingConfig": { "Mode": "Active" @@ -158,14 +158,14 @@ "LambdaFunctionSqsEventSourceexistingFunctiontestsqslambdaqueue15248716FB07DA49": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { - "FunctionName": { - "Ref": "LambdaFunctionBF21E41F" - }, "EventSourceArn": { "Fn::GetAtt": [ "testsqslambdaqueue601203B8", "Arn" ] + }, + "FunctionName": { + "Ref": "LambdaFunctionBF21E41F" } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/test.sqs-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/test.sqs-lambda.test.ts index efbc2b91f..20f88fe91 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/test.sqs-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sqs-lambda/test/test.sqs-lambda.test.ts @@ -15,13 +15,10 @@ import { Stack } from "aws-cdk-lib"; import { SqsToLambda, SqsToLambdaProps } from "../lib"; import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as sqs from 'aws-cdk-lib/aws-sqs'; import { Template } from 'aws-cdk-lib/assertions'; import * as kms from 'aws-cdk-lib/aws-kms'; -// -------------------------------------------------------------- -// Pattern deployment w/ new Lambda function and -// overridden properties -// -------------------------------------------------------------- test('Pattern deployment w/ new Lambda function and overridden props', () => { // Initial Setup const stack = new Stack(); @@ -55,9 +52,6 @@ test('Pattern deployment w/ new Lambda function and overridden props', () => { }); }); -// -------------------------------------------------------------- -// Test the getter methods -// -------------------------------------------------------------- test('Test getter methods', () => { // Initial Setup const stack = new Stack(); @@ -71,13 +65,13 @@ test('Test getter methods', () => { maxReceiveCount: 0, queueProps: {} }; - const app = new SqsToLambda(stack, 'test-apigateway-lambda', props); + const app = new SqsToLambda(stack, 'sqs-lambda', props); // Assertion 1 - expect(app.lambdaFunction !== null); + expect(app.lambdaFunction).toBeDefined(); // Assertion 2 - expect(app.sqsQueue !== null); + expect(app.sqsQueue).toBeDefined(); // Assertion 3 - expect(app.deadLetterQueue !== null); + expect(app.deadLetterQueue).toBeDefined(); }); // -------------------------------------------------------------- @@ -98,10 +92,6 @@ test('Test error handling for existing Lambda function', () => { }).toThrowError(); }); -// -------------------------------------------------------------- -// Test error handling for new Lambda function -// w/o required properties -// -------------------------------------------------------------- test('Test error handling for new Lambda function w/o required properties', () => { // Initial Setup const stack = new Stack(); @@ -116,9 +106,6 @@ test('Test error handling for new Lambda function w/o required properties', () = }).toThrowError(); }); -// -------------------------------------------------------------- -// Pattern deployment w/ batch size -// -------------------------------------------------------------- test('Pattern deployment w/ batch size', () => { const stack = new Stack(); const props: SqsToLambdaProps = { @@ -195,7 +182,7 @@ test('Queue is encrypted with imported CMK when set on queueProps.encryptionMast }); }); -test('Queue is encrypted with provided encrytionKeyProps', () => { +test('Queue is encrypted with provided encryptionKeyProps', () => { const stack = new Stack(); new SqsToLambda(stack, 'test-construct', { @@ -277,4 +264,49 @@ test('Queue is encrypted with customer managed KMS Key when enable encryption fl ] }, }); -}); \ No newline at end of file +}); + +test('Confirm CheckSqsProps is called', () => { + // Initial Setup + const stack = new Stack(); + const props: SqsToLambdaProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`) + }, + deployDeadLetterQueue: true, + maxReceiveCount: 0, + queueProps: {}, + existingQueueObj: new sqs.Queue(stack, 'test', {}) + }; + + const app = () => { + new SqsToLambda(stack, 'test-apigateway-lambda', props); + }; + expect(app).toThrowError("Error - Either provide queueProps or existingQueueObj, but not both.\n"); +}); + +test('Confirm call to CheckLambdaProps', () => { + // Initial Setup + const stack = new Stack(); + const lambdaFunction = new lambda.Function(stack, 'a-function', { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }); + + const props: SqsToLambdaProps = { + lambdaFunctionProps: { + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + }, + existingLambdaObj: lambdaFunction, + }; + const app = () => { + new SqsToLambda(stack, 'test-construct', props); + }; + // Assertion + expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/lib/index.ts index 55d74c8d1..ca3c4ae00 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/lib/index.ts @@ -53,7 +53,8 @@ export class WafwebaclToAlb extends Construct { */ constructor(scope: Construct, id: string, props: WafwebaclToAlbProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckWafWebAclProps(props); + // CheckAlbProps() not called because this only accepts and existing Load Balancer // Build the Web ACL this.webacl = defaults.buildWebacl(this, 'REGIONAL', { @@ -67,7 +68,8 @@ export class WafwebaclToAlb extends Construct { }; // Setup the Web ACL Association - new waf.CfnWebACLAssociation(scope, `${id}-WebACLAssociation`, aclProps); + // Before turning off SonarQube for the line, reduce the line to it's minimum + new waf.CfnWebACLAssociation(scope, `${id}-WebACLAssociation`, aclProps); // NOSONAR this.loadBalancer = props.existingLoadBalancerObj; } diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/test/integ.no-arguments.expected.json index 2271e0bbb..575dddfb3 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/test/integ.no-arguments.expected.json @@ -18,9 +18,6 @@ "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.0.0/19", "MapPublicIpOnLaunch": true, @@ -37,7 +34,10 @@ "Key": "Name", "Value": "no-arguments/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -53,15 +53,15 @@ "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-arguments/Vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet1RouteTableAssociation97140677": { @@ -78,12 +78,12 @@ "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet1RouteTable6C95E38E" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" } }, "DependsOn": [ @@ -105,15 +105,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "Tags": [ { "Key": "Name", @@ -129,9 +129,6 @@ "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.32.0/19", "MapPublicIpOnLaunch": true, @@ -148,7 +145,10 @@ "Key": "Name", "Value": "no-arguments/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -164,15 +164,15 @@ "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-arguments/Vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet2RouteTableAssociationDD5762D8": { @@ -189,12 +189,12 @@ "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet2RouteTable94F7E489" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" } }, "DependsOn": [ @@ -216,15 +216,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "Tags": [ { "Key": "Name", @@ -240,9 +240,6 @@ "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.64.0/19", "MapPublicIpOnLaunch": true, @@ -259,7 +256,10 @@ "Key": "Name", "Value": "no-arguments/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } }, "Metadata": { "cfn_nag": { @@ -275,15 +275,15 @@ "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-arguments/Vpc/PublicSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { @@ -300,12 +300,12 @@ "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPublicSubnet3RouteTable93458DBB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" } }, "DependsOn": [ @@ -327,15 +327,15 @@ "VpcPublicSubnet3NATGateway7640CD1D": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "VpcPublicSubnet3SubnetBE12F0B6" - }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet3EIP3A666A23", "AllocationId" ] }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, "Tags": [ { "Key": "Name", @@ -351,9 +351,6 @@ "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1a", "CidrBlock": "172.168.96.0/19", "MapPublicIpOnLaunch": false, @@ -370,21 +367,24 @@ "Key": "Name", "Value": "no-arguments/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-arguments/Vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { @@ -401,21 +401,18 @@ "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" } } }, "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1b", "CidrBlock": "172.168.128.0/19", "MapPublicIpOnLaunch": false, @@ -432,21 +429,24 @@ "Key": "Name", "Value": "no-arguments/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-arguments/Vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { @@ -463,21 +463,18 @@ "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet2RouteTableA678073B" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" } } }, "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "AvailabilityZone": "test-region-1c", "CidrBlock": "172.168.160.0/19", "MapPublicIpOnLaunch": false, @@ -494,21 +491,24 @@ "Key": "Name", "Value": "no-arguments/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "Tags": [ { "Key": "Name", "Value": "no-arguments/Vpc/PrivateSubnet3" } - ] + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } } }, "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { @@ -525,12 +525,12 @@ "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "VpcPrivateSubnet3RouteTableD98824C7" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" } } }, @@ -548,11 +548,11 @@ "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "Vpc8378EB38" - }, "InternetGatewayId": { "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" } } }, @@ -574,7 +574,7 @@ "Tags": [ { "Key": "Name", - "Value": "no-arguments/Vpc" + "Value": "no-arguments/Vpc/FlowLog" } ] } @@ -626,7 +626,7 @@ "Tags": [ { "Key": "Name", - "Value": "no-arguments/Vpc" + "Value": "no-arguments/Vpc/FlowLog" } ] }, @@ -646,11 +646,6 @@ "VpcFlowLog8FF33A73": { "Type": "AWS::EC2::FlowLog", "Properties": { - "ResourceId": { - "Ref": "Vpc8378EB38" - }, - "ResourceType": "VPC", - "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "VpcFlowLogIAMRole6A475D41", @@ -661,12 +656,17 @@ "LogGroupName": { "Ref": "VpcFlowLogLogGroup7B5C56B9" }, + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", "Tags": [ { "Key": "Name", - "Value": "no-arguments/Vpc" + "Value": "no-arguments/Vpc/FlowLog" } - ] + ], + "TrafficType": "ALL" } }, "newlbF396DAF2": { @@ -745,12 +745,6 @@ "DefaultAction": { "Allow": {} }, - "Scope": "REGIONAL", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": true, - "MetricName": "webACL", - "SampledRequestsEnabled": true - }, "Rules": [ { "Name": "AWS-AWSManagedRulesBotControlRuleSet", @@ -878,7 +872,13 @@ "SampledRequestsEnabled": true } } - ] + ], + "Scope": "REGIONAL", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": true, + "MetricName": "webACL", + "SampledRequestsEnabled": true + } } }, "testwafwebaclalbWebACLAssociation": { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/test/test.wafwebacl-alb.test.ts b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/test/test.wafwebacl-alb.test.ts index a8941e2ae..0c9c51a35 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/test/test.wafwebacl-alb.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-alb/test/test.wafwebacl-alb.test.ts @@ -38,10 +38,7 @@ function deployConstruct(stack: cdk.Stack, webaclProps?: waf.CfnWebACLProps, exi }); } -// -------------------------------------------------------------- -// Test error handling for existing WAF web ACL and user provided web ACL props -// -------------------------------------------------------------- -test('Test error handling for existing WAF web ACL and user provider web ACL props', () => { +test('Confirm CheckWafWebAclProps is called', () => { const stack = new cdk.Stack(); const props: waf.CfnWebACLProps = { defaultAction: { @@ -64,7 +61,7 @@ test('Test error handling for existing WAF web ACL and user provider web ACL pro existingWebaclObj: wafAcl, webaclProps: props }); - }).toThrowError(); + }).toThrowError('Error - Either provide existingWebaclObj or webaclProps, but not both.\n'); }); // -------------------------------------------------------------- @@ -74,8 +71,8 @@ test('Test default deployment', () => { const stack = new cdk.Stack(); const construct = deployConstruct(stack); - expect(construct.webacl !== null); - expect(construct.loadBalancer !== null); + expect(construct.webacl).toBeDefined(); + expect(construct.loadBalancer).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::WAFv2::WebACL", { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/lib/index.ts index fd7f4dae5..c7d3130ed 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/lib/index.ts @@ -54,7 +54,7 @@ export class WafwebaclToApiGateway extends Construct { */ constructor(scope: Construct, id: string, props: WafwebaclToApiGatewayProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckWafWebAclProps(props); // Build the Web ACL this.webacl = defaults.buildWebacl(this, 'REGIONAL', { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.existing-waf-to-multiple-gateways.expected.json b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.existing-waf-to-multiple-gateways.expected.json index a8c3a785d..f2926a264 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.existing-waf-to-multiple-gateways.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.existing-waf-to-multiple-gateways.expected.json @@ -40,13 +40,13 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, + "Handler": ".handler", "Role": { "Fn::GetAtt": [ "testOneFunctionServiceRole3F9CD9E7", "Arn" ] }, - "Handler": ".handler", "Runtime": "nodejs16.x" }, "DependsOn": [ @@ -129,10 +129,10 @@ "testOneApiDeploymentEF63BD86e15daf42da17689cb6d56b07d074b512": { "Type": "AWS::ApiGateway::Deployment", "Properties": { + "Description": "Automatically created by the RestApi construct", "RestApiId": { "Ref": "testOneApi71064556" - }, - "Description": "Automatically created by the RestApi construct" + } }, "DependsOn": [ "testOneApiproxyANY7F46A6A5", @@ -153,12 +153,12 @@ "testOneApiDeploymentStageprod5B67F2DF": { "Type": "AWS::ApiGateway::Stage", "Properties": { - "RestApiId": { - "Ref": "testOneApi71064556" - }, "DeploymentId": { "Ref": "testOneApiDeploymentEF63BD86e15daf42da17689cb6d56b07d074b512" }, + "RestApiId": { + "Ref": "testOneApi71064556" + }, "StageName": "prod" }, "DependsOn": [ @@ -275,14 +275,8 @@ "testOneApiproxyANY7F46A6A5": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Ref": "testOneApiproxyC9BD4274" - }, - "RestApiId": { - "Ref": "testOneApi71064556" - }, "AuthorizationType": "NONE", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -309,6 +303,12 @@ ] ] } + }, + "ResourceId": { + "Ref": "testOneApiproxyC9BD4274" + }, + "RestApiId": { + "Ref": "testOneApi71064556" } }, "Metadata": { @@ -403,17 +403,8 @@ "testOneApiANY899DD2DA": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Fn::GetAtt": [ - "testOneApi71064556", - "RootResourceId" - ] - }, - "RestApiId": { - "Ref": "testOneApi71064556" - }, "AuthorizationType": "NONE", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -440,6 +431,15 @@ ] ] } + }, + "ResourceId": { + "Fn::GetAtt": [ + "testOneApi71064556", + "RootResourceId" + ] + }, + "RestApiId": { + "Ref": "testOneApi71064556" } }, "Metadata": { @@ -493,13 +493,13 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, + "Handler": ".handler", "Role": { "Fn::GetAtt": [ "testTwoFunctionServiceRoleF678C905", "Arn" ] }, - "Handler": ".handler", "Runtime": "nodejs16.x" }, "DependsOn": [ @@ -582,10 +582,10 @@ "testTwoApiDeployment4EDBF4DF26b103f50979cda2b3c8314c6d694485": { "Type": "AWS::ApiGateway::Deployment", "Properties": { + "Description": "Automatically created by the RestApi construct", "RestApiId": { "Ref": "testTwoApi17A08EF5" - }, - "Description": "Automatically created by the RestApi construct" + } }, "DependsOn": [ "testTwoApiproxyANY63FFF74A", @@ -606,12 +606,12 @@ "testTwoApiDeploymentStageprod8DB1EDB4": { "Type": "AWS::ApiGateway::Stage", "Properties": { - "RestApiId": { - "Ref": "testTwoApi17A08EF5" - }, "DeploymentId": { "Ref": "testTwoApiDeployment4EDBF4DF26b103f50979cda2b3c8314c6d694485" }, + "RestApiId": { + "Ref": "testTwoApi17A08EF5" + }, "StageName": "prod" }, "DependsOn": [ @@ -728,14 +728,8 @@ "testTwoApiproxyANY63FFF74A": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Ref": "testTwoApiproxy2575DCE3" - }, - "RestApiId": { - "Ref": "testTwoApi17A08EF5" - }, "AuthorizationType": "NONE", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -762,6 +756,12 @@ ] ] } + }, + "ResourceId": { + "Ref": "testTwoApiproxy2575DCE3" + }, + "RestApiId": { + "Ref": "testTwoApi17A08EF5" } }, "Metadata": { @@ -856,17 +856,8 @@ "testTwoApiANY91121C6F": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Fn::GetAtt": [ - "testTwoApi17A08EF5", - "RootResourceId" - ] - }, - "RestApiId": { - "Ref": "testTwoApi17A08EF5" - }, "AuthorizationType": "NONE", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -893,6 +884,15 @@ ] ] } + }, + "ResourceId": { + "Fn::GetAtt": [ + "testTwoApi17A08EF5", + "RootResourceId" + ] + }, + "RestApiId": { + "Ref": "testTwoApi17A08EF5" } }, "Metadata": { @@ -912,12 +912,6 @@ "DefaultAction": { "Allow": {} }, - "Scope": "REGIONAL", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": true, - "MetricName": "webACL", - "SampledRequestsEnabled": true - }, "Rules": [ { "Name": "AWS-AWSManagedRulesBotControlRuleSet", @@ -1045,7 +1039,13 @@ "SampledRequestsEnabled": true } } - ] + ], + "Scope": "REGIONAL", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": true, + "MetricName": "webACL", + "SampledRequestsEnabled": true + } } }, "firstconstructWebACLAssociation": { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.no-arguments.expected.json index 0f7c7a7ec..7828ece80 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.no-arguments.expected.json @@ -40,13 +40,13 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, + "Handler": ".handler", "Role": { "Fn::GetAtt": [ "testFunctionServiceRoleFEC29B6F", "Arn" ] }, - "Handler": ".handler", "Runtime": "nodejs16.x" }, "DependsOn": [ @@ -129,10 +129,10 @@ "testApiDeployment3727A0B98616f677c89f00f84016798f65d107c0": { "Type": "AWS::ApiGateway::Deployment", "Properties": { + "Description": "Automatically created by the RestApi construct", "RestApiId": { "Ref": "testApiD6ECAB50" - }, - "Description": "Automatically created by the RestApi construct" + } }, "DependsOn": [ "testApiproxyANYC53F2608", @@ -153,12 +153,12 @@ "testApiDeploymentStageprodCE051BE8": { "Type": "AWS::ApiGateway::Stage", "Properties": { - "RestApiId": { - "Ref": "testApiD6ECAB50" - }, "DeploymentId": { "Ref": "testApiDeployment3727A0B98616f677c89f00f84016798f65d107c0" }, + "RestApiId": { + "Ref": "testApiD6ECAB50" + }, "StageName": "prod" }, "DependsOn": [ @@ -275,14 +275,8 @@ "testApiproxyANYC53F2608": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Ref": "testApiproxyA0E5503A" - }, - "RestApiId": { - "Ref": "testApiD6ECAB50" - }, "AuthorizationType": "NONE", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -309,6 +303,12 @@ ] ] } + }, + "ResourceId": { + "Ref": "testApiproxyA0E5503A" + }, + "RestApiId": { + "Ref": "testApiD6ECAB50" } }, "Metadata": { @@ -403,17 +403,8 @@ "testApiANYDC600770": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Fn::GetAtt": [ - "testApiD6ECAB50", - "RootResourceId" - ] - }, - "RestApiId": { - "Ref": "testApiD6ECAB50" - }, "AuthorizationType": "NONE", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -440,6 +431,15 @@ ] ] } + }, + "ResourceId": { + "Fn::GetAtt": [ + "testApiD6ECAB50", + "RootResourceId" + ] + }, + "RestApiId": { + "Ref": "testApiD6ECAB50" } }, "Metadata": { @@ -459,12 +459,6 @@ "DefaultAction": { "Allow": {} }, - "Scope": "REGIONAL", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": true, - "MetricName": "webACL", - "SampledRequestsEnabled": true - }, "Rules": [ { "Name": "AWS-AWSManagedRulesBotControlRuleSet", @@ -592,7 +586,13 @@ "SampledRequestsEnabled": true } } - ] + ], + "Scope": "REGIONAL", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": true, + "MetricName": "webACL", + "SampledRequestsEnabled": true + } } }, "testwafwebaclapigatewaylambdaWebACLAssociation": { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.partial-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.partial-arguments.expected.json index b48ef6055..2bb675390 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.partial-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/integ.partial-arguments.expected.json @@ -40,13 +40,13 @@ }, "S3Key": "0904d3723480fed2daf7885caa427b930881caae6879d1e6b0d395020173ef6f.zip" }, + "Handler": ".handler", "Role": { "Fn::GetAtt": [ "testFunctionServiceRoleFEC29B6F", "Arn" ] }, - "Handler": ".handler", "Runtime": "nodejs16.x" }, "DependsOn": [ @@ -129,10 +129,10 @@ "testApiDeployment3727A0B98616f677c89f00f84016798f65d107c0": { "Type": "AWS::ApiGateway::Deployment", "Properties": { + "Description": "Automatically created by the RestApi construct", "RestApiId": { "Ref": "testApiD6ECAB50" - }, - "Description": "Automatically created by the RestApi construct" + } }, "DependsOn": [ "testApiproxyANYC53F2608", @@ -153,12 +153,12 @@ "testApiDeploymentStageprodCE051BE8": { "Type": "AWS::ApiGateway::Stage", "Properties": { - "RestApiId": { - "Ref": "testApiD6ECAB50" - }, "DeploymentId": { "Ref": "testApiDeployment3727A0B98616f677c89f00f84016798f65d107c0" }, + "RestApiId": { + "Ref": "testApiD6ECAB50" + }, "StageName": "prod" }, "DependsOn": [ @@ -275,14 +275,8 @@ "testApiproxyANYC53F2608": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Ref": "testApiproxyA0E5503A" - }, - "RestApiId": { - "Ref": "testApiD6ECAB50" - }, "AuthorizationType": "NONE", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -309,6 +303,12 @@ ] ] } + }, + "ResourceId": { + "Ref": "testApiproxyA0E5503A" + }, + "RestApiId": { + "Ref": "testApiD6ECAB50" } }, "Metadata": { @@ -403,17 +403,8 @@ "testApiANYDC600770": { "Type": "AWS::ApiGateway::Method", "Properties": { - "HttpMethod": "ANY", - "ResourceId": { - "Fn::GetAtt": [ - "testApiD6ECAB50", - "RootResourceId" - ] - }, - "RestApiId": { - "Ref": "testApiD6ECAB50" - }, "AuthorizationType": "NONE", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -440,6 +431,15 @@ ] ] } + }, + "ResourceId": { + "Fn::GetAtt": [ + "testApiD6ECAB50", + "RootResourceId" + ] + }, + "RestApiId": { + "Ref": "testApiD6ECAB50" } }, "Metadata": { @@ -459,12 +459,6 @@ "DefaultAction": { "Allow": {} }, - "Scope": "REGIONAL", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": true, - "MetricName": "webACL", - "SampledRequestsEnabled": true - }, "Name": "test-name-apigateway", "Rules": [ { @@ -593,7 +587,13 @@ "SampledRequestsEnabled": true } } - ] + ], + "Scope": "REGIONAL", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": true, + "MetricName": "webACL", + "SampledRequestsEnabled": true + } } }, "testwafwebaclapigatewaylambdaWebACLAssociation": { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/test-helper.ts b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/test-helper.ts index 0422fc53f..3fa2ad9ab 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/test-helper.ts +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/test-helper.ts @@ -17,17 +17,17 @@ import * as api from "aws-cdk-lib/aws-apigateway"; import { addCfnSuppressRules } from "@aws-solutions-constructs/core"; export function CreateTestApi(stack: Stack, id: string): api.LambdaRestApi { - const lamdaFunction = new lambda.Function(stack, `${id}Function`, { + const lambdaFunction = new lambda.Function(stack, `${id}Function`, { code: lambda.Code.fromAsset(`${__dirname}/lambda`), runtime: lambda.Runtime.NODEJS_16_X, handler: ".handler", }); - addCfnSuppressRules(lamdaFunction, [{ id: "W58", reason: "Test Resource" }]); - addCfnSuppressRules(lamdaFunction, [{ id: "W89", reason: "Test Resource" }]); - addCfnSuppressRules(lamdaFunction, [{ id: "W92", reason: "Test Resource" }]); + addCfnSuppressRules(lambdaFunction, [{ id: "W58", reason: "Test Resource" }]); + addCfnSuppressRules(lambdaFunction, [{ id: "W89", reason: "Test Resource" }]); + addCfnSuppressRules(lambdaFunction, [{ id: "W92", reason: "Test Resource" }]); const restApi = new api.LambdaRestApi(stack, `${id}Api`, { - handler: lamdaFunction, + handler: lambdaFunction, }); const newDeployment = restApi.latestDeployment; diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/test.wafwebacl-apigateway.test.ts b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/test.wafwebacl-apigateway.test.ts index cc6da5575..45b066425 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/test.wafwebacl-apigateway.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-apigateway/test/test.wafwebacl-apigateway.test.ts @@ -30,7 +30,7 @@ function deployConstruct(stack: cdk.Stack, constructProps?: waf.CfnWebACLProps | return new WafwebaclToApiGateway(stack, 'test-wafwebacl-apigateway', props); } -test('Test error handling for existing WAF web ACL and user provider web ACL props', () => { +test('Confirm CheckWafWebAclProps is called', () => { const stack = new cdk.Stack(); const props: waf.CfnWebACLProps = { defaultAction: { @@ -53,15 +53,15 @@ test('Test error handling for existing WAF web ACL and user provider web ACL pro existingWebaclObj: wafAcl, webaclProps: props }); - }).toThrowError(); + }).toThrowError('Error - Either provide existingWebaclObj or webaclProps, but not both.\n'); }); test('Test default deployment', () => { const stack = new cdk.Stack(); const construct = deployConstruct(stack); - expect(construct.webacl !== null); - expect(construct.apiGateway !== null); + expect(construct.webacl).toBeDefined(); + expect(construct.apiGateway).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::WAFv2::WebACL", { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/lib/index.ts index 2215207ff..2fe981b31 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/lib/index.ts @@ -53,7 +53,7 @@ export class WafwebaclToAppsync extends Construct { */ constructor(scope: Construct, id: string, props: WafwebaclToAppsyncProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckWafWebAclProps(props); // Build the Web ACL this.webacl = defaults.buildWebacl(this, "REGIONAL", { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/integ.no-arguments.expected.json index d8a6edb1b..7e29e1c88 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/integ.no-arguments.expected.json @@ -13,12 +13,6 @@ "DefaultAction": { "Allow": {} }, - "Scope": "REGIONAL", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": true, - "MetricName": "webACL", - "SampledRequestsEnabled": true - }, "Rules": [ { "Name": "AWS-AWSManagedRulesBotControlRuleSet", @@ -146,7 +140,13 @@ "SampledRequestsEnabled": true } } - ] + ], + "Scope": "REGIONAL", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": true, + "MetricName": "webACL", + "SampledRequestsEnabled": true + } } }, "testwafwebaclappsyncWebACLAssociation": { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/integ.partial-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/integ.partial-arguments.expected.json index c7f333c0c..8a2b6cbf4 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/integ.partial-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/integ.partial-arguments.expected.json @@ -13,12 +13,6 @@ "DefaultAction": { "Allow": {} }, - "Scope": "REGIONAL", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": true, - "MetricName": "webACL", - "SampledRequestsEnabled": true - }, "Name": "test-name-appsync", "Rules": [ { @@ -147,7 +141,13 @@ "SampledRequestsEnabled": true } } - ] + ], + "Scope": "REGIONAL", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": true, + "MetricName": "webACL", + "SampledRequestsEnabled": true + } } }, "testwafwebaclappsyncWebACLAssociation": { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/test.wafwebacl-appsync.test.ts b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/test.wafwebacl-appsync.test.ts index 6b13384b6..02cf0ac92 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/test.wafwebacl-appsync.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-appsync/test/test.wafwebacl-appsync.test.ts @@ -40,10 +40,7 @@ function deployConstruct( }); } -// -------------------------------------------------------------- -// Test error handling for existing WAF web ACL and user provided web ACL props -// -------------------------------------------------------------- -test("Test error handling for existing WAF web ACL and user provider web ACL props", () => { +test('Confirm CheckWafWebAclProps is called', () => { const stack = new cdk.Stack(); const props: waf.CfnWebACLProps = { defaultAction: { @@ -66,7 +63,7 @@ test("Test error handling for existing WAF web ACL and user provider web ACL pro existingWebaclObj: wafAcl, webaclProps: props, }); - }).toThrowError(); + }).toThrowError('Error - Either provide existingWebaclObj or webaclProps, but not both.\n'); }); // -------------------------------------------------------------- @@ -76,8 +73,8 @@ test("Test default deployment", () => { const stack = new cdk.Stack(); const construct = deployConstruct(stack); - expect(construct.webacl !== null); - expect(construct.appsyncApi !== null); + expect(construct.webacl).toBeDefined(); + expect(construct.appsyncApi).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::WAFv2::WebACL", { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/lib/index.ts index 757996dd5..457d481a7 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/lib/index.ts @@ -57,7 +57,7 @@ export class WafwebaclToCloudFront extends Construct { */ constructor(scope: Construct, id: string, props: WafwebaclToCloudFrontProps) { super(scope, id); - defaults.CheckProps(props); + defaults.CheckWafWebAclProps(props); // Build the Web ACL this.webacl = defaults.buildWebacl(this, 'CLOUDFRONT', { diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.existing-waf-to-multiple-cloudfront.expected.json b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.existing-waf-to-multiple-cloudfront.expected.json index 5b1394173..1dd044136 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.existing-waf-to-multiple-cloudfront.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.existing-waf-to-multiple-cloudfront.expected.json @@ -176,12 +176,6 @@ "DefaultAction": { "Allow": {} }, - "Scope": "CLOUDFRONT", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": true, - "MetricName": "webACL", - "SampledRequestsEnabled": true - }, "Rules": [ { "Name": "AWS-AWSManagedRulesBotControlRuleSet", @@ -309,7 +303,13 @@ "SampledRequestsEnabled": true } } - ] + ], + "Scope": "CLOUDFRONT", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": true, + "MetricName": "webACL", + "SampledRequestsEnabled": true + } } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.no-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.no-arguments.expected.json index f50031c7d..65721a0dd 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.no-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.no-arguments.expected.json @@ -91,12 +91,6 @@ "DefaultAction": { "Allow": {} }, - "Scope": "CLOUDFRONT", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": true, - "MetricName": "webACL", - "SampledRequestsEnabled": true - }, "Rules": [ { "Name": "AWS-AWSManagedRulesBotControlRuleSet", @@ -224,7 +218,13 @@ "SampledRequestsEnabled": true } } - ] + ], + "Scope": "CLOUDFRONT", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": true, + "MetricName": "webACL", + "SampledRequestsEnabled": true + } } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.partial-arguments.expected.json b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.partial-arguments.expected.json index d90fd31af..dce1c2672 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.partial-arguments.expected.json +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/integ.partial-arguments.expected.json @@ -91,12 +91,6 @@ "DefaultAction": { "Allow": {} }, - "Scope": "CLOUDFRONT", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": true, - "MetricName": "webACL", - "SampledRequestsEnabled": true - }, "Name": "test-name-cloudfront", "Rules": [ { @@ -225,7 +219,13 @@ "SampledRequestsEnabled": true } } - ] + ], + "Scope": "CLOUDFRONT", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": true, + "MetricName": "webACL", + "SampledRequestsEnabled": true + } } } }, diff --git a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/test.wafwebacl-cloudfront.test.ts b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/test.wafwebacl-cloudfront.test.ts index 77461d1d4..3ec3b72f3 100644 --- a/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/test.wafwebacl-cloudfront.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-wafwebacl-cloudfront/test/test.wafwebacl-cloudfront.test.ts @@ -37,7 +37,7 @@ function deployConstruct(stack: cdk.Stack, constructProps?: waf.CfnWebACLProps | return new WafwebaclToCloudFront(stack, 'test-wafwebacl-cloudfront', props); } -test('Test error handling for existing WAF web ACL and user provider web ACL props', () => { +test('Confirm CheckWafWebAclProps is called', () => { const stack = new cdk.Stack(); const props: waf.CfnWebACLProps = { defaultAction: { @@ -63,15 +63,15 @@ test('Test error handling for existing WAF web ACL and user provider web ACL pro existingWebaclObj: wafAcl, webaclProps: props }); - }).toThrowError(); + }).toThrowError('Error - Either provide existingWebaclObj or webaclProps, but not both.\n'); }); test('Test default deployment', () => { const stack = new cdk.Stack(); const construct = deployConstruct(stack); - expect(construct.webacl !== null); - expect(construct.cloudFrontWebDistribution !== null); + expect(construct.webacl).toBeDefined(); + expect(construct.cloudFrontWebDistribution).toBeDefined(); const template = Template.fromStack(stack); template.hasResourceProperties("AWS::WAFv2::WebACL", { diff --git a/source/patterns/@aws-solutions-constructs/core/index.ts b/source/patterns/@aws-solutions-constructs/core/index.ts index c35ed2b18..29bc3741f 100644 --- a/source/patterns/@aws-solutions-constructs/core/index.ts +++ b/source/patterns/@aws-solutions-constructs/core/index.ts @@ -64,7 +64,6 @@ export * from './lib/glue-table-defaults'; export * from './lib/glue-table-helper'; export * from './lib/glue-database-defaults'; export * from './lib/glue-database-helper'; -export * from './lib/input-validation'; export * from './test/test-helper'; export * from './lib/ssm-string-parameter-helper'; export * from './lib/eventbridge-helper'; diff --git a/source/patterns/@aws-solutions-constructs/core/lib/alb-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/alb-helper.ts index 8441bd6b5..604edddef 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/alb-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/alb-helper.ts @@ -112,12 +112,15 @@ export function AddListener( protocol: "HTTPS", }; + // NOSONAR: (typescript:S5332) + // This listener is explicitly created to redirect non TLS connections + // The lack of SSL/TLS is intentional const httpListener = new elb.ApplicationListener( scope, `${id}-redirect`, { loadBalancer, - protocol: ApplicationProtocol.HTTP, + protocol: ApplicationProtocol.HTTP, // NOSONAR defaultAction: ListenerAction.redirect(opt), } ); @@ -216,17 +219,22 @@ export function CheckAlbProps(props: any) { let errorMessages = ''; let errorFound = false; + if (props.loadBalancerProps && props.existingLoadBalancerObj) { + errorMessages += 'Error - Either provide loadBalancerProps or existingLoadBalancerObj, but not both.\n'; + errorFound = true; + } + + if ((props?.logAlbAccessLogs === false) && (props.albLoggingBucketProps)) { + errorMessages += 'Error - If logAlbAccessLogs is false, supplying albLoggingBucketProps is invalid.\n'; + errorFound = true; + } + if (props.listenerProps?.certificateArns) { errorMessages += "certificateArns is deprecated. Please supply certificates using props.listenerProps.certificates\n"; errorFound = true; } - if ( - ((props.existingLoadBalancerObj && - props.existingLoadBalancerObj.listeners.length === 0) || - !props.existingLoadBalancerObj) && - !props.listenerProps - ) { + if (ValidateAddListenerProps(props)) { errorMessages += "When adding the first listener and target to a load balancer, listenerProps must be specified and include at least a certificate or protocol: HTTP\n"; errorFound = true; } @@ -269,4 +277,15 @@ export function CheckAlbProps(props: any) { if (errorFound) { throw new Error(errorMessages); } -} \ No newline at end of file + +} + +function ValidateAddListenerProps(props: any) { + if (((props.existingLoadBalancerObj && + props.existingLoadBalancerObj.listeners.length === 0) || + !props.existingLoadBalancerObj) && + !props.listenerProps) { + return true; + } + return false; +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/apigateway-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/apigateway-helper.ts index 3a52a22fb..3ba3363dc 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/apigateway-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/apigateway-helper.ts @@ -67,7 +67,7 @@ function configureCloudwatchRoleForApi(scope: Construct, api: apigateway.RestApi addCfnSuppressRules(deployment, [ { id: 'W45', - reason: `ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource` + reason: `ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource` } ]); @@ -397,6 +397,6 @@ export function addProxyMethodToApiResource(params: AddProxyMethodToApiResourceI }; // Setup the API Gateway method - const overridenProps = consolidateProps(defaultMethodOptions, params.methodOptions); - return params.apiResource.addMethod(params.apiMethod, apiGatewayIntegration, overridenProps); + const overriddenProps = consolidateProps(defaultMethodOptions, params.methodOptions); + return params.apiResource.addMethod(params.apiMethod, apiGatewayIntegration, overriddenProps); } \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/core/lib/cloudfront-distribution-defaults.ts b/source/patterns/@aws-solutions-constructs/core/lib/cloudfront-distribution-defaults.ts index f88b3c467..266fa604d 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/cloudfront-distribution-defaults.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/cloudfront-distribution-defaults.ts @@ -94,7 +94,7 @@ export function DefaultCloudFrontWebDistributionForS3Props( /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ -export function DefaultCloudFrontDisributionForMediaStoreProps(mediastoreContainer: mediastore.CfnContainer, +export function DefaultCloudFrontDistributionForMediaStoreProps(mediastoreContainer: mediastore.CfnContainer, loggingBucket: s3.Bucket | undefined, originRequestPolicy: cloudfront.OriginRequestPolicy, setHttpSecurityHeaders: boolean, diff --git a/source/patterns/@aws-solutions-constructs/core/lib/cloudfront-distribution-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/cloudfront-distribution-helper.ts index 15991ecfe..19f7eec07 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/cloudfront-distribution-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/cloudfront-distribution-helper.ts @@ -24,7 +24,7 @@ import * as mediastore from 'aws-cdk-lib/aws-mediastore'; import { DefaultCloudFrontWebDistributionForS3Props, DefaultCloudFrontWebDistributionForApiGatewayProps, - DefaultCloudFrontDisributionForMediaStoreProps + DefaultCloudFrontDistributionForMediaStoreProps } from './cloudfront-distribution-defaults'; import { addCfnSuppressRules, consolidateProps } from './utils'; import { createLoggingBucket } from './s3-bucket-helper'; @@ -203,7 +203,7 @@ export function CloudFrontDistributionForMediaStore(scope: Construct, const cloudfrontFunction = getCloudfrontFunction(httpSecurityHeaders, scope); - const defaultprops = DefaultCloudFrontDisributionForMediaStoreProps( + const defaultprops = DefaultCloudFrontDistributionForMediaStoreProps( mediaStoreContainer, loggingBucket, originRequestPolicy, @@ -264,3 +264,22 @@ function getLoggingBucket( function getCloudfrontFunction(httpSecurityHeaders: boolean, scope: Construct) { return httpSecurityHeaders ? defaultCloudfrontFunction(scope) : undefined; } + +export interface CloudFrontProps { + readonly insertHttpSecurityHeaders?: boolean; + readonly responseHeadersPolicyProps?: cloudfront.ResponseHeadersPolicyProps; +} + +export function CheckCloudFrontProps(propsObject: CloudFrontProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.insertHttpSecurityHeaders !== false && propsObject.responseHeadersPolicyProps?.securityHeadersBehavior) { + errorMessages += 'responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/dynamodb-table-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/dynamodb-table-helper.ts index 9d28b59b4..cf2cfe68b 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/dynamodb-table-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/dynamodb-table-helper.ts @@ -70,7 +70,6 @@ export interface BuildDynamoDBTableResponse { * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ export function buildDynamoDBTable(scope: Construct, props: BuildDynamoDBTableProps): BuildDynamoDBTableResponse { - checkTableProps(props); // Conditional DynamoDB Table creation if (props.existingTableObj) { @@ -84,33 +83,6 @@ export function buildDynamoDBTable(scope: Construct, props: BuildDynamoDBTablePr } } -/** - * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. - */ -export function checkTableProps(props: BuildDynamoDBTableProps) { - let errorMessages = ''; - let errorFound = false; - - if (props.dynamoTableProps && props.existingTableObj) { - errorMessages += 'Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'; - errorFound = true; - } - - if (props.dynamoTableProps && props.existingTableInterface) { - errorMessages += 'Error - Either provide existingTableInterface or dynamoTableProps, but not both.\n'; - errorFound = true; - } - - if (props.existingTableObj && props.existingTableInterface) { - errorMessages += 'Error - Either provide existingTableInterface or existingTableObj, but not both.\n'; - errorFound = true; - } - - if (errorFound) { - throw new Error(errorMessages); - } -} - export interface BuildDynamoDBTableWithStreamResponse { readonly tableInterface: dynamodb.ITable, readonly tableObject?: dynamodb.Table, @@ -143,3 +115,33 @@ export function getPartitionKeyNameFromTable(table: dynamodb.Table): string { } return partitionKey.attributeName; } + +export interface DynamoDBProps { + readonly dynamoTableProps?: dynamodb.TableProps, + readonly existingTableObj?: dynamodb.Table, + readonly existingTableInterface?: dynamodb.ITable, +} + +export function CheckDynamoDBProps(propsObject: DynamoDBProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.dynamoTableProps && propsObject.existingTableObj) { + errorMessages += 'Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'; + errorFound = true; + } + + if (propsObject.dynamoTableProps && propsObject.existingTableInterface) { + errorMessages += 'Error - Either provide existingTableInterface or dynamoTableProps, but not both.\n'; + errorFound = true; + } + + if (propsObject.existingTableObj && propsObject.existingTableInterface) { + errorMessages += 'Error - Either provide existingTableInterface or existingTableObj, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/elasticsearch-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/elasticsearch-helper.ts index 73e8d2a02..be82d4981 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/elasticsearch-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/elasticsearch-helper.ts @@ -83,7 +83,10 @@ export function buildElasticSearch(scope: Construct, props: BuildElasticSearchPr const defaultCfnDomainProps = DefaultCfnDomainProps(props.domainName, cognitoKibanaConfigureRole, props); const finalCfnDomainProps = consolidateProps(defaultCfnDomainProps, props.clientDomainProps, constructDrivenProps); - const esDomain = new elasticsearch.CfnDomain(scope, `ElasticsearchDomain`, finalCfnDomainProps); + // tlsSecurityPolicy is set in DefaultCfnDomainProps() - it is the + // default behavior, but Sonarqube cannot follow the program flow to confirm this. + // This is confirmed by the 'Check that TLS 1.2 is the default' test in aws-lambda-elasticsearch + const esDomain = new elasticsearch.CfnDomain(scope, `ElasticsearchDomain`, finalCfnDomainProps); // NOSONAR addCfnSuppressRules(esDomain, [ { diff --git a/source/patterns/@aws-solutions-constructs/core/lib/eventbridge-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/eventbridge-helper.ts index 469ca514f..819ec3bfd 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/eventbridge-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/eventbridge-helper.ts @@ -49,4 +49,23 @@ export function buildEventBus(scope: Construct, props: BuildEventBusProps): even } // ESLint requires this return statement, so disabling SonarQube warning return; // NOSONAR -} \ No newline at end of file +} + +export interface EventBridgeProps { + readonly existingEventBusInterface: events.IEventBus, + readonly eventBusProps: events.EventBusProps +} + +export function CheckEventBridgeProps(propsObject: EventBridgeProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.existingEventBusInterface && propsObject.eventBusProps) { + errorMessages += 'Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/fargate-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/fargate-helper.ts index f47e31c38..4036ed44b 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/fargate-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/fargate-helper.ts @@ -62,7 +62,7 @@ export function CreateFargateService( defaults.ServiceEndpointTypes.S3 ); - const constructContainerDefintionProps: any = {}; + const constructContainerDefinitionProps: any = {}; const constructFargateServiceDefinitionProps: any = {}; if (!props.clientFargateServiceProps?.cluster) { @@ -77,7 +77,7 @@ export function CreateFargateService( // Set up the Fargate service if (!props.clientContainerDefinitionProps?.image) { - constructContainerDefintionProps.image = CreateImage( + constructContainerDefinitionProps.image = CreateImage( scope, id, props.ecrRepositoryArn, @@ -92,7 +92,7 @@ export function CreateFargateService( id, props.clientFargateTaskDefinitionProps, props.clientContainerDefinitionProps, - constructContainerDefintionProps + constructContainerDefinitionProps ); constructFargateServiceDefinitionProps.taskDefinition = createTaskDefinitionResponse.taskDefinition; newContainerDefinition = createTaskDefinitionResponse.containerDefinition; @@ -224,16 +224,7 @@ export function CheckFargateProps(props: any) { let errorMessages = ""; let errorFound = false; - if ( - props.existingFargateServiceObject && - (props.existingImageObject || - props.ecrImageVersion || - props.containerDefinitionProps || - props.fargateTaskDefinitionProps || - props.ecrRepositoryArn || - props.fargateServiceProps || - props.clusterProps) - ) { + if (CheckForConflictingServiceProps(props)) { errorFound = true; errorMessages += "If you provide an existingFargateServiceObject, you cannot provide any props defining a new service\n"; @@ -267,10 +258,10 @@ export function CheckFargateProps(props: any) { "If you provide a cluster in fargateServiceProps then you cannot provide clusterProps\n"; } - if (props.clusterProps?.vpc) { + if (CheckForInvalidVpcs(props)) { errorFound = true; errorMessages += - "All services in the construct use the construct VPC, you cannot specify a VPC in clusterProps\n"; + "Provide all VPC info at Construct level, not within clusterProps nor targetGroupProps\n"; } if ( @@ -290,6 +281,34 @@ export function CheckFargateProps(props: any) { } } +/** + * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. + */ +export function CheckForConflictingServiceProps(props: any): boolean { + if (props.existingFargateServiceObject && + (props.existingImageObject || + props.ecrImageVersion || + props.containerDefinitionProps || + props.fargateTaskDefinitionProps || + props.ecrRepositoryArn || + props.fargateServiceProps || + props.clusterProps) + ) { + return true; + } + return false; +} + +/** + * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. + */ +export function CheckForInvalidVpcs(props: any): boolean { + if (props.clusterProps?.vpc || props.targetGroupProps?.vpc) { + return true; + } + return false; +} + /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ @@ -299,4 +318,4 @@ export function getServiceVpcSecurityGroupIds(service: ecs.FargateService): stri service.connections.securityGroups.forEach(element => securityGroupIds.push(element.securityGroupId)); return securityGroupIds; -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/glue-job-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/glue-job-helper.ts index 104cf6e71..d5e61b6eb 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/glue-job-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/glue-job-helper.ts @@ -215,12 +215,10 @@ export function deployGlueJob(scope: Construct, glueJobProps: glue.CfnJobProps, } else { // create CDK Bucket instance from S3 url and grant read access to Glue Job's service principal if (isJobCommandProperty(newGlueJobProps.command)) { - if (!newGlueJobProps.command.scriptLocation) { - throw Error('Script location has to be provided as an s3 Url location. Script location cannot be empty'); - } const scriptLocation = newGlueJobProps.command.scriptLocation; - const scriptBucketLocation: IBucket = Bucket.fromBucketArn(scope, 'ScriptLocaiton', getS3ArnfromS3Url(scriptLocation)); + // Incoming Props, including scriptLocation, are checked upstream in CheckGlueProps() + const scriptBucketLocation: IBucket = Bucket.fromBucketArn(scope, 'ScriptLocation', getS3ArnfromS3Url(scriptLocation!)); scriptBucketLocation.grantRead(jobRole); } } @@ -240,7 +238,7 @@ export function deployGlueJob(scope: Construct, glueJobProps: glue.CfnJobProps, export function createGlueJobRole(scope: Construct): Role { return new Role(scope, 'JobRole', { assumedBy: new ServicePrincipal('glue.amazonaws.com'), - description: 'Service role that Glue custom ETL jobs will assume for exeuction', + description: 'Service role that Glue custom ETL jobs will assume for execution', }); } @@ -259,7 +257,7 @@ export function createGlueTable(scope: Construct, database: glue.CfnDatabase, ta * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. * * This method creates an AWS Glue database. The method is only called with an existing Glue database type is not provided. - * The method uses the user provided props to override the defaul props for the Glue database + * The method uses the user provided props to override the default props for the Glue database * * @param scope * @param databaseProps @@ -299,4 +297,4 @@ function isJobCommandProperty(command: glue.CfnJob.JobCommandProperty | IResolva defaults.printWarning('command not of type JobCommandProperty type'); return false; } -} \ No newline at end of file +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/glue-table-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/glue-table-helper.ts index 447c57a38..4939a26be 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/glue-table-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/glue-table-helper.ts @@ -18,6 +18,8 @@ import { CfnTable, CfnTableProps } from "aws-cdk-lib/aws-glue"; import { Construct } from "constructs"; +import * as glue from 'aws-cdk-lib/aws-glue'; +import * as s3assets from 'aws-cdk-lib/aws-s3-assets'; /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. @@ -29,8 +31,52 @@ import { Construct } from "constructs"; * @param fieldSchema * @param sourceType * @param parameters - Key value pairs of parameters. If source type is 'Kinesis', pass Kinesis Data Stream name with key - * as 'STREAM_NAME'. Example: {STREAM_NAME: 'KinesisStreamConstrct.streamName'} + * as 'STREAM_NAME'. Example: {STREAM_NAME: 'KinesisStreamConstruct.streamName'} */ export function DefaultGlueTable(scope: Construct, tableProps: CfnTableProps): CfnTable { return new CfnTable(scope, 'GlueTable', tableProps); -} \ No newline at end of file +} +export interface GlueProps { + readonly existingGlueJob?: glue.CfnJob, + readonly etlCodeAsset?: s3assets.Asset; + readonly glueJobProps?: glue.CfnJobProps | any; + readonly fieldSchema?: glue.CfnTable.ColumnProperty[]; + readonly existingTable?: glue.CfnTable; + readonly tablePropss?: glue.CfnTableProps; +} + +export function CheckGlueProps(propsObject: GlueProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.glueJobProps && propsObject.existingGlueJob) { + errorMessages += 'Error - Either provide glueJobProps or existingGlueJob, but not both.\n'; + errorFound = true; + } + + if ((!propsObject.existingGlueJob) && (!propsObject.glueJobProps.command.scriptLocation && !propsObject.etlCodeAsset)) { + errorMessages += ('Either one of CfnJob.JobCommandProperty.scriptLocation or etlCodeAsset has ' + + 'to be provided. If the ETL Job code file exists in a local filesystem, please set ' + + 'KinesisstreamsToGluejobProps.etlCodeAsset. If the ETL Job is available in an S3 bucket, set the ' + + 'CfnJob.JobCommandProperty.scriptLocation property\n'); + errorFound = true; + } + + if (propsObject.glueJobProps?.command?.scriptLocation) { + const s3Url: string = propsObject.glueJobProps.command.scriptLocation; + const found = s3Url.match(/^s3:\/\/\S+\/\S+/g); + if (!(found && found.length > 0 && found[0].length === s3Url.length)) { + errorMessages += "Invalid S3 URL for Glue script provided\n"; + errorFound = true; + } + } + + if (propsObject.fieldSchema === undefined && propsObject.existingTable === undefined && propsObject.tableProps === undefined) { + errorMessages += "Either fieldSchema or table property has to be set, both cannot be omitted"; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/input-validation.ts b/source/patterns/@aws-solutions-constructs/core/lib/input-validation.ts deleted file mode 100644 index e54e7d9b0..000000000 --- a/source/patterns/@aws-solutions-constructs/core/lib/input-validation.ts +++ /dev/null @@ -1,262 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance - * with the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -/* - * The functions found here in the core library are for internal use and can be changed - * or removed outside of a major release. We recommend against calling them directly from client code. - */ - -import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; -import * as kinesis from 'aws-cdk-lib/aws-kinesis'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; -import * as sqs from 'aws-cdk-lib/aws-sqs'; -import * as mediastore from 'aws-cdk-lib/aws-mediastore'; -import * as s3 from 'aws-cdk-lib/aws-s3'; -import * as ec2 from 'aws-cdk-lib/aws-ec2'; -import * as elb from 'aws-cdk-lib/aws-elasticloadbalancingv2'; -import * as sns from 'aws-cdk-lib/aws-sns'; -import * as glue from 'aws-cdk-lib/aws-glue'; -import * as sagemaker from 'aws-cdk-lib/aws-sagemaker'; -import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager"; -import * as kms from "aws-cdk-lib/aws-kms"; -import {ResponseHeadersPolicyProps} from "aws-cdk-lib/aws-cloudfront"; -import * as opensearch from "aws-cdk-lib/aws-opensearchservice"; - -export interface VerifiedProps { - readonly dynamoTableProps?: dynamodb.TableProps, - readonly existingTableObj?: dynamodb.Table, - readonly existingTableInterface?: dynamodb.ITable, - - readonly existingStreamObj?: kinesis.Stream; - readonly kinesisStreamProps?: kinesis.StreamProps, - - readonly existingLambdaObj?: lambda.Function, - readonly lambdaFunctionProps?: lambda.FunctionProps, - - readonly existingQueueObj?: sqs.Queue, - readonly queueProps?: sqs.QueueProps, - readonly deployDeadLetterQueue?: boolean, - readonly deadLetterQueueProps?: sqs.QueueProps, - - readonly existingMediaStoreContainerObj?: mediastore.CfnContainer; - readonly mediaStoreContainerProps?: mediastore.CfnContainerProps; - - readonly existingBucketObj?: s3.Bucket, - readonly existingBucketInterface?: s3.IBucket, - readonly bucketProps?: s3.BucketProps, - - readonly topicProps?: sns.TopicProps, - readonly existingTopicObj?: sns.Topic, - - readonly glueJobProps?: glue.CfnJobProps, - readonly existingGlueJob?: glue.CfnJob, - - readonly existingSagemakerEndpointObj?: sagemaker.CfnEndpoint, - readonly endpointProps?: sagemaker.CfnEndpointProps, - - readonly existingSecretObj?: secretsmanager.Secret; - readonly secretProps?: secretsmanager.SecretProps; - - readonly existingVpc?: ec2.IVpc; - readonly vpcProps?: ec2.VpcProps; - readonly deployVpc?: boolean; - - readonly encryptionKey?: kms.Key, - readonly encryptionKeyProps?: kms.KeyProps - - readonly loadBalancerProps?: elb.ApplicationLoadBalancerProps; - readonly existingLoadBalancerObj?: elb.ApplicationLoadBalancer; - - readonly logAlbAccessLogs?: boolean; - readonly albLoggingBucketProps?: s3.BucketProps; - - readonly existingLoggingBucketObj?: s3.IBucket; - readonly loggingBucketProps?: s3.BucketProps; - readonly logS3AccessLogs?: boolean; - - readonly insertHttpSecurityHeaders?: boolean; - readonly responseHeadersPolicyProps?: ResponseHeadersPolicyProps; - readonly openSearchDomainProps?: opensearch.CfnDomainProps; -} - -/** - * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. - */ -export function CheckProps(propsObject: VerifiedProps | any) { - let errorMessages = ''; - let errorFound = false; - - if (propsObject.loadBalancerProps && propsObject.existingLoadBalancerObj) { - errorMessages += 'Error - Either provide loadBalancerProps or existingLoadBalancerObj, but not both.\n'; - errorFound = true; - } - - if (propsObject.dynamoTableProps && propsObject.existingTableObj) { - errorMessages += 'Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'; - errorFound = true; - } - - if (propsObject.dynamoTableProps && propsObject.existingTableInterface) { - errorMessages += 'Error - Either provide existingTableInterface or dynamoTableProps, but not both.\n'; - errorFound = true; - } - - if (propsObject.existingStreamObj && propsObject.kinesisStreamProps) { - errorMessages += 'Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'; - errorFound = true; - } - - if (propsObject.existingLambdaObj && propsObject.lambdaFunctionProps) { - errorMessages += 'Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'; - errorFound = true; - } - - if (propsObject.existingQueueObj && propsObject.queueProps) { - errorMessages += 'Error - Either provide queueProps or existingQueueObj, but not both.\n'; - errorFound = true; - } - - if (propsObject.queueProps?.encryptionMasterKey && propsObject.encryptionKey) { - errorMessages += 'Error - Either provide queueProps.encryptionMasterKey or encryptionKey, but not both.\n'; - errorFound = true; - } - - if (propsObject.queueProps?.encryptionMasterKey && propsObject.encryptionKeyProps) { - errorMessages += 'Error - Either provide queueProps.encryptionMasterKey or encryptionKeyProps, but not both.\n'; - errorFound = true; - } - - if ((propsObject?.deployDeadLetterQueue === false) && propsObject.deadLetterQueueProps) { - errorMessages += 'Error - If deployDeadLetterQueue is false then deadLetterQueueProps cannot be specified.\n'; - errorFound = true; - } - - const isQueueFifo: boolean = propsObject?.queueProps?.fifo; - const isDeadLetterQueueFifo: boolean = propsObject?.deadLetterQueueProps?.fifo; - const deployDeadLetterQueue: boolean = propsObject.deployDeadLetterQueue || propsObject.deployDeadLetterQueue === undefined; - - if (deployDeadLetterQueue && (isQueueFifo !== isDeadLetterQueueFifo)) { - errorMessages += 'Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + - 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'; - errorFound = true; - } - - if (propsObject.existingMediaStoreContainerObj && propsObject.mediaStoreContainerProps) { - errorMessages += 'Error - Either provide mediaStoreContainerProps or existingMediaStoreContainerObj, but not both.\n'; - errorFound = true; - } - - if (propsObject.existingBucketObj && propsObject.bucketProps) { - errorMessages += 'Error - Either provide bucketProps or existingBucketObj, but not both.\n'; - errorFound = true; - } - - if (propsObject.existingBucketInterface && propsObject.bucketProps) { - errorMessages += 'Error - Either provide bucketProps or existingBucketInterface, but not both.\n'; - errorFound = true; - } - - if (propsObject.topicProps && propsObject.existingTopicObj) { - errorMessages += 'Error - Either provide topicProps or existingTopicObj, but not both.\n'; - errorFound = true; - } - - if (propsObject.topicProps?.masterKey && propsObject.encryptionKey) { - errorMessages += 'Error - Either provide topicProps.masterKey or encryptionKey, but not both.\n'; - errorFound = true; - } - - if (propsObject.topicProps?.masterKey && propsObject.encryptionKeyProps) { - errorMessages += 'Error - Either provide topicProps.masterKey or encryptionKeyProps, but not both.\n'; - errorFound = true; - } - - if (propsObject.glueJobProps && propsObject.existingGlueJob) { - errorMessages += 'Error - Either provide glueJobProps or existingGlueJob, but not both.\n'; - errorFound = true; - } - - if (propsObject.existingSagemakerEndpointObj && propsObject.endpointProps) { - errorMessages += 'Error - Either provide endpointProps or existingSagemakerEndpointObj, but not both.\n'; - errorFound = true; - } - - if (propsObject.existingSecretObj && propsObject.secretProps) { - errorMessages += 'Error - Either provide secretProps or existingSecretObj, but not both.\n'; - errorFound = true; - } - - if ((propsObject.deployVpc || propsObject.vpcProps) && propsObject.existingVpc) { - errorMessages += 'Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'; - errorFound = true; - } - - if (propsObject.encryptionKey && propsObject.encryptionKeyProps) { - errorMessages += 'Error - Either provide encryptionKey or encryptionKeyProps, but not both.\n'; - errorFound = true; - } - - if (propsObject.existingEventBusInterface && propsObject.eventBusProps) { - errorMessages += 'Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'; - errorFound = true; - } - - if (propsObject.existingWebaclObj && propsObject.webaclProps) { - errorMessages += 'Error - Either provide existingWebaclObj or webaclProps, but not both.\n'; - errorFound = true; - } - - if ((propsObject?.logAlbAccessLogs === false) && (propsObject.albLoggingBucketProps)) { - errorMessages += 'Error - If logAlbAccessLogs is false, supplying albLoggingBucketProps is invalid.\n'; - errorFound = true; - } - - if (propsObject.existingLoggingBucketObj && propsObject.loggingBucketProps) { - errorMessages += 'Error - Either provide existingLoggingBucketObj or loggingBucketProps, but not both.\n'; - errorFound = true; - } - - if ((propsObject?.logS3AccessLogs === false) && (propsObject.loggingBucketProps || propsObject.existingLoggingBucketObj)) { - errorMessages += 'Error - If logS3AccessLogs is false, supplying loggingBucketProps or existingLoggingBucketObj is invalid.\n'; - errorFound = true; - } - - if (propsObject.existingBucketObj && (propsObject.loggingBucketProps || propsObject.logS3AccessLogs)) { - errorMessages += 'Error - If existingBucketObj is provided, supplying loggingBucketProps or logS3AccessLogs is an error.\n'; - errorFound = true; - } - - if (propsObject.insertHttpSecurityHeaders !== false && propsObject.responseHeadersPolicyProps?.securityHeadersBehavior) { - errorMessages += 'responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.'; - errorFound = true; - } - - if (propsObject.openSearchDomainProps?.vpcOptions) { - throw new Error("Error - Define VPC using construct parameters not the OpenSearch Service props"); - } - - if (errorFound) { - throw new Error(errorMessages); - } -} - -/** - * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. - */ -export function CheckListValues(allowedPermissions: string[], submittedValues: string[], valueType: string) { - submittedValues.forEach((submittedValue) => { - if (!allowedPermissions.includes(submittedValue)) { - throw Error(`Invalid ${valueType} submitted - ${submittedValue}` ); - } - }); -} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/kendra-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/kendra-helper.ts index 0b88b9edc..3d5a809ee 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/kendra-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/kendra-helper.ts @@ -18,13 +18,12 @@ import * as kendra from 'aws-cdk-lib/aws-kendra'; import * as iam from 'aws-cdk-lib/aws-iam'; -import { addCfnSuppressRules, consolidateProps } from "./utils"; +import { addCfnSuppressRules, consolidateProps, generatePhysicalName, overrideProps } from "./utils"; import { Aws } from 'aws-cdk-lib'; // Note: To ensure CDKv2 compatibility, keep the import statement for Construct separate import { Construct } from 'constructs'; import { DefaultKendraIndexProps } from './kendra-defaults'; -import { generatePhysicalName, overrideProps } from "./utils"; export interface BuildKendraIndexProps { readonly kendraIndexProps?: kendra.CfnIndexProps | any; @@ -109,18 +108,18 @@ function CreateS3DataSource(scope: Construct, // the type to remove the union with IResolvable const dataSourceConfig = clientProps.dataSourceConfiguration as kendra.CfnDataSource.DataSourceConfigurationProperty; if (!dataSourceConfig) { - throw new Error('Error - an S3 Kendra DataSource requires an DataSourceCofiguration prop'); + throw new Error('Error - an S3 Kendra DataSource requires an DataSourceConfiguration prop'); } const s3DataSourceConfig = dataSourceConfig.s3Configuration as kendra.CfnDataSource.S3DataSourceConfigurationProperty; if (!s3DataSourceConfig) { - throw new Error('Error - an S3 Kendra DataSource requires an DataSourceCofiguration.S3Configuration prop'); + throw new Error('Error - an S3 Kendra DataSource requires an DataSourceConfiguration.S3Configuration prop'); } // No Bucket name is an error if (!s3DataSourceConfig.bucketName) { - throw new Error('Error - an S3 Kendra DataSource requires the DataSourceCofiguration.S3Configuration.bucketName prop'); + throw new Error('Error - an S3 Kendra DataSource requires the DataSourceConfiguration.S3Configuration.bucketName prop'); } // If there's no role, make a role and put it into defaultProps diff --git a/source/patterns/@aws-solutions-constructs/core/lib/kinesis-streams-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/kinesis-streams-helper.ts index f366dafc8..050fbd956 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/kinesis-streams-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/kinesis-streams-helper.ts @@ -95,4 +95,23 @@ export function buildKinesisStreamCWAlarms(scope: Construct): cloudwatch.Alarm[] })); return alarms; -} \ No newline at end of file +} + +export interface KinesisStreamProps { + readonly existingStreamObj?: kinesis.Stream; + readonly kinesisStreamProps?: kinesis.StreamProps, +} + +export function CheckKinesisStreamProps(propsObject: KinesisStreamProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.existingStreamObj && propsObject.kinesisStreamProps) { + errorMessages += 'Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/lambda-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/lambda-helper.ts index fc2f88838..0a0989c4e 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/lambda-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/lambda-helper.ts @@ -113,7 +113,7 @@ export function deployLambdaFunction(scope: Construct, } }); - // If this Lambda function is going to access resoures in a + // If this Lambda function is going to access resources in a // VPC, then it needs privileges to access an ENI in that VPC if (lambdaFunctionProps.vpc || vpc) { lambdaServiceRole.addToPolicy(new iam.PolicyStatement({ @@ -194,7 +194,7 @@ export function deployLambdaFunction(scope: Construct, /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. * - * A wrapper above Function.addPermision that + * A wrapper above Function.addPermission that * prevents two different calls to addPermission using * the same construct id. */ @@ -236,4 +236,23 @@ export function getLambdaVpcSecurityGroupIds(lambdaFunction: lambda.Function): s lambdaFunction.connections.securityGroups.forEach(element => securityGroupIds.push(element.securityGroupId)); return securityGroupIds; -} \ No newline at end of file +} + +export interface LambdaProps { + readonly existingLambdaObj?: lambda.Function, + readonly lambdaFunctionProps?: lambda.FunctionProps, +} + +export function CheckLambdaProps(propsObject: LambdaProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.existingLambdaObj && propsObject.lambdaFunctionProps) { + errorMessages += 'Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/mediastore-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/mediastore-helper.ts index b8428283c..4ce2f08d8 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/mediastore-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/mediastore-helper.ts @@ -39,4 +39,23 @@ export function MediaStoreContainer(scope: Construct, mediaStoreContainerProps?: mediaStoreContainer.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.RETAIN; return mediaStoreContainer; -} \ No newline at end of file +} + +export interface MediaStoreProps { + readonly existingMediaStoreContainerObj?: mediastore.CfnContainer; + readonly mediaStoreContainerProps?: mediastore.CfnContainerProps; +} + +export function CheckMediaStoreProps(propsObject: MediaStoreProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.existingMediaStoreContainerObj && propsObject.mediaStoreContainerProps) { + errorMessages += 'Error - Either provide mediaStoreContainerProps or existingMediaStoreContainerObj, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/opensearch-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/opensearch-helper.ts index b3844204f..6aa3124e2 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/opensearch-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/opensearch-helper.ts @@ -82,7 +82,10 @@ export function buildOpenSearch(scope: Construct, props: BuildOpenSearchProps): const defaultCfnDomainProps = DefaultOpenSearchCfnDomainProps(props.openSearchDomainName, cognitoDashboardConfigureRole, props); const finalCfnDomainProps = consolidateProps(defaultCfnDomainProps, props.clientDomainProps, constructDrivenProps); - const opensearchDomain = new opensearch.CfnDomain(scope, `OpenSearchDomain`, finalCfnDomainProps); + // tlsSecurityPolicy is set in DefaultOpenSearchCfnDomainProps() - it is the + // default behavior, but Sonarqube cannot follow the program flow to confirm this. + // This is confirmed by the 'Check that TLS 1.2 is the default' test in aws-lambda-opensearch + const opensearchDomain = new opensearch.CfnDomain(scope, `OpenSearchDomain`, finalCfnDomainProps); // NOSONAR addCfnSuppressRules(opensearchDomain, [ { @@ -302,3 +305,21 @@ function createDashboardCognitoRole( cognitoDashboardConfigureRolePolicy.attachToRole(cognitoDashboardConfigureRole); return cognitoDashboardConfigureRole; } + +export interface OpenSearchProps { + readonly openSearchDomainProps?: opensearch.CfnDomainProps; +} + +export function CheckOpenSearchProps(propsObject: OpenSearchProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.openSearchDomainProps?.vpcOptions) { + errorMessages += "Error - Define VPC using construct parameters not the OpenSearch Service props\n"; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/s3-bucket-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/s3-bucket-helper.ts index 7bcf603cf..adcf285f6 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/s3-bucket-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/s3-bucket-helper.ts @@ -61,7 +61,19 @@ export function createLoggingBucket(scope: Construct, const combinedBucketProps = consolidateProps(DefaultS3Props(), loggingBucketProps); // Create the Logging Bucket - const loggingBucket: s3.Bucket = new s3.Bucket(scope, bucketId, combinedBucketProps); + // NOSONAR (typescript:S6281) + // Block Public Access is set by DefaultS3Props, but Sonarqube can't detect it + // It is verified by 's3 bucket with default props' in the unit tests + // NOSONAR (typescript:S6245) + // Encryption is turned on in the default properties that Sonarqube doesn't see + // Verified by unit test 's3 bucket with default props' + // NOSONAR (typescript:S6249) + // enforceSSL is turned on in the default properties that Sonarqube doesn't see + // Verified by unit test 's3 bucket with default props' + // NOSONAR (typescript:typescript:S6249) + // versioning is turned on in the default properties that Sonarqube doesn't see + // Verified by unit test 's3 bucket with default props' + const loggingBucket: s3.Bucket = new s3.Bucket(scope, bucketId, combinedBucketProps); // NOSONAR // Extract the CfnBucket from the loggingBucket const loggingBucketResource = loggingBucket.node.findChild('Resource') as s3.CfnBucket; @@ -94,7 +106,19 @@ export function createAlbLoggingBucket(scope: Construct, const combinedBucketProps = consolidateProps(DefaultS3Props(), loggingBucketProps); // Create the Logging Bucket - const loggingBucket: s3.Bucket = new s3.Bucket(scope, bucketId, combinedBucketProps); + // NOSONAR (typescript:S6281) + // Block Public Access is set by DefaultS3Props, but Sonarqube can't detect it + // It is verified by 's3 bucket with default props' in the unit tests + // NOSONAR (typescript:S6245) + // Encryption is turned on in the default properties that Sonarqube doesn't see + // Verified by unit test 's3 bucket with default props' + // NOSONAR (typescript:S6249) + // enforceSSL is turned on in the default properties that Sonarqube doesn't see + // Verified by unit test 's3 bucket with default props' + // NOSONAR (typescript:typescript:S6249) + // versioning is turned on in the default properties that Sonarqube doesn't see + // Verified by unit test 's3 bucket with default props' + const loggingBucket: s3.Bucket = new s3.Bucket(scope, bucketId, combinedBucketProps); // NOSONAR // Extract the CfnBucket from the loggingBucket const loggingBucketResource = loggingBucket.node.findChild('Resource') as s3.CfnBucket; @@ -163,7 +187,19 @@ export function buildS3Bucket(scope: Construct, const combinedBucketProps = consolidateProps(defaultBucketProps, props.bucketProps); - const s3Bucket: s3.Bucket = new s3.Bucket(scope, resolvedBucketId, combinedBucketProps ); + // NOSONAR (typescript:S6281) - Block Public Access is set by DefaultS3Props, + // but Sonarqube can't detect it + // It is verified by 's3 bucket with default props' in the unit tests + // NOSONAR (typescript:S6245) + // Encryption is turned on in the default properties that Sonarqube doesn't see + // Verified by unit test 's3 bucket with default props' + // NOSONAR (typescript:S6249) + // enforceSSL is turned on in the default properties that Sonarqube doesn't see + // Verified by unit test 's3 bucket with default props' + // NOSONAR (typescript:typescript:S6249) + // versioning is turned on in the default properties that Sonarqube doesn't see + // Verified by unit test 's3 bucket with default props' + const s3Bucket: s3.Bucket = new s3.Bucket(scope, resolvedBucketId, combinedBucketProps ); // NOSONAR return { bucket: s3Bucket, loggingBucket }; } @@ -202,3 +238,41 @@ export function addCfnNagS3BucketNotificationRulesToSuppress(stackRoot: cdk.Stac } ]); } + +export interface S3Props { + readonly existingBucketObj?: s3.Bucket, + readonly existingBucketInterface?: s3.IBucket, + readonly bucketProps?: s3.BucketProps, + readonly existingLoggingBucketObj?: s3.IBucket; + readonly loggingBucketProps?: s3.BucketProps; + readonly logS3AccessLogs?: boolean; +} + +export function CheckS3Props(propsObject: S3Props | any) { + let errorMessages = ''; + let errorFound = false; + + if ((propsObject.existingBucketObj || propsObject.existingBucketInterface) && propsObject.bucketProps) { + errorMessages += 'Error - Either provide bucketProps or existingBucketObj, but not both.\n'; + errorFound = true; + } + + if (propsObject.existingLoggingBucketObj && propsObject.loggingBucketProps) { + errorMessages += 'Error - Either provide existingLoggingBucketObj or loggingBucketProps, but not both.\n'; + errorFound = true; + } + + if ((propsObject?.logS3AccessLogs === false) && (propsObject.loggingBucketProps || propsObject.existingLoggingBucketObj)) { + errorMessages += 'Error - If logS3AccessLogs is false, supplying loggingBucketProps or existingLoggingBucketObj is invalid.\n'; + errorFound = true; + } + + if (propsObject.existingBucketObj && (propsObject.loggingBucketProps || propsObject.logS3AccessLogs)) { + errorMessages += 'Error - If existingBucketObj is provided, supplying loggingBucketProps or logS3AccessLogs is an error.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/sagemaker-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/sagemaker-helper.ts index 9ea8f7786..24e3b84d4 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/sagemaker-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/sagemaker-helper.ts @@ -121,7 +121,7 @@ function addPermissions(role: iam.Role, props?: BuildSagemakerEndpointProps) { ); } - // To create a Sagemaker model using Bring-Your-Own-Model (BYOM) algorith image + // To create a Sagemaker model using Bring-Your-Own-Model (BYOM) algorithm image // The image URL is specified in the modelProps role.addToPolicy( new iam.PolicyStatement({ @@ -240,80 +240,92 @@ export function buildSagemakerNotebook( let subnetId: string; // Conditional Sagemaker Notebook creation - if (!props.existingNotebookObj) { - if ( - (props.sagemakerNotebookProps?.subnetId && props.sagemakerNotebookProps?.securityGroupIds === undefined) || - (props.sagemakerNotebookProps?.subnetId === undefined && props.sagemakerNotebookProps?.securityGroupIds) - ) { - throw new Error('Must define both sagemakerNotebookProps.subnetId and sagemakerNotebookProps.securityGroupIds'); - } + if (props.existingNotebookObj) { + return { notebook: props.existingNotebookObj }; + } - addPermissions(props.role); + if (CheckNotebookVpcProps(props)) { + throw new Error('Must define both sagemakerNotebookProps.subnetId and sagemakerNotebookProps.securityGroupIds'); + } - if (props.sagemakerNotebookProps?.kmsKeyId === undefined) { - kmsKeyId = buildEncryptionKey(scope).keyId; - } else { - kmsKeyId = props.sagemakerNotebookProps.kmsKeyId; - } + addPermissions(props.role); - if (props.deployInsideVpc === undefined || props.deployInsideVpc) { - if ( - props.sagemakerNotebookProps?.subnetId === undefined && - props.sagemakerNotebookProps?.securityGroupIds === undefined - ) { - vpcInstance = buildVpc(scope, { - defaultVpcProps: DefaultPublicPrivateVpcProps(), - }); - securityGroup = buildSecurityGroup( - scope, - 'SecurityGroup', - { - vpc: vpcInstance, - allowAllOutbound: false, - }, - [], - [{ peer: ec2.Peer.anyIpv4(), connection: ec2.Port.tcp(443) }] - ); - - subnetId = vpcInstance.privateSubnets[0].subnetId; - - sagemakerNotebookProps = DefaultSagemakerNotebookProps(props.role.roleArn, kmsKeyId, subnetId, [ - securityGroup.securityGroupId, - ]); - } else { - sagemakerNotebookProps = DefaultSagemakerNotebookProps( - props.role.roleArn, - kmsKeyId, - props.sagemakerNotebookProps?.subnetId, - props.sagemakerNotebookProps?.securityGroupIds - ); - } - } else { - sagemakerNotebookProps = DefaultSagemakerNotebookProps(props.role.roleArn, kmsKeyId); - } + if (props.sagemakerNotebookProps?.kmsKeyId === undefined) { + kmsKeyId = buildEncryptionKey(scope).keyId; + } else { + kmsKeyId = props.sagemakerNotebookProps.kmsKeyId; + } + + if (props.deployInsideVpc === undefined || props.deployInsideVpc) { + if ( + props.sagemakerNotebookProps?.subnetId === undefined && + props.sagemakerNotebookProps?.securityGroupIds === undefined + ) { + vpcInstance = buildVpc(scope, { + defaultVpcProps: DefaultPublicPrivateVpcProps(), + }); + securityGroup = buildSecurityGroup( + scope, + 'SecurityGroup', + { + vpc: vpcInstance, + allowAllOutbound: false, + }, + [], + [{ peer: ec2.Peer.anyIpv4(), connection: ec2.Port.tcp(443) }] + ); - sagemakerNotebookProps = consolidateProps(sagemakerNotebookProps, props.sagemakerNotebookProps); + subnetId = vpcInstance.privateSubnets[0].subnetId; - // Create the notebook - const sagemakerInstance: sagemaker.CfnNotebookInstance = new sagemaker.CfnNotebookInstance( - scope, - 'SagemakerNotebook', - sagemakerNotebookProps - ); - if (vpcInstance) { - return { notebook: sagemakerInstance, vpc: vpcInstance, securityGroup }; + sagemakerNotebookProps = DefaultSagemakerNotebookProps(props.role.roleArn, kmsKeyId, subnetId, [ + securityGroup.securityGroupId, + ]); } else { - return { notebook: sagemakerInstance }; + sagemakerNotebookProps = DefaultSagemakerNotebookProps( + props.role.roleArn, + kmsKeyId, + props.sagemakerNotebookProps?.subnetId, + props.sagemakerNotebookProps?.securityGroupIds + ); } } else { - // Return existing notebook object - return { notebook: props.existingNotebookObj }; + sagemakerNotebookProps = DefaultSagemakerNotebookProps(props.role.roleArn, kmsKeyId); + } + + sagemakerNotebookProps = consolidateProps(sagemakerNotebookProps, props.sagemakerNotebookProps); + + // Create the notebook + // NOSONAR: (typescript:S6319) + // keyID is created above in the if (props.sagemakerNotebookProps?.kmsKeyId === undefined) + // block. It is then passed to DefaultSagemakerNotebookProps() + // This behavior is validated in unit test + const sagemakerInstance: sagemaker.CfnNotebookInstance = new sagemaker.CfnNotebookInstance( + scope, + 'SagemakerNotebook', + sagemakerNotebookProps // NOSONAR + ); + if (vpcInstance) { + return { notebook: sagemakerInstance, vpc: vpcInstance, securityGroup }; + } else { + return { notebook: sagemakerInstance }; + } +} + +/** + * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. + */ +function CheckNotebookVpcProps(props: BuildSagemakerNotebookProps): boolean { + if ((props.sagemakerNotebookProps?.subnetId && props.sagemakerNotebookProps?.securityGroupIds === undefined) || + (props.sagemakerNotebookProps?.subnetId === undefined && props.sagemakerNotebookProps?.securityGroupIds) + ) { + return true; } + return false; } export interface BuildSagemakerEndpointProps { /** - * Existing Sagemaker Enpoint object, if this is set then the modelProps, endpointConfigProps, and endpointProps are ignored + * Existing Sagemaker Endpoint object, if this is set then the modelProps, endpointConfigProps, and endpointProps are ignored * * @default - None */ @@ -538,3 +550,22 @@ export function createSagemakerEndpoint( return endpoint; } + +export interface SagemakerProps { + readonly existingSagemakerEndpointObj?: sagemaker.CfnEndpoint, + readonly endpointProps?: sagemaker.CfnEndpointProps, +} + +export function CheckSagemakerProps(propsObject: SagemakerProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.existingSagemakerEndpointObj && propsObject.endpointProps) { + errorMessages += 'Error - Either provide endpointProps or existingSagemakerEndpointObj, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/secretsmanager-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/secretsmanager-helper.ts index 095c96271..84c0c0d20 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/secretsmanager-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/secretsmanager-helper.ts @@ -16,7 +16,7 @@ * or removed outside of a major release. We recommend against calling them directly from client code. */ -import { Secret, SecretProps } from 'aws-cdk-lib/aws-secretsmanager'; +import * as secrets from 'aws-cdk-lib/aws-secretsmanager'; // Note: To ensure CDKv2 compatibility, keep the import statement for Construct separate import { Construct } from 'constructs'; import { DefaultSecretProps } from './secretsmanager-defaults'; @@ -31,10 +31,10 @@ import { consolidateProps, addCfnSuppressRules } from './utils'; * @param id * @param secretProps */ -export function buildSecretsManagerSecret(scope: Construct, id: string, secretProps?: SecretProps): Secret { - let secret: Secret; +export function buildSecretsManagerSecret(scope: Construct, id: string, secretProps?: secrets.SecretProps): secrets.Secret { + let secret: secrets.Secret; - secret = new Secret(scope, id, consolidateProps(DefaultSecretProps, secretProps)); + secret = new secrets.Secret(scope, id, consolidateProps(DefaultSecretProps, secretProps)); // suppress warning on build addCfnSuppressRules(secret, [ @@ -46,3 +46,22 @@ export function buildSecretsManagerSecret(scope: Construct, id: string, secretPr return secret; } + +export interface SecretsManagerProps { + readonly existingSecretObj?: secrets.Secret; + readonly secretProps?: secrets.SecretProps; +} + +export function CheckSecretsManagerProps(propsObject: SecretsManagerProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.existingSecretObj && propsObject.secretProps) { + errorMessages += 'Error - Either provide secretProps or existingSecretObj, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/sns-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/sns-helper.ts index 5e0c61beb..b82075a24 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/sns-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/sns-helper.ts @@ -160,7 +160,10 @@ export function buildTopic(scope: Construct, props: BuildTopicProps): BuildTopic } // Create the SNS Topic - const topic: sns.Topic = new sns.Topic(scope, 'SnsTopic', snsTopicProps); + // NOSONAR (typescript:S6327) - The masterKey is set in the if statement above, SONAR is + // not catching it. Behavior is confirmed in the + // 'Test deployment with no properties using AWS Managed KMS Key' unit test + const topic: sns.Topic = new sns.Topic(scope, 'SnsTopic', snsTopicProps); // NOSONAR applySecureTopicPolicy(topic); @@ -169,3 +172,42 @@ export function buildTopic(scope: Construct, props: BuildTopicProps): BuildTopic return { topic: props.existingTopicObj, key: props.existingTopicEncryptionKey }; } } + +export interface SnsProps { + readonly topicProps?: sns.TopicProps, + readonly existingTopicObj?: sns.Topic, + readonly existingTopicObject?: sns.Topic, + readonly encryptionKey?: kms.Key, + readonly encryptionKeyProps?: kms.KeyProps +} + +export function CheckSnsProps(propsObject: SnsProps | any) { + let errorMessages = ''; + let errorFound = false; + + // FargateToSns used TopicObject instead of TopicObj - to fix would be a breaking change, so we + // must look for both here. + if (propsObject.topicProps && (propsObject.existingTopicObj || propsObject.existingTopicObject)) { + errorMessages += 'Error - Either provide topicProps or existingTopicObj, but not both.\n'; + errorFound = true; + } + + if (propsObject.topicProps?.masterKey && propsObject.encryptionKey) { + errorMessages += 'Error - Either provide topicProps.masterKey or encryptionKey, but not both.\n'; + errorFound = true; + } + + if (propsObject.topicProps?.masterKey && propsObject.encryptionKeyProps) { + errorMessages += 'Error - Either provide topicProps.masterKey or encryptionKeyProps, but not both.\n'; + errorFound = true; + } + + if (propsObject.encryptionKey && propsObject.encryptionKeyProps) { + errorMessages += 'Error - Either provide encryptionKey or encryptionKeyProps, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/sqs-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/sqs-helper.ts index bd49f1214..4328319a7 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/sqs-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/sqs-helper.ts @@ -76,12 +76,7 @@ export interface BuildQueueResponse { * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ export function buildQueue(scope: Construct, id: string, props: BuildQueueProps): BuildQueueResponse { - - if ((props.queueProps?.encryptionMasterKey || props.encryptionKey || props.encryptionKeyProps) - && props.enableEncryptionWithCustomerManagedKey === true) { - printWarning(`Ignoring enableEncryptionWithCustomerManagedKey because one of - queueProps.encryptionMasterKey, encryptionKey, or encryptionKeyProps was already specified`); - } + CheckEncryptionWarnings(props); // If an existingQueueObj is not specified if (!props.existingQueueObj) { @@ -111,7 +106,11 @@ export function buildQueue(scope: Construct, id: string, props: BuildQueueProps) queueProps.encryptionMasterKey = buildEncryptionKey(scope, props.encryptionKeyProps); } - const queue = new sqs.Queue(scope, id, queueProps); + // NOSONAR (typescript:S6330) + // encryption is set to QueueEncryption.KMS_MANAGED by default in DefaultQueueProps, but + // Sonarqube can't parse the code well enough to see this. Encryption is confirmed by + // the 'Test deployment without imported encryption key' unit test + const queue = new sqs.Queue(scope, id, queueProps); // NOSONAR applySecureQueuePolicy(queue); @@ -123,6 +122,16 @@ export function buildQueue(scope: Construct, id: string, props: BuildQueueProps) } } +/** + * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. + */ +function CheckEncryptionWarnings(props: BuildQueueProps) { + if ((props.queueProps?.encryptionMasterKey || props.encryptionKey || props.encryptionKeyProps) + && props.enableEncryptionWithCustomerManagedKey === true) { + printWarning(`Ignoring enableEncryptionWithCustomerManagedKey because one of + queueProps.encryptionMasterKey, encryptionKey, or encryptionKeyProps was already specified`); + } +} export interface BuildDeadLetterQueueProps { /** * Existing instance of SQS queue object, providing both this and queueProps will cause an error. @@ -218,4 +227,57 @@ function applySecureQueuePolicy(queue: sqs.Queue): void { } }) ); -} \ No newline at end of file +} + +export interface SqsProps { + readonly existingQueueObj?: sqs.Queue, + readonly queueProps?: sqs.QueueProps, + readonly deployDeadLetterQueue?: boolean, + readonly deadLetterQueueProps?: sqs.QueueProps, + readonly encryptionKey?: kms.Key, + readonly encryptionKeyProps?: kms.KeyProps +} + +export function CheckSqsProps(propsObject: SqsProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.existingQueueObj && propsObject.queueProps) { + errorMessages += 'Error - Either provide queueProps or existingQueueObj, but not both.\n'; + errorFound = true; + } + + if (propsObject.queueProps?.encryptionMasterKey && propsObject.encryptionKey) { + errorMessages += 'Error - Either provide queueProps.encryptionMasterKey or encryptionKey, but not both.\n'; + errorFound = true; + } + + if (propsObject.queueProps?.encryptionMasterKey && propsObject.encryptionKeyProps) { + errorMessages += 'Error - Either provide queueProps.encryptionMasterKey or encryptionKeyProps, but not both.\n'; + errorFound = true; + } + + if (propsObject.encryptionKey && propsObject.encryptionKeyProps) { + errorMessages += 'Error - Either provide encryptionKey or encryptionKeyProps, but not both.\n'; + errorFound = true; + } + + if ((propsObject?.deployDeadLetterQueue === false) && propsObject.deadLetterQueueProps) { + errorMessages += 'Error - If deployDeadLetterQueue is false then deadLetterQueueProps cannot be specified.\n'; + errorFound = true; + } + + const isQueueFifo: boolean = propsObject?.queueProps?.fifo; + const isDeadLetterQueueFifo: boolean = propsObject?.deadLetterQueueProps?.fifo; + const deployDeadLetterQueue: boolean = propsObject.deployDeadLetterQueue || propsObject.deployDeadLetterQueue === undefined; + + if (deployDeadLetterQueue && (isQueueFifo !== isDeadLetterQueueFifo)) { + errorMessages += 'Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + + 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/utils.ts b/source/patterns/@aws-solutions-constructs/core/lib/utils.ts index f0a831993..5a0e065cd 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/utils.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/utils.ts @@ -100,7 +100,7 @@ export function printWarning(message: string) { * different stack instances * @param {string[]} parts - the various string components of the name (eg - stackName, solutions construct ID, L2 construct ID) * @param {number} maxLength - the longest string that can be returned - * @returns {string} - a string with concatenated parts (truncated if neccessary) + a hash of the full concatenated parts + * @returns {string} - a string with concatenated parts (truncated if necessary) + a hash of the full concatenated parts * * This is based upon this discussion - https://github.com/aws/aws-cdk/issues/1424 */ @@ -135,7 +135,7 @@ export function generateResourceName( * so it will remain static in multiple updates of a single stack, but will be different in a separate stack instance * @param {string[]} parts - the various string components of the name (eg - stackName, solutions construct ID, L2 construct ID) * @param {number} maxLength - the longest string that can be returned - * @returns {string} - a string with concatenated parts (truncated if neccessary) + a hash of the full concatenated parts + * @returns {string} - a string with concatenated parts (truncated if necessary) + a hash of the full concatenated parts * */ export function generatePhysicalName( @@ -256,3 +256,14 @@ export function generateName(scope: Construct, resourceId: string = ""): string } return name; } + +/** + * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. + */ +export function CheckListValues(allowedPermissions: string[], submittedValues: string[], valueType: string) { + submittedValues.forEach((submittedValue) => { + if (!allowedPermissions.includes(submittedValue)) { + throw Error(`Invalid ${valueType} submitted - ${submittedValue}`); + } + }); +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/vpc-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/vpc-helper.ts index 6ca739ca4..f880b9356 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/vpc-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/vpc-helper.ts @@ -270,4 +270,24 @@ export function retrievePrivateSubnetIds(vpc: ec2.IVpc) { }; return vpc.selectSubnets(subnetSelector).subnetIds; -} \ No newline at end of file +} + +export interface VpcPropsSet { + readonly existingVpc?: ec2.IVpc; + readonly vpcProps?: ec2.VpcProps; + readonly deployVpc?: boolean; +} + +export function CheckVpcProps(propsObject: VpcPropsSet | any) { + let errorMessages = ''; + let errorFound = false; + + if ((propsObject.deployVpc || propsObject.vpcProps) && propsObject.existingVpc) { + errorMessages += 'Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} diff --git a/source/patterns/@aws-solutions-constructs/core/lib/waf-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/waf-helper.ts index 3f4b51c97..67a03a9ea 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/waf-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/waf-helper.ts @@ -50,3 +50,22 @@ export function buildWebacl(scope: Construct, webaclScope: string, props: BuildW return webAcl; } + +export interface WafWebAclProps { + readonly existingWebaclObj: waf.CfnWebACL, + readonly webaclProps: waf.CfnWebACLProps, +} + +export function CheckWafWebAclProps(propsObject: WafWebAclProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.existingWebaclObj && propsObject.webaclProps) { + errorMessages += 'Error - Either provide existingWebaclObj or webaclProps, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/core/test/alb-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/alb-helper.test.ts index cec06de2c..927969687 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/alb-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/alb-helper.test.ts @@ -549,6 +549,54 @@ test('Test sending listenerProps to existingListener error', () => { expect(app).toThrowError("This load balancer already has a listener, listenerProps may not be specified\n"); }); +test('Test sending loadBalancerProps and existingLoadBalancerObj is an error', () => { + const stack = new Stack(); + + const vpc = defaults.buildVpc(stack, { + defaultVpcProps: defaults.DefaultPublicPrivateVpcProps(), + }); + + const existingLoadBalancer = new elb.ApplicationLoadBalancer(stack, 'load-balancer', { + vpc, + internetFacing: true, + loadBalancerName: 'unique-name' + }); + + const props = { + vpc, + existingLoadBalancerObj: existingLoadBalancer, + loadBalancerProps: { + loadBalancerName: 'new-loadbalancer', + vpc, + internetFacing: true + } + }; + + const app = () => { + defaults.CheckAlbProps(props); + }; + + expect(app).toThrowError("Error - Either provide loadBalancerProps or existingLoadBalancerObj, but not both.\n"); +}); + +test('Test sending albLoggingBucketProps when logAlbAccessLogs is false is an error', () => { + + const props = { + logAlbAccessLogs: false, + albLoggingBucketProps: {}, + loadBalancerProps: { + loadBalancerName: 'new-loadbalancer', + internetFacing: true + } + }; + + const app = () => { + defaults.CheckAlbProps(props); + }; + + expect(app).toThrowError("Error - If logAlbAccessLogs is false, supplying albLoggingBucketProps is invalid.\n"); +}); + test('Test sending VPC in loadBalancerProps error', () => { const props = { loadBalancerProps: { diff --git a/source/patterns/@aws-solutions-constructs/core/test/cloudfront-distribution-s3-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/cloudfront-distribution-s3-helper.test.ts index 047d61509..71bf22f6f 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/cloudfront-distribution-s3-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/cloudfront-distribution-s3-helper.test.ts @@ -21,6 +21,7 @@ import { Bucket } from 'aws-cdk-lib/aws-s3'; import * as origins from 'aws-cdk-lib/aws-cloudfront-origins'; import { LambdaEdgeEventType } from 'aws-cdk-lib/aws-cloudfront'; import * as acm from 'aws-cdk-lib/aws-certificatemanager'; +import * as defaults from '../'; test('check bucket policy metadata', () => { const stack = new Stack(); @@ -539,3 +540,23 @@ test('test cloudfront override cloudfront custom domain names ', () => { } }); }); + +// --------------------------- +// Prop Tests +// --------------------------- +test('Test CloudFront insertHttpHeaders bad props', () => { + + const props: defaults.CloudFrontProps = { + insertHttpSecurityHeaders: true, + responseHeadersPolicyProps: { + securityHeadersBehavior: {} + } + }; + + const app = () => { + defaults.CheckCloudFrontProps(props); + }; + + // Assertion + expect(app).toThrowError('responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/dynamo-table.test.ts b/source/patterns/@aws-solutions-constructs/core/test/dynamo-table.test.ts index 70c50ee08..c995e14b7 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/dynamo-table.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/dynamo-table.test.ts @@ -421,74 +421,37 @@ test('test getPartitionKeyNameFromTable()', () => { expect(testKeyName).toEqual(partitionKeyName); }); -test('Test providing both existingTableInterface and existingTableObj', () => { +// --------------------------- +// Prop Tests +// --------------------------- +test('Test fail DynamoDB table check', () => { const stack = new Stack(); - const tableProps: dynamodb.TableProps = { - partitionKey: { - name: 'table_id', - type: dynamodb.AttributeType.STRING - }, - stream: dynamodb.StreamViewType.NEW_IMAGE + const props: defaults.DynamoDBProps = { + existingTableObj: new dynamodb.Table(stack, 'placeholder', defaults.DefaultTableProps), + dynamoTableProps: defaults.DefaultTableProps, }; - const existingTableInterface = new dynamodb.Table(stack, 'DynamoTable', tableProps) - ; - const newProps = { - existingTableInterface, - existingTableObj: existingTableInterface - }; const app = () => { - defaults.buildDynamoDBTable(stack, newProps); + defaults.CheckDynamoDBProps(props); }; - expect(app).toThrowError('Error - Either provide existingTableInterface or existingTableObj, but not both.\n'); + // Assertion + expect(app).toThrowError('Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'); }); -test('Test providing both existingTableInterface and dynamoTableProps', () => { +test('Test fail DynamoDB table check (for interface AND obj)', () => { const stack = new Stack(); - const dynamoTableProps: dynamodb.TableProps = { - partitionKey: { - name: 'table_id', - type: dynamodb.AttributeType.STRING - }, - stream: dynamodb.StreamViewType.NEW_IMAGE + const props: defaults.DynamoDBProps = { + existingTableInterface: new dynamodb.Table(stack, 'placeholder', defaults.DefaultTableProps), + existingTableObj: new dynamodb.Table(stack, 'placeholderobj', defaults.DefaultTableProps), }; - const existingTableInterface = new dynamodb.Table(stack, 'DynamoTable', dynamoTableProps) - ; - const newProps = { - existingTableInterface, - dynamoTableProps - }; const app = () => { - defaults.buildDynamoDBTable(stack, newProps); + defaults.CheckDynamoDBProps(props); }; - expect(app).toThrowError('Error - Either provide existingTableInterface or dynamoTableProps, but not both.\n'); + // Assertion + expect(app).toThrowError('Error - Either provide existingTableInterface or existingTableObj, but not both.\n'); }); - -test('Test providing both existingTableObj and dynamoTableProps', () => { - const stack = new Stack(); - - const dynamoTableProps: dynamodb.TableProps = { - partitionKey: { - name: 'table_id', - type: dynamodb.AttributeType.STRING - }, - stream: dynamodb.StreamViewType.NEW_IMAGE - }; - - const existingTableObj = new dynamodb.Table(stack, 'DynamoTable', dynamoTableProps) - ; - const newProps = { - existingTableObj, - dynamoTableProps - }; - const app = () => { - defaults.buildDynamoDBTable(stack, newProps); - }; - - expect(app).toThrowError('Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'); -}); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/core/test/eventbridge-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/eventbridge-helper.test.ts index a9b81c64f..c2b4c0b9a 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/eventbridge-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/eventbridge-helper.test.ts @@ -63,4 +63,24 @@ test('Test deployment with new EventBus with props', () => { Template.fromStack(stack).hasResourceProperties('AWS::Events::EventBus', { Name: 'testneweventbus' }); -}); \ No newline at end of file +}); + +// --------------------------- +// Prop Tests +// --------------------------- + +test('Test fail EventBridge bad bus props', () => { + const stack = new Stack(); + + const props: defaults.EventBridgeProps = { + existingEventBusInterface: new events.EventBus(stack, 'test', {}), + eventBusProps: {} + }; + + const app = () => { + defaults.CheckEventBridgeProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide existingEventBusInterface or eventBusProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/fargate-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/fargate-helper.test.ts index 0bbe984cc..c49bc067a 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/fargate-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/fargate-helper.test.ts @@ -343,7 +343,7 @@ test('Check providing vpc in the targetGroupsProps is an error', () => { defaults.CheckFargateProps(props); }; - expect(app).toThrowError("Provide all VPC info at Construct level, not within targetGroupProps\n"); + expect(app).toThrowError("Provide all VPC info at Construct level, not within clusterProps nor targetGroupProps\n"); }); test('Check providing taskDefinition in the fargateServiceProps is an error', () => { @@ -380,7 +380,7 @@ test('Check providing vpc in clusterProps is an error', () => { defaults.CheckFargateProps(props); }; - expect(app).toThrowError("All services in the construct use the construct VPC, you cannot specify a VPC in clusterProps\n"); + expect(app).toThrowError("Provide all VPC info at Construct level, not within clusterProps nor targetGroupProps\n"); }); test('Check providing existing service without existing container and existing VPC is an error', () => { diff --git a/source/patterns/@aws-solutions-constructs/core/test/glue-job-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/glue-job-helper.test.ts index 171811669..9a2e159d8 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/glue-job-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/glue-job-helper.test.ts @@ -18,10 +18,8 @@ import { Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; import { Bucket, BucketEncryption } from 'aws-cdk-lib/aws-s3'; import { RemovalPolicy, Stack } from "aws-cdk-lib"; import * as defaults from '..'; +import * as iam from 'aws-cdk-lib/aws-iam'; -// -------------------------------------------------------------- -// Test deployment with role creation -// -------------------------------------------------------------- test('Test deployment with role creation', () => { // Stack const stack = new Stack(); @@ -75,9 +73,6 @@ test('Test deployment with role creation', () => { }); }); -// -------------------------------------------------------------- -// Pass an existing Glue Job -// -------------------------------------------------------------- test('Create a Glue Job outside the construct', () => { // Stack const stack = new Stack(); @@ -138,9 +133,6 @@ test('Create a Glue Job outside the construct', () => { }); }); -// -------------------------------------------------------------- -// Provide additional parameters other than default ones -// -------------------------------------------------------------- test('Test custom deployment properties', () => { // Stack const stack = new Stack(); @@ -252,9 +244,6 @@ test('Test custom deployment properties', () => { }); }); -// -------------------------------------------------------------- -// Do not supply parameters and error out -// -------------------------------------------------------------- test('Do no supply glueJobProps or existingCfnJob and error out', () => { const stack = new Stack(); try { @@ -275,10 +264,7 @@ test('Do no supply glueJobProps or existingCfnJob and error out', () => { } }); -// -------------------------------------------------------------- -// Allow the construct to create the job role required -// -------------------------------------------------------------- -test('Test deployment with role creation', () => { +test('llow the construct to create the job role required', () => { // Stack const stack = new Stack(); const jobID = 'glueetl'; @@ -318,15 +304,12 @@ test('Test deployment with role creation', () => { }], Version: "2012-10-17" }, - Description: "Service role that Glue custom ETL jobs will assume for exeuction" + Description: "Service role that Glue custom ETL jobs will assume for execution" } }); }); -// -------------------------------------------------------------- -// Test deployment when output location is provided -// -------------------------------------------------------------- -test('Test deployment with role creation', () => { +test('Test deployment when output location is provided', () => { // Stack const stack = new Stack(); const jobID = 'glueetl'; @@ -376,49 +359,6 @@ test('Test deployment with role creation', () => { }); }); -// -------------------------------------------------------------- -// Test deployment when script location not provided - throw error -// -------------------------------------------------------------- -test('Test deployment with role creation', () => { - // Stack - const stack = new Stack(); - const jobID = 'glueetl'; - - const cfnJobProps = { - command: { - name: jobID, - pythonVersion: '3' - } - }; - - const database = defaults.createGlueDatabase(stack); - try { - defaults.buildGlueJob(stack, { - glueJobProps: cfnJobProps, - outputDataStore: { - datastoreType: defaults.SinkStoreType.S3, - existingS3OutputBucket: new Bucket(stack, 'OutputBucket', { - versioned: false - }) - }, - database, - table: defaults.createGlueTable(stack, database, undefined, [{ - name: "id", - type: "int", - comment: "" - }], 'kinesis', {STREAM_NAME: 'testStream'}) - }); - } catch (error) { - expect(error).toBeInstanceOf(Error); - expect(error.message).toEqual('Either one of CfnJob.JobCommandProperty.scriptLocation or KinesisstreamsToGluejobProps.etlCodeAsset ' + - 'has to be provided. If the ETL Job code file exists in a local filesystem, please set KinesisstreamsToGluejobProps.etlCodeAsset. ' + - 'If the ETL Job is available in an S3 bucket, set the CfnJob.JobCommandProperty.scriptLocation property'); - } -}); - -// -------------------------------------------------------------- -// Dont pass Job Command attributes and it should throw an error -// -------------------------------------------------------------- test('Test for incorrect Job Command property', () => { const stack = new Stack(); try { @@ -489,9 +429,6 @@ test('GlueJob configuration with glueVersion 2.0 should not support maxCapacity } }); -// -------------------------------------------------------------- -// Fail if setting maxCapacity and WorkerType/ NumberOfWorkers -// -------------------------------------------------------------- test('Cannot use maxCapacity and WorkerType, so error out', () => { const stack = new Stack(); try { @@ -578,4 +515,104 @@ test('Cannot use maxCapacity and WorkerType, so error out', () => { } catch (error) { expect(error).toBeInstanceOf(Error); } -}); \ No newline at end of file +}); + +// --------------------------- +// Prop Tests +// --------------------------- +test('Test fail Glue job check', () => { + const stack = new Stack(); + + const _jobRole = new iam.Role(stack, 'CustomETLJobRole', { + assumedBy: new iam.ServicePrincipal('glue.amazonaws.com') + }); + + const jobProps: CfnJobProps = defaults.DefaultGlueJobProps(_jobRole, { + command: { + name: 'glueetl', + pythonVersion: '3', + scriptLocation: new Bucket(stack, 'ScriptBucket').bucketArn, + }, + role: new iam.Role(stack, 'JobRole', { + assumedBy: new iam.ServicePrincipal('glue.amazonaws.com') + }).roleArn + }, 'testETLJob', {}); + + const job = new CfnJob(stack, 'placeholder', jobProps); + + const props: defaults.GlueProps = { + glueJobProps: jobProps, + existingGlueJob: job + }; + + const app = () => { + defaults.CheckGlueProps(props); + }; + + // Assertion + expect(app).toThrowError("Error - Either provide glueJobProps or existingGlueJob, but not both.\n"); +}); + +test('Test bad Glue script location', () => { + const stack = new Stack(); + + const _jobRole = new iam.Role(stack, 'CustomETLJobRole', { + assumedBy: new iam.ServicePrincipal('glue.amazonaws.com') + }); + + const jobProps: CfnJobProps = defaults.DefaultGlueJobProps(_jobRole, { + command: { + name: 'glueetl', + pythonVersion: '3', + scriptLocation: "s://bad/url", + }, + role: new iam.Role(stack, 'JobRole', { + assumedBy: new iam.ServicePrincipal('glue.amazonaws.com') + }).roleArn + }, 'testETLJob', {}); + + const props: defaults.GlueProps = { + glueJobProps: jobProps, + }; + + const app = () => { + defaults.CheckGlueProps(props); + }; + + // Assertion + expect(app).toThrowError('Invalid S3 URL for Glue script provided\n'); +}); + +test('Test missing Glue script location', () => { + const stack = new Stack(); + + const _jobRole = new iam.Role(stack, 'CustomETLJobRole', { + assumedBy: new iam.ServicePrincipal('glue.amazonaws.com') + }); + + const jobProps: CfnJobProps = defaults.DefaultGlueJobProps(_jobRole, { + command: { + name: 'glueetl', + pythonVersion: '3', + }, + role: new iam.Role(stack, 'JobRole', { + assumedBy: new iam.ServicePrincipal('glue.amazonaws.com') + }).roleArn + }, 'testETLJob', {}); + + const props: defaults.GlueProps = { + glueJobProps: jobProps, + }; + + const app = () => { + defaults.CheckGlueProps(props); + }; + + const expectedError: string = 'Either one of CfnJob.JobCommandProperty.scriptLocation or etlCodeAsset has ' + + 'to be provided. If the ETL Job code file exists in a local filesystem, please set ' + + 'KinesisstreamsToGluejobProps.etlCodeAsset. If the ETL Job is available in an S3 bucket, set the ' + + 'CfnJob.JobCommandProperty.scriptLocation property\n'; + + // Assertion + expect(app).toThrowError(expectedError); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/input-validation.test.ts b/source/patterns/@aws-solutions-constructs/core/test/input-validation.test.ts deleted file mode 100644 index fb991db03..000000000 --- a/source/patterns/@aws-solutions-constructs/core/test/input-validation.test.ts +++ /dev/null @@ -1,593 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance - * with the License. A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions - * and limitations under the License. - */ - -// Imports -import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; -import * as glue from 'aws-cdk-lib/aws-glue'; -import * as iam from 'aws-cdk-lib/aws-iam'; -import * as kinesis from 'aws-cdk-lib/aws-kinesis'; -import * as kms from 'aws-cdk-lib/aws-kms'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; -import * as mediastore from 'aws-cdk-lib/aws-mediastore'; -import * as s3 from 'aws-cdk-lib/aws-s3'; -import * as sns from 'aws-cdk-lib/aws-sns'; -import * as sqs from 'aws-cdk-lib/aws-sqs'; -import { Stack } from 'aws-cdk-lib'; -import * as defaults from '../'; -import { MediaStoreContainerProps } from '../lib/mediastore-defaults'; -import { BuildSagemakerEndpoint } from '../lib/sagemaker-helper'; -import { CreateScrapBucket } from './test-helper'; - -test('Test with valid props', () => { - const props: defaults.VerifiedProps = { - }; - - defaults.CheckProps(props); -}); - -test('Test fail DynamoDB table check', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - existingTableObj: new dynamodb.Table(stack, 'placeholder', defaults.DefaultTableProps), - dynamoTableProps: defaults.DefaultTableProps, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'); -}); - -test("Test fail Lambda function check", () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - lambdaFunctionProps: { - code: lambda.Code.fromAsset(`${__dirname}/lambda`), - runtime: lambda.Runtime.NODEJS_16_X, - handler: "index.handler", - }, - existingLambdaObj: new lambda.Function(stack, "placeholder", { - code: lambda.Code.fromAsset(`${__dirname}/lambda`), - runtime: lambda.Runtime.NODEJS_16_X, - handler: "index.handler", - }), - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError( - "Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n" - ); -}); - -test("Test fail SQS Queue check", () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - queueProps: {}, - existingQueueObj: new sqs.Queue(stack, 'placeholder', {}), - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide queueProps or existingQueueObj, but not both.\n'); -}); - -test('Test fail SQS queue check when queueProps.encryptionMasterKey and encryptionKey are both specified', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - queueProps: { - encryptionMasterKey: new kms.Key(stack, 'key') - }, - encryptionKey: new kms.Key(stack, 'otherkey') - }; - - const app = () => { - defaults.CheckProps(props); - }; - - expect(app).toThrowError('Error - Either provide queueProps.encryptionMasterKey or encryptionKey, but not both.\n'); -}); - -test('Test fail SQS queue check when queueProps.encryptionMasterKey and encryptionKeyProps are both specified', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - encryptionKeyProps: { - description: 'key description' - }, - queueProps: { - encryptionMasterKey: new kms.Key(stack, 'key') - } - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide queueProps.encryptionMasterKey or encryptionKeyProps, but not both.\n'); -}); - -test('Test fail Dead Letter Queue check', () => { - - const props: defaults.VerifiedProps = { - deployDeadLetterQueue: false, - deadLetterQueueProps: {}, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - If deployDeadLetterQueue is false then deadLetterQueueProps cannot be specified.\n'); -}); - -test('Test fail Dead Letter Queue check with queueProps fifo set to true and undefined deadLetterQueueProps', () => { - - const props: defaults.VerifiedProps = { - queueProps: {fifo: true}, - deadLetterQueueProps: {}, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + - 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); -}); - -test('Test fail Dead Letter Queue check with queueProps fifo set to true and deadLetterQueueProps fifo set to false', () => { - - const props: defaults.VerifiedProps = { - queueProps: {fifo: true}, - deadLetterQueueProps: {fifo: false}, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + - 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); -}); - -test('Test fail Dead Letter Queue check with queueProps fifo set to false and deadLetterQueueProps fifo set to true', () => { - - const props: defaults.VerifiedProps = { - deadLetterQueueProps: {fifo: true}, - queueProps: {fifo: false}, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + - 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); -}); - -test('Test fail Dead Letter Queue check with deadLetterQueueProps fifo set to true', () => { - - const props: defaults.VerifiedProps = { - deadLetterQueueProps: {fifo: true}, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + - 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); -}); - -test('Test fail Dead Letter Queue check with queueProps fifo set to false', () => { - - const props: defaults.VerifiedProps = { - queueProps: {fifo: false}, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + - 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); -}); - -test("Test fail MediaStore container check", () => { - const stack = new Stack(); - - const mediaStoreContainer = new mediastore.CfnContainer( - stack, - "placeholder", - MediaStoreContainerProps() - ); - - const props: defaults.VerifiedProps = { - mediaStoreContainerProps: MediaStoreContainerProps(), - existingMediaStoreContainerObj: mediaStoreContainer, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError( - "Error - Either provide mediaStoreContainerProps or existingMediaStoreContainerObj, but not both.\n" - ); -}); - -test('Test fail Kinesis stream check', () => { - const stack = new Stack(); - - const stream = new kinesis.Stream(stack, 'placeholder', { - - }); - - const props: defaults.VerifiedProps = { - existingStreamObj: stream, - kinesisStreamProps: {} - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'); -}); - -test('Test fail S3 check', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - existingBucketObj: CreateScrapBucket(stack, { }), - bucketProps: {}, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); -}); - -test('Test fail SNS topic check', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - topicProps: {}, - existingTopicObj: new sns.Topic(stack, 'placeholder', {}) - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide topicProps or existingTopicObj, but not both.\n'); -}); - -test('Test fail SNS topic check with bad topic attribute name', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - topicProps: {}, - existingTopicObj: new sns.Topic(stack, 'placeholder', {}) - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide topicProps or existingTopicObj, but not both.\n'); -}); - -test('Test fail SNS topic check when both encryptionKey and encryptionKeyProps are specified', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - encryptionKey: new kms.Key(stack, 'key'), - encryptionKeyProps: { - description: 'a description' - } - }; - - const app = () => { - defaults.CheckProps(props); - }; - - expect(app).toThrowError('Error - Either provide encryptionKey or encryptionKeyProps, but not both.\n'); -}); - -test('Test fail SNS topic check when both topicProps.masterKey and encryptionKeyProps are specified', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - topicProps: { - masterKey: new kms.Key(stack, 'key') - }, - encryptionKeyProps: { - description: 'a description' - } - }; - - const app = () => { - defaults.CheckProps(props); - }; - - expect(app).toThrowError('Error - Either provide topicProps.masterKey or encryptionKeyProps, but not both.\n'); -}); - -test('Test fail SNS topic check when both encryptionKey and topicProps.masterKey are specified', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - encryptionKey: new kms.Key(stack, 'key'), - topicProps: { - masterKey: new kms.Key(stack, 'otherkey') - } - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide topicProps.masterKey or encryptionKey, but not both.\n'); -}); - -test('Test fail Glue job check', () => { - const stack = new Stack(); - - const _jobRole = new iam.Role(stack, 'CustomETLJobRole', { - assumedBy: new iam.ServicePrincipal('glue.amazonaws.com') - }); - - const jobProps: glue.CfnJobProps = defaults.DefaultGlueJobProps(_jobRole, { - command: { - name: 'glueetl', - pythonVersion: '3', - scriptLocation: new s3.Bucket(stack, 'ScriptBucket').bucketArn, - }, - role: new iam.Role(stack, 'JobRole', { - assumedBy: new iam.ServicePrincipal('glue.amazonaws.com') - }).roleArn}, 'testETLJob', {}); - - const job = new glue.CfnJob(stack, 'placeholder', jobProps); - - const props: defaults.VerifiedProps = { - glueJobProps: jobProps, - existingGlueJob: job - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide glueJobProps or existingGlueJob, but not both.\n'); -}); - -test('Test fail SageMaker endpoint check', () => { - const stack = new Stack(); - - // Build Sagemaker Inference Endpoint - const modelProps = { - primaryContainer: { - image: ".dkr.ecr..amazonaws.com/linear-learner:latest", - modelDataUrl: "s3:////model.tar.gz", - }, - }; - - const buildSagemakerEndpointResponse = BuildSagemakerEndpoint(stack, { modelProps }); - - const props: defaults.VerifiedProps = { - existingSagemakerEndpointObj: buildSagemakerEndpointResponse.endpoint, - endpointProps: { - endpointConfigName: 'placeholder' - } - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide endpointProps or existingSagemakerEndpointObj, but not both.\n'); -}); - -test('Test fail Secret check', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - secretProps: {}, - existingSecretObj: defaults.buildSecretsManagerSecret(stack, 'secret', {}), - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide secretProps or existingSecretObj, but not both.\n'); -}); - -test('Test fail encryption key check', () => { - const stack = new Stack(); - - const key = defaults.buildEncryptionKey(stack, { - enableKeyRotation: false - }); - - const props: defaults.VerifiedProps = { - encryptionKey: key, - encryptionKeyProps: {}, - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide encryptionKey or encryptionKeyProps, but not both.\n'); -}); - -test('Test fail Vpc check with deployVpc', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - deployVpc: true, - existingVpc: defaults.buildVpc(stack, { - defaultVpcProps: defaults.DefaultPublicPrivateVpcProps(), - }), - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); -}); - -test('Test fail Vpc check with vpcProps', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - vpcProps: defaults.DefaultPublicPrivateVpcProps(), - existingVpc: defaults.buildVpc(stack, { - defaultVpcProps: defaults.DefaultPublicPrivateVpcProps(), - }), - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); -}); - -test('Test fail multiple failures message', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - secretProps: {}, - existingSecretObj: defaults.buildSecretsManagerSecret(stack, 'secret', {}), - topicProps: {}, - existingTopicObj: new sns.Topic(stack, 'placeholder', {}) - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError( - 'Error - Either provide topicProps or existingTopicObj, but not both.\n' + - 'Error - Either provide secretProps or existingSecretObj, but not both.\n' - ); -}); - -test('Test fail existing log bucket and log bucket prop check', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - existingLoggingBucketObj: new s3.Bucket(stack, 'logging-bucket'), - loggingBucketProps: { - autoDeleteObjects: true - } - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - Either provide existingLoggingBucketObj or loggingBucketProps, but not both.\n'); -}); - -test('Test fail false logS3Accesslogs and loggingBucketProps check', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - existingLoggingBucketObj: new s3.Bucket(stack, 'logging-bucket'), - logS3AccessLogs: false - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - If logS3AccessLogs is false, supplying loggingBucketProps or existingLoggingBucketObj is invalid.\n'); -}); - -test('Test fail existingBucketObj and loggingBucketProps check', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - existingBucketObj: new s3.Bucket(stack, 'temp-bucket'), - loggingBucketProps: { - autoDeleteObjects: true - } - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError('Error - If existingBucketObj is provided, supplying loggingBucketProps or logS3AccessLogs is an error.\n'); -}); - -test('Test successful CheckListValues', () => { - - const app = () => { - defaults.CheckListValues(['one', 'two', 'four'], ['four', 'one'], 'test value'); - }; - - // Assertion - expect(app).not.toThrowError(); -}); - -test('Test unsuccessful CheckListValues', () => { - - const app = () => { - defaults.CheckListValues(['one', 'two', 'four'], ['four', 'three'], 'test value'); - }; - - // Assertion - expect(app).toThrowError('Invalid test value submitted - three'); -}); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/core/test/kendra-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/kendra-helper.test.ts index 8e934d19a..6bec8b6eb 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/kendra-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/kendra-helper.test.ts @@ -30,7 +30,7 @@ test('Launch Kendra index with defaults', () => { template.resourceCountIs("AWS::IAM::Role", 1); }); -test('Confirm kendra has log wrting privileges', () => { +test('Confirm kendra has log writing privileges', () => { const stack = new Stack(undefined, undefined); buildKendraIndex(stack, 'test', {}); @@ -372,7 +372,7 @@ test('Confirm error if does not provide DataSource configuration', () => { AddKendraDataSource(stack, 'test-bad-source', testIndex, dataSourceProps); }; - expect(app).toThrowError(/Error - an S3 Kendra DataSource requires an DataSourceCofiguration prop/); + expect(app).toThrowError(/Error - an S3 Kendra DataSource requires an DataSourceConfiguration prop/); }); test('Confirm error if does not provide S3 DataSource configuration', () => { @@ -392,7 +392,7 @@ test('Confirm error if does not provide S3 DataSource configuration', () => { AddKendraDataSource(stack, 'test-bad-source', testIndex, dataSourceProps); }; - expect(app).toThrowError(/Error - an S3 Kendra DataSource requires an DataSourceCofiguration.S3Configuration prop/); + expect(app).toThrowError(/Error - an S3 Kendra DataSource requires an DataSourceConfiguration.S3Configuration prop/); }); test('Confirm error if does not provide S3 Bucketname', () => { @@ -415,7 +415,7 @@ test('Confirm error if does not provide S3 Bucketname', () => { AddKendraDataSource(stack, 'test-bad-source', testIndex, dataSourceProps); }; - expect(app).toThrowError(/Error - an S3 Kendra DataSource requires the DataSourceCofiguration.S3Configuration.bucketName prop/); + expect(app).toThrowError(/Error - an S3 Kendra DataSource requires the DataSourceConfiguration.S3Configuration.bucketName prop/); }); test('Launch Kendra index with multiple data sources', () => { @@ -552,4 +552,4 @@ test('Confirm successful operation of normalizeKendraPermissions()', () => { }; expect(app).toThrowError(/Invalid indexPermission value - valid values are "READ", "SUBMITFEEDBACK" and "WRITE"/); -}); \ No newline at end of file +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/kinesis-streams-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/kinesis-streams-helper.test.ts index 485c3430b..12e63a482 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/kinesis-streams-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/kinesis-streams-helper.test.ts @@ -17,9 +17,6 @@ import * as defaults from '../'; import * as kinesis from 'aws-cdk-lib/aws-kinesis'; import { Template } from 'aws-cdk-lib/assertions'; -// -------------------------------------------------------------- -// Test minimal deployment with no properties -// -------------------------------------------------------------- test('Test minimal deployment with no properties', () => { // Stack const stack = new Stack(); @@ -36,9 +33,6 @@ test('Test minimal deployment with no properties', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ custom properties -// -------------------------------------------------------------- test('Test deployment w/ custom properties', () => { // Stack const stack = new Stack(); @@ -63,9 +57,6 @@ test('Test deployment w/ custom properties', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ existing stream -// -------------------------------------------------------------- test('Test deployment w/ existing stream', () => { // Stack const stack = new Stack(); @@ -97,4 +88,27 @@ test('Count Kinesis CW Alarms', () => { const cwList = defaults.buildKinesisStreamCWAlarms(stack); expect(cwList.length).toEqual(2); -}); \ No newline at end of file +}); + +// --------------------------- +// Prop Tests +// --------------------------- +test('Test fail Kinesis stream check', () => { + const stack = new Stack(); + + const stream = new kinesis.Stream(stack, 'placeholder', { + + }); + + const props: defaults.KinesisStreamProps = { + existingStreamObj: stream, + kinesisStreamProps: {} + }; + + const app = () => { + defaults.CheckKinesisStreamProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/lambda-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/lambda-helper.test.ts index 99b0c6d99..00a521ac8 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/lambda-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/lambda-helper.test.ts @@ -504,7 +504,7 @@ test('buildLambdaFunction uses constructId when specified', () => { }); }); -// specifying constructId takes precendence over functionName for setting the +// specifying constructId takes precedence over functionName for setting the // underlying lambda function and iam role construct ids. test('buildLambdaFunction uses constructId when both constructId and functionName are specified', () => { const stack = new Stack(); @@ -561,3 +561,32 @@ test('buildLambdaFunction uses default name when neither constructId or function }, }); }); + +// --------------------------- +// Prop Tests +// --------------------------- +test("Test fail Lambda function check", () => { + const stack = new Stack(); + + const props: defaults.LambdaProps = { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: "index.handler", + }, + existingLambdaObj: new lambda.Function(stack, "placeholder", { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: "index.handler", + }), + }; + + const app = () => { + defaults.CheckLambdaProps(props); + }; + + // Assertion + expect(app).toThrowError( + "Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n" + ); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/mediastore-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/mediastore-helper.test.ts index b2c2e295c..8e8746dea 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/mediastore-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/mediastore-helper.test.ts @@ -15,6 +15,8 @@ import { Template } from 'aws-cdk-lib/assertions'; import { Stack } from 'aws-cdk-lib'; import * as mediastore from 'aws-cdk-lib/aws-mediastore'; import { MediaStoreContainer } from '../lib/mediastore-helper'; +import { MediaStoreContainerProps } from '../lib/mediastore-defaults'; +import * as defaults from '../'; test('MediaStore container override params', () => { const stack = new Stack(); @@ -46,4 +48,31 @@ test('MediaStore container override params', () => { LifecyclePolicy: '{}', ContainerName: 'TestContainer' }); -}); \ No newline at end of file +}); + +// --------------------------- +// Prop Tests +// --------------------------- +test("Test fail MediaStore container check", () => { + const stack = new Stack(); + + const mediaStoreContainer = new mediastore.CfnContainer( + stack, + "placeholder", + MediaStoreContainerProps() + ); + + const props: defaults.MediaStoreProps = { + mediaStoreContainerProps: MediaStoreContainerProps(), + existingMediaStoreContainerObj: mediaStoreContainer, + }; + + const app = () => { + defaults.CheckMediaStoreProps(props); + }; + + // Assertion + expect(app).toThrowError( + "Error - Either provide mediaStoreContainerProps or existingMediaStoreContainerObj, but not both.\n" + ); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/s3-bucket.test.ts b/source/patterns/@aws-solutions-constructs/core/test/s3-bucket.test.ts index b3e5b0176..f36fd43e8 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/s3-bucket.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/s3-bucket.test.ts @@ -18,6 +18,7 @@ import * as defaults from '../index'; import { overrideProps } from '../lib/utils'; import { Template } from 'aws-cdk-lib/assertions'; import { expectNonexistence } from "./test-helper"; +import { CreateScrapBucket } from './test-helper'; test('test s3Bucket override versioningConfiguration', () => { const stack = new Stack(); @@ -359,4 +360,75 @@ test('Test enforcing SSL when bucketProps is provided and enforceSSL is not set' Version: "2012-10-17" } }); -}); \ No newline at end of file +}); + +// --------------------------- +// Prop Tests +// --------------------------- +test('Test fail S3 check', () => { + const stack = new Stack(); + + const props: defaults.S3Props = { + existingBucketObj: CreateScrapBucket(stack, {}), + bucketProps: {}, + }; + + const app = () => { + defaults.CheckS3Props(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); +}); + +test('Test fail existing log bucket and log bucket prop check', () => { + const stack = new Stack(); + + const props: defaults.S3Props = { + existingLoggingBucketObj: new s3.Bucket(stack, 'logging-bucket'), + loggingBucketProps: { + autoDeleteObjects: true + } + }; + + const app = () => { + defaults.CheckS3Props(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide existingLoggingBucketObj or loggingBucketProps, but not both.\n'); +}); + +test('Test fail false logS3Accesslogs and loggingBucketProps check', () => { + const stack = new Stack(); + + const props: defaults.S3Props = { + existingLoggingBucketObj: new s3.Bucket(stack, 'logging-bucket'), + logS3AccessLogs: false + }; + + const app = () => { + defaults.CheckS3Props(props); + }; + + // Assertion + expect(app).toThrowError('Error - If logS3AccessLogs is false, supplying loggingBucketProps or existingLoggingBucketObj is invalid.\n'); +}); + +test('Test fail existingBucketObj and loggingBucketProps check', () => { + const stack = new Stack(); + + const props: defaults.S3Props = { + existingBucketObj: new s3.Bucket(stack, 'temp-bucket'), + loggingBucketProps: { + autoDeleteObjects: true + } + }; + + const app = () => { + defaults.CheckS3Props(props); + }; + + // Assertion + expect(app).toThrowError('Error - If existingBucketObj is provided, supplying loggingBucketProps or logS3AccessLogs is an error.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/sagemaker-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/sagemaker-helper.test.ts index ac6e09bc8..d496d5633 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/sagemaker-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/sagemaker-helper.test.ts @@ -17,6 +17,7 @@ import * as kms from 'aws-cdk-lib/aws-kms'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as defaults from '../'; import { Template } from 'aws-cdk-lib/assertions'; +import { BuildSagemakerEndpoint } from '../lib/sagemaker-helper'; test('Test deployment with VPC', () => { // Stack @@ -81,6 +82,27 @@ test('Test deployment w/ existing VPC', () => { }); }); +test('Test default values encrypt notebook', () => { + // Stack + const stack = new Stack(); + const sagemakerRole = new iam.Role(stack, 'SagemakerRole', { + assumedBy: new iam.ServicePrincipal('sagemaker.amazonaws.com'), + }); + + // Build Sagemaker Notebook Instance + defaults.buildSagemakerNotebook(stack, { + role: sagemakerRole, + deployInsideVpc: false, + }); + // Assertion + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::SageMaker::NotebookInstance', { + KmsKeyId: { + Ref: "EncryptionKey1B843E66" + }, + }); +}); + test('Test deployment w/ override', () => { // Stack const stack = new Stack(); @@ -216,3 +238,34 @@ test('Test exception for not providing private or isolated subnets in an existin // Assertion 1 expect(app).toThrowError(); }); + +// --------------------------- +// Prop Tests +// --------------------------- +test('Test fail SageMaker endpoint check', () => { + const stack = new Stack(); + + // Build Sagemaker Inference Endpoint + const modelProps = { + primaryContainer: { + image: ".dkr.ecr..amazonaws.com/linear-learner:latest", + modelDataUrl: "s3:////model.tar.gz", + }, + }; + + const buildSagemakerEndpointResponse = BuildSagemakerEndpoint(stack, { modelProps }); + + const props: defaults.SagemakerProps = { + existingSagemakerEndpointObj: buildSagemakerEndpointResponse.endpoint, + endpointProps: { + endpointConfigName: 'placeholder' + } + }; + + const app = () => { + defaults.CheckSagemakerProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide endpointProps or existingSagemakerEndpointObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/secretsmanager-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/secretsmanager-helper.test.ts index b6b1717c1..4e6337cd7 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/secretsmanager-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/secretsmanager-helper.test.ts @@ -18,9 +18,6 @@ import { Template } from 'aws-cdk-lib/assertions'; const DESCRIPTION = 'test secret description'; const SECRET_NAME = 'test secret name'; -// -------------------------------------------------------------- -// Test minimal deployment with no properties -// -------------------------------------------------------------- test('Test minimal deployment with no properties', () => { // Stack const stack = new Stack(); @@ -34,9 +31,6 @@ test('Test minimal deployment with no properties', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ custom properties -// -------------------------------------------------------------- test('Test deployment with custom properties', () => { // Stack const stack = new Stack(); @@ -57,3 +51,23 @@ test('Test deployment with custom properties', () => { } }); }); + +// --------------------------- +// Prop Tests +// --------------------------- + +test('Test fail Secret check', () => { + const stack = new Stack(); + + const props: defaults.SecretsManagerProps = { + secretProps: {}, + existingSecretObj: defaults.buildSecretsManagerSecret(stack, 'secret', {}), + }; + + const app = () => { + defaults.CheckSecretsManagerProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide secretProps or existingSecretObj, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/sns-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/sns-helper.test.ts index 225b15abe..a0ecf4812 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/sns-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/sns-helper.test.ts @@ -307,3 +307,112 @@ test('existing unencrypted topic is not overridden with defaults', () => { template.resourceCountIs('AWS::KMS::Key', 0); template.resourceCountIs('AWS::SNS::Topic', 1); }); + +// --------------------------- +// Prop Tests +// --------------------------- +test('Test fail SNS topic check', () => { + const stack = new Stack(); + + const props: defaults.SnsProps = { + topicProps: {}, + existingTopicObj: new sns.Topic(stack, 'placeholder', {}) + }; + + const app = () => { + defaults.CheckSnsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide topicProps or existingTopicObj, but not both.\n'); +}); + +test('Test fail SNS topic check with bad topic attribute name', () => { + const stack = new Stack(); + + const props: defaults.SnsProps = { + topicProps: {}, + existingTopicObj: new sns.Topic(stack, 'placeholder', {}) + }; + + const app = () => { + defaults.CheckSnsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide topicProps or existingTopicObj, but not both.\n'); +}); + +test('Test fail SNS topic check when both encryptionKey and encryptionKeyProps are specified', () => { + const stack = new Stack(); + + const props: defaults.SnsProps = { + encryptionKey: new kms.Key(stack, 'key'), + encryptionKeyProps: { + description: 'a description' + } + }; + + const app = () => { + defaults.CheckSnsProps(props); + }; + + expect(app).toThrowError('Error - Either provide encryptionKey or encryptionKeyProps, but not both.\n'); +}); + +test('Test fail SNS topic check when both topicProps.masterKey and encryptionKeyProps are specified', () => { + const stack = new Stack(); + + const props: defaults.SnsProps = { + topicProps: { + masterKey: new kms.Key(stack, 'key') + }, + encryptionKeyProps: { + description: 'a description' + } + }; + + const app = () => { + defaults.CheckSnsProps(props); + }; + + expect(app).toThrowError('Error - Either provide topicProps.masterKey or encryptionKeyProps, but not both.\n'); +}); + +test('Test fail SNS topic check when both encryptionKey and topicProps.masterKey are specified', () => { + const stack = new Stack(); + + const props: defaults.SnsProps = { + encryptionKey: new kms.Key(stack, 'key'), + topicProps: { + masterKey: new kms.Key(stack, 'otherkey') + } + }; + + const app = () => { + defaults.CheckSnsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide topicProps.masterKey or encryptionKey, but not both.\n'); +}); + +test('Test fail encryption key check', () => { + const stack = new Stack(); + + const key = defaults.buildEncryptionKey(stack, { + enableKeyRotation: false + }); + + const props: defaults.SnsProps = { + encryptionKey: key, + encryptionKeyProps: {}, + }; + + const app = () => { + defaults.CheckSnsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide encryptionKey or encryptionKeyProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/sqs-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/sqs-helper.test.ts index 44ce77d05..2d48bda4b 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/sqs-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/sqs-helper.test.ts @@ -190,3 +190,168 @@ test('Test creating a FIFO queue', () => { }); expect(buildQueueResponse.queue.fifo).toBe(true); }); + +// --------------------------- +// Prop Tests +// --------------------------- + +test("Test fail SQS Queue check", () => { + const stack = new Stack(); + + const props: defaults.SqsProps = { + queueProps: {}, + existingQueueObj: new sqs.Queue(stack, 'placeholder', {}), + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide queueProps or existingQueueObj, but not both.\n'); +}); + +test('Test fail SQS queue check when queueProps.encryptionMasterKey and encryptionKey are both specified', () => { + const stack = new Stack(); + + const props: defaults.SqsProps = { + queueProps: { + encryptionMasterKey: new kms.Key(stack, 'key') + }, + encryptionKey: new kms.Key(stack, 'otherkey') + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + expect(app).toThrowError('Error - Either provide queueProps.encryptionMasterKey or encryptionKey, but not both.\n'); +}); + +test('Test fail SQS queue check when queueProps.encryptionMasterKey and encryptionKeyProps are both specified', () => { + const stack = new Stack(); + + const props: defaults.SqsProps = { + encryptionKeyProps: { + description: 'key description' + }, + queueProps: { + encryptionMasterKey: new kms.Key(stack, 'key') + } + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide queueProps.encryptionMasterKey or encryptionKeyProps, but not both.\n'); +}); + +test('Test fail SQS check when both encryptionKey and encryptionKeyProps are specified', () => { + const stack = new Stack(); + + const props: defaults.SqsProps = { + encryptionKey: new kms.Key(stack, 'key'), + encryptionKeyProps: { + description: 'a description' + } + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + expect(app).toThrowError('Error - Either provide encryptionKey or encryptionKeyProps, but not both.\n'); +}); + +test('Test fail Dead Letter Queue check', () => { + + const props: defaults.SqsProps = { + deployDeadLetterQueue: false, + deadLetterQueueProps: {}, + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - If deployDeadLetterQueue is false then deadLetterQueueProps cannot be specified.\n'); +}); + +test('Test fail Dead Letter Queue check with queueProps fifo set to true and undefined deadLetterQueueProps', () => { + + const props: defaults.SqsProps = { + queueProps: { fifo: true }, + deadLetterQueueProps: {}, + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + + 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); +}); + +test('Test fail Dead Letter Queue check with queueProps fifo set to true and deadLetterQueueProps fifo set to false', () => { + + const props: defaults.SqsProps = { + queueProps: { fifo: true }, + deadLetterQueueProps: { fifo: false }, + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + + 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); +}); + +test('Test fail Dead Letter Queue check with queueProps fifo set to false and deadLetterQueueProps fifo set to true', () => { + + const props: defaults.SqsProps = { + deadLetterQueueProps: { fifo: true }, + queueProps: { fifo: false }, + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + + 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); +}); + +test('Test fail Dead Letter Queue check with deadLetterQueueProps fifo set to true', () => { + + const props: defaults.SqsProps = { + deadLetterQueueProps: { fifo: true }, + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + + 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); +}); + +test('Test fail Dead Letter Queue check with queueProps fifo set to false', () => { + + const props: defaults.SqsProps = { + queueProps: { fifo: false }, + }; + + const app = () => { + defaults.CheckSqsProps(props); + }; + + expect(app).toThrowError('Error - If you specify a fifo: true in either queueProps or deadLetterQueueProps, you must also set fifo: ' + + 'true in the other props object. Fifo must match for the Queue and the Dead Letter Queue.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/utils.test.ts b/source/patterns/@aws-solutions-constructs/core/test/utils.test.ts index 6597b2154..88a1a9c9e 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/utils.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/utils.test.ts @@ -212,3 +212,39 @@ test('Test generateName uniqueness', () => { const nameTwo = defaults.generateName(stackTwo, ""); expect(nameOne === nameTwo).toBe(false); }); + +test('Test successful CheckListValues', () => { + + const app = () => { + defaults.CheckListValues(['one', 'two', 'four'], ['four', 'one'], 'test value'); + }; + + // Assertion + expect(app).not.toThrowError(); +}); + +test('Test fail OpenSearch improper vpc specification', () => { + + const props: defaults.OpenSearchProps = { + openSearchDomainProps: { + vpcOptions: {} + }, + }; + + const app = () => { + defaults.CheckOpenSearchProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Define VPC using construct parameters not the OpenSearch Service props\n'); +}); + +test('Test unsuccessful CheckListValues', () => { + + const app = () => { + defaults.CheckListValues(['one', 'two', 'four'], ['four', 'three'], 'test value'); + }; + + // Assertion + expect(app).toThrowError('Invalid test value submitted - three'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/vpc-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/vpc-helper.test.ts index 73c0b3322..3b52ad4ec 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/vpc-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/vpc-helper.test.ts @@ -18,9 +18,6 @@ import { Template } from 'aws-cdk-lib/assertions'; import { AddAwsServiceEndpoint, ServiceEndpointTypes } from '../lib/vpc-helper'; import { DefaultPublicPrivateVpcProps, DefaultIsolatedVpcProps } from '../lib/vpc-defaults'; -// -------------------------------------------------------------- -// Test minimal Isolated deployment with no properties -// -------------------------------------------------------------- test("Test minimal deployment with no properties", () => { // Stack const stack = new Stack(); @@ -39,9 +36,6 @@ test("Test minimal deployment with no properties", () => { template.resourceCountIs('AWS::EC2::InternetGateway', 0); }); -// -------------------------------------------------------------- -// Test deployment w/ user provided custom properties -// -------------------------------------------------------------- test('Test deployment w/ user provided custom properties', () => { // Stack const stack = new Stack(); @@ -61,9 +55,6 @@ test('Test deployment w/ user provided custom properties', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ construct provided custom properties -// -------------------------------------------------------------- test('Test deployment w/ construct provided custom properties', () => { // Stack const stack = new Stack(); @@ -83,9 +74,6 @@ test('Test deployment w/ construct provided custom properties', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ construct and user provided custom properties -// -------------------------------------------------------------- test('Test deployment w/ construct and user provided custom properties', () => { // Stack const stack = new Stack(); @@ -110,9 +98,6 @@ test('Test deployment w/ construct and user provided custom properties', () => { }); }); -// -------------------------------------------------------------- -// Test priority of default, user and construct properties -// -------------------------------------------------------------- test('Test deployment w/ construct and user provided custom properties', () => { // Stack const stack = new Stack(); @@ -145,9 +130,6 @@ test('Test deployment w/ construct and user provided custom properties', () => { template.resourceCountIs('AWS::EC2::InternetGateway', 0); }); -// -------------------------------------------------------------- -// Test deployment w/ existing VPC provided -// -------------------------------------------------------------- test('Test deployment w/ existing VPC provided', () => { // Stack const stack = new Stack(); @@ -162,9 +144,6 @@ test('Test deployment w/ existing VPC provided', () => { expect(newVpc).toBe(testExistingVpc); }); -// -------------------------------------------------------------- -// Test adding Gateway Endpoint -// -------------------------------------------------------------- test('Test adding Gateway Endpoint', () => { // Stack const stack = new Stack(); @@ -188,9 +167,6 @@ test('Test adding Gateway Endpoint', () => { template.resourceCountIs('AWS::EC2::VPCEndpoint', 3); }); -// -------------------------------------------------------------- -// Test adding Interface Endpoint -// -------------------------------------------------------------- test('Test adding Interface Endpoint', () => { // Stack const stack = new Stack(); @@ -207,9 +183,6 @@ test('Test adding Interface Endpoint', () => { }); }); -// -------------------------------------------------------------- -// Test adding SAGEMAKER_RUNTIME Interface Endpoint -// -------------------------------------------------------------- test('Test adding SAGEMAKER_RUNTIME Interface Endpoint', () => { // Stack const stack = new Stack(); @@ -226,9 +199,6 @@ test('Test adding SAGEMAKER_RUNTIME Interface Endpoint', () => { }); }); -// -------------------------------------------------------------- -// Test adding a second Endpoint of same service -// -------------------------------------------------------------- test('Test adding a second Endpoint of same service', () => { // Stack const stack = new Stack(); @@ -244,9 +214,6 @@ test('Test adding a second Endpoint of same service', () => { Template.fromStack(stack).resourceCountIs('AWS::EC2::VPCEndpoint', 1); }); -// -------------------------------------------------------------- -// Test adding bad Endpoint -// -------------------------------------------------------------- test('Test adding bad Endpoint', () => { // Stack const stack = new Stack(); @@ -262,9 +229,6 @@ test('Test adding bad Endpoint', () => { expect(app).toThrowError(); }); -// -------------------------------------------------------------- -// Test adding Events Interface Endpoint -// -------------------------------------------------------------- test('Test adding Events Interface Endpoint', () => { // Stack const stack = new Stack(); @@ -279,4 +243,43 @@ test('Test adding Events Interface Endpoint', () => { Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPCEndpoint', { VpcEndpointType: 'Interface', }); -}); \ No newline at end of file +}); + +// --------------------------- +// Prop Tests +// --------------------------- +test('Test fail Vpc check with deployVpc', () => { + const stack = new Stack(); + + const props: defaults.VpcPropsSet = { + deployVpc: true, + existingVpc: defaults.buildVpc(stack, { + defaultVpcProps: defaults.DefaultPublicPrivateVpcProps(), + }), + }; + + const app = () => { + defaults.CheckVpcProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); + +test('Test fail Vpc check with vpcProps', () => { + const stack = new Stack(); + + const props: defaults.VpcPropsSet = { + vpcProps: defaults.DefaultPublicPrivateVpcProps(), + existingVpc: defaults.buildVpc(stack, { + defaultVpcProps: defaults.DefaultPublicPrivateVpcProps(), + }), + }; + + const app = () => { + defaults.CheckVpcProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/core/test/waf-helper.test.ts b/source/patterns/@aws-solutions-constructs/core/test/waf-helper.test.ts index d93ba3d19..66fc14798 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/waf-helper.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/waf-helper.test.ts @@ -256,9 +256,6 @@ test('Test deployment w/ user provided partial custom properties', () => { }); }); -// -------------------------------------------------------------- -// Test deployment w/ existing WAF web ACL provided -// -------------------------------------------------------------- test('Test deployment w/ existing WAF web ACL provided', () => { // Stack const stack = new Stack(); @@ -269,4 +266,56 @@ test('Test deployment w/ existing WAF web ACL provided', () => { }); expect(newWaf).toBe(testWaf); -}); \ No newline at end of file +}); + +// --------------------------- +// Prop Tests +// --------------------------- +test('Test WebACL bad props', () => { + const stack = new Stack(); + const wafProps: waf.CfnWebACLProps = { + scope: 'CLOUDFRONT', + defaultAction: { + allow: {} + }, + visibilityConfig: { + cloudWatchMetricsEnabled: false, + metricName: 'webACL', + sampledRequestsEnabled: true + }, + rules: [ + defaults.wrapManagedRuleSet("AWSManagedRulesCommonRuleSet", "AWS", 0), + defaults.wrapManagedRuleSet("AWSManagedRulesWordPressRuleSet", "AWS", 1), + ] + }; + + const wafPropsTwo: waf.CfnWebACLProps = { + scope: 'CLOUDFRONT', + defaultAction: { + allow: {} + }, + visibilityConfig: { + cloudWatchMetricsEnabled: false, + metricName: 'webACL', + sampledRequestsEnabled: true + }, + rules: [ + defaults.wrapManagedRuleSet("AWSManagedRulesCommonRuleSet", "AWS", 0), + defaults.wrapManagedRuleSet("AWSManagedRulesWordPressRuleSet", "AWS", 1), + ] + }; + + const acl: waf.CfnWebACL = new waf.CfnWebACL(stack, 'test', wafProps); + + const props: defaults.WafWebAclProps = { + existingWebaclObj: acl, + webaclProps: wafPropsTwo, + }; + + const app = () => { + defaults.CheckWafWebAclProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide existingWebaclObj or webaclProps, but not both.\n'); +}); diff --git a/source/patterns/@aws-solutions-constructs/resources/README.md b/source/patterns/@aws-solutions-constructs/resources/README.md index 04bc21a96..08e056c31 100644 --- a/source/patterns/@aws-solutions-constructs/resources/README.md +++ b/source/patterns/@aws-solutions-constructs/resources/README.md @@ -16,6 +16,6 @@ |:-------------|:-------------|
-The resources library contains resuable resources that can be leveraged from solutions constructs. These resources are deployable units with their own sets of integration tests (to contrast them with the solutions constructs `core` library). +The resources library contains reusable resources that can be leveraged from solutions constructs. These resources are deployable units with their own sets of integration tests (to contrast them with the solutions constructs `core` library). -The first resource being published is the `template-writer`, which does automatic text transformation/substiution, implemented as a custom resource, and run as part of a CloudFormation stack Create/Update/Delete lifecycle. Some use-cases for using the `template-writer` resource can be seen in the `aws-openapigateway-lambda` Solutions Construct, where it transforms an incoming OpenAPI Definition (residing locally or in S3) by auto-populating the `uri` fields of the `x-amazon-apigateway-integration` integrations with the resolved value of the backing lambda functions. \ No newline at end of file +The first resource being published is the `template-writer`, which does automatic text transformation/substiution, implemented as a custom resource, and run as part of a CloudFormation stack Create/Update/Delete lifecycle. Some use-cases for using the `template-writer` resource can be seen in the `aws-openapigateway-lambda` Solutions Construct, where it transforms an incoming OpenAPI Definition (residing locally or in S3) by auto-populating the `uri` fields of the `x-amazon-apigateway-integration` integrations with the resolved value of the backing lambda functions. diff --git a/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer-from-asset.expected.json b/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer-from-asset.expected.json index 2d452a073..7e40d2de2 100644 --- a/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer-from-asset.expected.json +++ b/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer-from-asset.expected.json @@ -211,13 +211,13 @@ }, "S3Key": "96f7d2d4f45b57a586d030966d31e06bc622b5f20258ca38d605fef38e6b9a17.zip" }, + "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "TestTemplateWriterLambdaRole192FE23A", "Arn" ] }, - "Handler": "index.handler", "Runtime": "nodejs18.x", "TracingConfig": { "Mode": "Active" @@ -326,13 +326,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "8e3d635893ea17fa3158623489cd42c680fad925b38de1ef51cb10d84f6e245e.zip" - }, - "Role": { - "Fn::GetAtt": [ - "TestTemplateWriterProviderframeworkonEventServiceRoleED11CF9A", - "Arn" - ] + "S3Key": "7382a0addb9f34974a1ea6c6c9b063882af874828f366f5c93b2b7b64db15c94.zip" }, "Description": "AWS CDK resource provider framework - onEvent (template-writer-from-asset/TestTemplateWriterProvider)", "Environment": { @@ -346,7 +340,13 @@ } }, "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", + "Role": { + "Fn::GetAtt": [ + "TestTemplateWriterProviderframeworkonEventServiceRoleED11CF9A", + "Arn" + ] + }, + "Runtime": "nodejs18.x", "Timeout": 900 }, "DependsOn": [ diff --git a/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer-from-large-asset.expected.json b/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer-from-large-asset.expected.json index 706be9649..e7903d42f 100644 --- a/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer-from-large-asset.expected.json +++ b/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer-from-large-asset.expected.json @@ -211,14 +211,14 @@ }, "S3Key": "96f7d2d4f45b57a586d030966d31e06bc622b5f20258ca38d605fef38e6b9a17.zip" }, + "Handler": "index.handler", + "MemorySize": 1024, "Role": { "Fn::GetAtt": [ "TestTemplateWriterLambdaRole192FE23A", "Arn" ] }, - "Handler": "index.handler", - "MemorySize": 1024, "Runtime": "nodejs18.x", "Timeout": 60, "TracingConfig": { @@ -328,13 +328,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "8e3d635893ea17fa3158623489cd42c680fad925b38de1ef51cb10d84f6e245e.zip" - }, - "Role": { - "Fn::GetAtt": [ - "TestTemplateWriterProviderframeworkonEventServiceRoleED11CF9A", - "Arn" - ] + "S3Key": "7382a0addb9f34974a1ea6c6c9b063882af874828f366f5c93b2b7b64db15c94.zip" }, "Description": "AWS CDK resource provider framework - onEvent (template-writer-from-large-asset/TestTemplateWriterProvider)", "Environment": { @@ -348,7 +342,13 @@ } }, "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", + "Role": { + "Fn::GetAtt": [ + "TestTemplateWriterProviderframeworkonEventServiceRoleED11CF9A", + "Arn" + ] + }, + "Runtime": "nodejs18.x", "Timeout": 900 }, "DependsOn": [ diff --git a/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer.expected.json b/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer.expected.json index 0a968389b..c6eaa8d8c 100644 --- a/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer.expected.json +++ b/source/patterns/@aws-solutions-constructs/resources/test/integ.template-writer.expected.json @@ -1,5 +1,5 @@ { - "Description": "Integration Test for Tempalte Writer Resource", + "Description": "Integration Test for Template Writer Resource", "Resources": { "TemplateWriterTemplateWriterLambdaRole8C61D206": { "Type": "AWS::IAM::Role", @@ -429,4 +429,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/tools/cdk-integ-tools/package.json b/source/tools/cdk-integ-tools/package.json index 25e932120..bbaf5dc05 100644 --- a/source/tools/cdk-integ-tools/package.json +++ b/source/tools/cdk-integ-tools/package.json @@ -32,12 +32,12 @@ "@types/node": "18.11.9", "tslint": "^5.20.1", "typescript": "~3.9.10", - "aws-cdk-lib": "2.81.0", + "aws-cdk-lib": "2.99.1", "constructs": "^10.0.0" }, "dependencies": { - "@aws-cdk/cloudformation-diff": "2.81.0", - "aws-cdk": "2.81.0", + "@aws-cdk/cloudformation-diff": "2.99.1", + "aws-cdk": "2.99.1", "fs-extra": "^9.0.1", "yargs": "^16.1.1", "deepmerge": "^4.0.0" diff --git a/source/use_cases/aws-custom-glue-etl/test/integ.gluejob.expected.json b/source/use_cases/aws-custom-glue-etl/test/integ.gluejob.expected.json index 189a79f23..a4f429a37 100644 --- a/source/use_cases/aws-custom-glue-etl/test/integ.gluejob.expected.json +++ b/source/use_cases/aws-custom-glue-etl/test/integ.gluejob.expected.json @@ -110,7 +110,7 @@ ], "Version": "2012-10-17" }, - "Description": "Service role that Glue custom ETL jobs will assume for exeuction" + "Description": "Service role that Glue custom ETL jobs will assume for execution" } }, "CustomETLJobRoleDefaultPolicy564ADEA9": { @@ -766,4 +766,4 @@ ] } } -} \ No newline at end of file +} diff --git a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.js.snap b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.js.snap index 7d030bcb2..67b478ac1 100644 --- a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.js.snap +++ b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.js.snap @@ -571,7 +571,7 @@ Object { "rules_to_suppress": Array [ Object { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource", + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource", }, ], }, diff --git a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.ts.snap b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.ts.snap index 0b0094eb5..4163dd067 100644 --- a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.ts.snap +++ b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.ts.snap @@ -443,7 +443,7 @@ Object { "rules_to_suppress": Array [ Object { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource", + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource", }, ], }, diff --git a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.js.snap b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.js.snap index c37d27adf..5b598d732 100644 --- a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.js.snap +++ b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.js.snap @@ -583,7 +583,7 @@ Object { "rules_to_suppress": Array [ Object { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource", + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource", }, ], }, diff --git a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.ts.snap b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.ts.snap index f91c4e580..5decef574 100644 --- a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.ts.snap +++ b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.ts.snap @@ -659,7 +659,7 @@ Object { "rules_to_suppress": Array [ Object { "id": "W45", - "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource", + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource", }, ], },