From f4829ba1af3643a8b42bb74af9dfa8207d383da3 Mon Sep 17 00:00:00 2001 From: mickychetta <45010053+mickychetta@users.noreply.github.com> Date: Tue, 10 May 2022 05:36:36 -0700 Subject: [PATCH] feat(aws-fargate-stepfunctions): new construct (#677) * created README.md * removed arn env var prop and fixed state machine doc comments * made createCloudWatchAlarms prop optional * created new construct * fixed README typo * refactored test to single concept design * updated default for vpcProps --- DESIGN_GUIDELINES.md | 4 +- .../aws-fargate-stepfunctions/.eslintignore | 4 + .../aws-fargate-stepfunctions/.gitignore | 15 + .../aws-fargate-stepfunctions/.npmignore | 21 + .../aws-fargate-stepfunctions/README.md | 141 ++ .../architecture.png | Bin 0 -> 187339 bytes .../aws-fargate-stepfunctions/lib/index.ts | 187 +++ .../aws-fargate-stepfunctions/package.json | 110 ++ .../test/fargate-stepfunctions.test.ts | 313 ++++ .../test/integ.new-resources.expected.json | 1355 +++++++++++++++++ .../test/integ.new-resources.ts | 59 + .../integ.no-cloudwatch-alarms.expected.json | 1292 ++++++++++++++++ .../test/integ.no-cloudwatch-alarms.ts | 59 + 13 files changed, 3558 insertions(+), 2 deletions(-) create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.eslintignore create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.gitignore create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.npmignore create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/README.md create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/architecture.png create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/lib/index.ts create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/package.json create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/fargate-stepfunctions.test.ts create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.expected.json create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.ts create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.expected.json create mode 100644 source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.ts diff --git a/DESIGN_GUIDELINES.md b/DESIGN_GUIDELINES.md index 8985fd9b7..fcb96c45b 100644 --- a/DESIGN_GUIDELINES.md +++ b/DESIGN_GUIDELINES.md @@ -347,14 +347,14 @@ Existing Inconsistencies would not be published, that’s for our internal use | Name | Type | Description | Notes | | --- | --- | --- |--- | | stateMachineProps |[`sfn.StateMachineProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-stepfunctions.StateMachineProps.html)|Optional user provided props to override the default props for `sfn.StateMachine`| -| createCloudWatchAlarms | `boolean`|Whether to create recommended CloudWatch alarms.| +| createCloudWatchAlarms? | `boolean`|Whether to create recommended CloudWatch alarms.| **Required Construct Properties** | Name | Type | Description | Notes | | --- | --- | --- |--- | | stateMachine| [`sfn.StateMachine`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-stepfunctions.StateMachine.html)|Returns an instance of `sfn.StateMachine` created by the construct.| -| stateMachineLoggingGroup|[`logs.ILogGroup`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-logs.ILogGroup.html)|Returns an instance of the `logs.ILogGroup` created by the construct for StateMachine.| +| stateMachineLogGroup|[`logs.ILogGroup`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-logs.ILogGroup.html)|Returns an instance of the `logs.ILogGroup` created by the construct for StateMachine.| | cloudwatchAlarms? | [`cloudwatch.Alarm[]`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cloudwatch.Alarm.html)|Returns a list of `cloudwatch.Alarm` created by the construct.| ## VPC diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.eslintignore b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.eslintignore new file mode 100644 index 000000000..e6f7801ea --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.eslintignore @@ -0,0 +1,4 @@ +lib/*.js +test/*.js +*.d.ts +coverage diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.gitignore b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.gitignore new file mode 100644 index 000000000..6773cabd2 --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.gitignore @@ -0,0 +1,15 @@ +lib/*.js +test/*.js +*.js.map +*.d.ts +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.npmignore b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.npmignore new file mode 100644 index 000000000..f66791629 --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/.npmignore @@ -0,0 +1,21 @@ +# Exclude typescript source and config +*.ts +tsconfig.json +coverage +.nyc_output +*.tgz +*.snk +*.tsbuildinfo + +# Include javascript files and typescript declarations +!*.js +!*.d.ts + +# Exclude jsii outdir +dist + +# Include .jsii +!.jsii + +# Include .jsii +!.jsii \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/README.md b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/README.md new file mode 100644 index 000000000..e0583aff3 --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/README.md @@ -0,0 +1,141 @@ +# aws-fargate-stepfunctions module + + +--- + +![Stability: Experimental](https://img.shields.io/badge/stability-Experimental-important.svg?style=for-the-badge) + +> All classes are under active development and subject to non-backward compatible changes or removal in any +> future version. These are not subject to the [Semantic Versioning](https://semver.org/) model. +> This means that while you may use them, you may need to update your source code when upgrading to a newer version of this package. + +--- + + +| **Reference Documentation**:| https://docs.aws.amazon.com/solutions/latest/constructs/| +|:-------------|:-------------| +
+ +| **Language** | **Package** | +|:-------------|-----------------| +|![Python Logo](https://docs.aws.amazon.com/cdk/api/latest/img/python32.png) Python|`aws_solutions_constructs.aws_fargate_stepfunctions`| +|![Typescript Logo](https://docs.aws.amazon.com/cdk/api/latest/img/typescript32.png) Typescript|`@aws-solutions-constructs/aws-fargate-stepfunctions`| +|![Java Logo](https://docs.aws.amazon.com/cdk/api/latest/img/java32.png) Java|`software.amazon.awsconstructs.services.fargatestepfunctions`| + +This AWS Solutions Construct implements an AWS Fargate service that can execute an AWS Step Functions state machine + +Here is a minimal deployable pattern definition: + +Typescript +``` typescript +import { Construct } from 'constructs'; +import { Stack, StackProps } from 'aws-cdk-lib'; +import { FargateToStepfunctions, FargateToStepfunctionsProps } from '@aws-solutions-constructs/aws-fargate-stepfunctions'; +import * as stepfunctions from 'aws-cdk-lib/aws-stepfunctions'; + +const startState = new stepfunctions.Pass(this, 'StartState'); + +const constructProps: FargateToStepfunctionsProps = { + publicApi: true, + ecrRepositoryArn: "arn:aws:ecr:us-east-1:123456789012:repository/your-ecr-repo", + stateMachineProps: { + definition: startState + } +}; + +new FargateToStepfunctions(this, 'test-construct', constructProps); +``` + +Python +``` python +from aws_solutions_constructs.aws_fargate_stepfunctions import FargateToStepfunctions, FargateToStepfunctionsProps +from aws_cdk import ( + aws_stepfunctions as stepfunctions, + Stack +) +from constructs import Construct + +start_state = stepfunctions.Pass(self, 'start_state') + +FargateToStepfunctions(self, 'test_construct', + public_api=True, + ecr_repository_arn="arn:aws:ecr:us-east-1:123456789012:repository/your-ecr-repo", + state_machine_props=stepfunctions.StateMachineProps( + definition=start_state)) +``` + +Java +``` java +import software.constructs.Construct; + +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.StackProps; +import software.amazon.awsconstructs.services.fargatestepfunctions.*; +import software.amazon.awscdk.services.stepfunctions.*; + +start_state = stepfunctions.Pass(self, 'start_state') + +new FargateToStepfunctions(this, "test-construct", new FargateToStepfunctionsProps.Builder() + .publicApi(true) + .ecrRepositoryArn("arn:aws:ecr:us-east-1:123456789012:repository/your-ecr-repo") + .stateMachineProps(new StateMachineProps.Builder() + .definition(startState) + .build() + .build()); +``` + +## Pattern Construct Props + +| **Name** | **Type** | **Description** | +|:-------------|:----------------|-----------------| +| publicApi | `boolean` | Whether the construct is deploying a private or public API. This has implications for the VPC. | +| vpcProps? | [`ec2.VpcProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-ec2.VpcProps.html) | Optional custom properties for a VPC the construct will create. This VPC will be used by any Private Hosted Zone the construct creates (that's why loadBalancerProps and privateHostedZoneProps can't include a VPC). Providing both this and existingVpc is an error. | +| existingVpc? | [`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-ec2.IVpc.html) | An existing VPC in which to deploy the construct. Providing both this and vpcProps is an error. If the client provides an existing load balancer and/or existing Private Hosted Zone, those constructs must exist in this VPC. | +| clusterProps? | [`ecs.ClusterProps`](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs.ClusterProps.html) | Optional properties to create a new ECS cluster. To provide an existing cluster, use the cluster attribute of fargateServiceProps. | +| ecrRepositoryArn? | `string` | The arn of an ECR Repository containing the image to use to generate the containers. Either this or the image property of containerDefinitionProps must be provided. format: arn:aws:ecr:*region*:*account number*:repository/*Repository Name* | +| ecrImageVersion? | `string` | The version of the image to use from the repository. Defaults to 'Latest' | +| containerDefinitionProps? | [`ecs.ContainerDefinitionProps \| any`](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_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/v1/docs/@aws-cdk_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/v1/docs/@aws-cdk_aws-ecs.FargateServiceProps.html) | Optional values to override default Fargate Task definition properties (fargate-defaults.ts). The construct will default to launching the service is the most isolated subnets available (precedence: Isolated, Private and Public). Override those and other defaults here. | +|existingFargateServiceObject? | [`ecs.FargateService`](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_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: ecrImageVersion, containerDefinitionProps, fargateTaskDefinitionProps, ecrRepositoryArn, fargateServiceProps, clusterProps | +|existingContainerDefinitionObject? | [`ecs.ContainerDefinition`](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs.ContainerDefinition.html) | A container definition already instantiated as part of a Fargate service. This must be the container in the existingFargateServiceObject | +|stateMachineProps|[`sfn.StateMachineProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-stepfunctions.StateMachineProps.html)|User provided props to override the default props for sfn.StateMachine.| +| createCloudWatchAlarms? | `boolean`|Whether to create recommended CloudWatch alarms. Default is true.| +|logGroupProps?|[`logs.LogGroupProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-logs.LogGroupProps.html)|Optional user provided props to override the default props for for the CloudWatchLogs LogGroup.| +|stateMachineEnvironmentVariableName?|`string`|Optional name for the container environment variable containing the state machine ARN.| + +## Pattern Properties + +| **Name** | **Type** | **Description** | +|:-------------|:----------------|-----------------| +| vpc | [`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-ec2.IVpc.html) | The VPC used by the construct (whether created by the construct or provided by the client) | +| service | [`ecs.FargateService`](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs.FargateService.html) | The AWS Fargate service used by this construct (whether created by this construct or passed to this construct at initialization) | +| container | [`ecs.ContainerDefinition`](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs.ContainerDefinition.html) | The container associated with the AWS Fargate service in the service property. | +| stateMachine| [`sfn.StateMachine`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-stepfunctions.StateMachine.html)|Returns an instance of `sfn.StateMachine` created by the construct.| +| stateMachineLogGroup|[`logs.ILogGroup`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-logs.ILogGroup.html)|Returns an instance of the `logs.ILogGroup` created by the construct for StateMachine.| +| cloudwatchAlarms? | [`cloudwatch.Alarm[]`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cloudwatch.Alarm.html)|Returns a list of `cloudwatch.Alarm` created by the construct.| + +## Default settings + +Out of the box implementation of the Construct without any override will set the following defaults: + +### AWS Fargate Service +* Sets up an AWS Fargate service + * Uses the existing service if provided + * Creates a new service if none provided. + * Service will run in isolated subnets if available, then private subnets if available and finally public subnets +* Adds an environment variable to the container containing the ARN of the state machine + * Default name is `STATE_MACHINE_ARN` +* Add permissions to the container IAM role allowing it to start the execution of a state machine + +### AWS Step Functions +* Sets up an AWS Step Functions state machine + * Uses an existing state machine if one is provided, otherwise creates a new one +* Adds an Interface Endpoint to the VPC for Step Functions (the service by default runs in Isolated or Private subnets) +* Enables CloudWatch logging + +## Architecture +![Architecture Diagram](architecture.png) + +*** +© Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/architecture.png b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..091cbd81be8f55e527da54048f6bf52ca16892a8 GIT binary patch literal 187339 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
  • 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

    iloZ#ixK6_Z0%N5Z>e3UOvRdal?_^$K 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 z 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 NtFC(sdDH6Y{{e00XAA%U literal 0 HcmV?d00001 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 new file mode 100644 index 000000000..ce2acfd3d --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/lib/index.ts @@ -0,0 +1,187 @@ +/** + * Copyright 2022 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. + */ + +// Note: To ensure CDKv2 compatibility, keep the import statement for Construct separate +import { Construct } from "@aws-cdk/core"; +import * as defaults from "@aws-solutions-constructs/core"; +import * as ecs from "@aws-cdk/aws-ecs"; +import * as ec2 from "@aws-cdk/aws-ec2"; +import * as sfn from '@aws-cdk/aws-stepfunctions'; +import * as logs from '@aws-cdk/aws-logs'; +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; + +export interface FargateToStepfunctionsProps { + /** + * Whether the construct is deploying a private or public API. This has implications for the VPC deployed + * by this construct. + * + * @default - none + */ + readonly publicApi: boolean; + /** + * Optional custom properties for a VPC the construct will create. This VPC will + * be used by the new Fargate service the construct creates (that's + * why targetGroupProps can't include a VPC). Providing + * both this and existingVpc is an error. A Step Functions Interface + * endpoint will be included in this VPC. + * + * @default - A set of defaults from vpc-defaults.ts: DefaultPublicPrivateVpcProps() for public APIs + * and DefaultIsolatedVpcProps() for private APIs. + */ + readonly vpcProps?: ec2.VpcProps; + /** + * An existing VPC in which to deploy the construct. Providing both this and + * vpcProps is an error. If the client provides an existing Fargate service, + * this value must be the VPC where the service is running. A Step Functions Interface + * endpoint will be added to this VPC. + * + * @default - none + */ + readonly existingVpc?: ec2.IVpc; + /** + * Optional properties to create a new ECS cluster + */ + readonly clusterProps?: ecs.ClusterProps; + /** + * The arn of an ECR Repository containing the image to use + * to generate the containers + * + * format: + * arn:aws:ecr:[region]:[account number]:repository/[Repository Name] + */ + readonly ecrRepositoryArn?: string; + /** + * The version of the image to use from the repository + * + * @default - 'latest' + */ + readonly ecrImageVersion?: string; + /* + * Optional props to define the container created for the Fargate Service + * + * defaults - fargate-defaults.ts + */ + readonly containerDefinitionProps?: ecs.ContainerDefinitionProps | any; + /* + * Optional props to define the Fargate Task Definition for this construct + * + * defaults - fargate-defaults.ts + */ + readonly fargateTaskDefinitionProps?: ecs.FargateTaskDefinitionProps | any; + /** + * Optional values to override default Fargate Task definition properties + * (fargate-defaults.ts). The construct will default to launching the service + * is the most isolated subnets available (precedence: Isolated, Private and + * Public). Override those and other defaults here. + * + * defaults - fargate-defaults.ts + */ + readonly fargateServiceProps?: ecs.FargateServiceProps | any; + /** + * 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. If this value + * is provided, then existingContainerDefinitionObject must be provided as well. + * + * @default - none + */ + readonly existingFargateServiceObject?: ecs.FargateService; + /* + * A container definition already instantiated as part of a Fargate service. This must + * be the container in the existingFargateServiceObject. + * + * @default - None + */ + readonly existingContainerDefinitionObject?: ecs.ContainerDefinition; + /** + * User provided StateMachineProps to override the defaults + * + * @default - None + */ + readonly stateMachineProps: sfn.StateMachineProps; + /** + * Whether to create recommended CloudWatch alarms + * + * @default - true + */ + readonly createCloudWatchAlarms?: boolean; + /** + * User provided props to override the default props for the CloudWatchLogs LogGroup. + * + * @default - Default props are used + */ + readonly logGroupProps?: logs.LogGroupProps; + /** + * Optional name for the container environment variable containing the state machine ARN. + * + * @default - None + */ + readonly stateMachineEnvironmentVariableName?: string; +} + +export class FargateToStepfunctions extends Construct { + public readonly vpc: ec2.IVpc; + public readonly service: ecs.FargateService; + public readonly container: ecs.ContainerDefinition; + public readonly stateMachine: sfn.StateMachine; + public readonly stateMachineLogGroup: logs.ILogGroup; + public readonly cloudwatchAlarms?: cloudwatch.Alarm[]; + + constructor(scope: Construct, id: string, props: FargateToStepfunctionsProps) { + super(scope, id); + defaults.CheckProps(props); + defaults.CheckFargateProps(props); + + this.vpc = defaults.buildVpc(scope, { + existingVpc: props.existingVpc, + defaultVpcProps: props.publicApi ? defaults.DefaultPublicPrivateVpcProps() : defaults.DefaultIsolatedVpcProps(), + userVpcProps: props.vpcProps, + constructVpcProps: { enableDnsHostnames: true, enableDnsSupport: true } + }); + + defaults.AddAwsServiceEndpoint(scope, this.vpc, defaults.ServiceEndpointTypes.STEP_FUNCTIONS); + + if (props.existingFargateServiceObject) { + this.service = props.existingFargateServiceObject; + // CheckFargateProps confirms that the container is provided + this.container = props.existingContainerDefinitionObject!; + } else { + [this.service, this.container] = defaults.CreateFargateService( + scope, + id, + this.vpc, + props.clusterProps, + props.ecrRepositoryArn, + props.ecrImageVersion, + props.fargateTaskDefinitionProps, + props.containerDefinitionProps, + props.fargateServiceProps + ); + } + + [this.stateMachine, this.stateMachineLogGroup] = defaults.buildStateMachine(this, props.stateMachineProps, + props.logGroupProps); + + this.stateMachine.grantStartExecution(this.service.taskDefinition.taskRole); + + if (props.createCloudWatchAlarms === undefined || props.createCloudWatchAlarms) { + // Deploy best-practice CloudWatch Alarm for state machine + this.cloudwatchAlarms = defaults.buildStepFunctionCWAlarms(this, this.stateMachine); + } + + // Add environment variable + const stateMachineEnvironmentVariableName = props.stateMachineEnvironmentVariableName || 'STATE_MACHINE_ARN'; + this.container.addEnvironment(stateMachineEnvironmentVariableName, this.stateMachine.stateMachineArn); + } +} diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/package.json b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/package.json new file mode 100644 index 000000000..afa446f43 --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/package.json @@ -0,0 +1,110 @@ +{ + "name": "@aws-solutions-constructs/aws-fargate-stepfunctions", + "version": "0.0.0", + "description": "CDK Constructs for AWS Fargate to Amazon Step Functions integration", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/awslabs/aws-solutions-constructs.git", + "directory": "source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions" + }, + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "scripts": { + "build": "tsc -b .", + "lint": "eslint -c ../eslintrc.yml --ext=.js,.ts . && tslint --project .", + "lint-fix": "eslint -c ../eslintrc.yml --ext=.js,.ts --fix .", + "test": "jest --coverage", + "clean": "tsc -b --clean", + "watch": "tsc -b -w", + "integ": "cdk-integ", + "integ-no-clean": "cdk-integ --no-clean", + "integ-assert": "cdk-integ-assert", + "jsii": "jsii", + "jsii-pacmak": "jsii-pacmak", + "build+lint+test": "npm run jsii && npm run lint && npm test && npm run integ-assert", + "snapshot-update": "npm run jsii && npm test -- -u && npm run integ-assert" + }, + "jsii": { + "outdir": "dist", + "targets": { + "java": { + "package": "software.amazon.awsconstructs.services.fargatestepfunctions", + "maven": { + "groupId": "software.amazon.awsconstructs", + "artifactId": "fargatestepfunctions" + } + }, + "dotnet": { + "namespace": "Amazon.SolutionsConstructs.AWS.FargateStepfunctions", + "packageId": "Amazon.SolutionsConstructs.AWS.FargateStepfunctions", + "signAssembly": true, + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "python": { + "distName": "aws-solutions-constructs.aws-fargate-stepfunctions", + "module": "aws_solutions_constructs.aws_fargate_stepfunctions" + } + } + }, + "dependencies": { + "@aws-cdk/aws-cloudwatch": "0.0.0", + "@aws-cdk/core": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", + "@aws-cdk/aws-ecs": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", + "@aws-cdk/aws-stepfunctions": "0.0.0", + "@aws-solutions-constructs/core": "0.0.0", + "constructs": "^3.2.0" + }, + "devDependencies": { + "@aws-cdk/assert": "0.0.0", + "@aws-cdk/aws-cloudwatch": "0.0.0", + "@aws-cdk/core": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", + "@aws-cdk/aws-ecs": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", + "@aws-cdk/aws-stepfunctions": "0.0.0", + "@aws-solutions-constructs/core": "0.0.0", + "@types/jest": "^26.0.22", + "@types/node": "^10.3.0", + "constructs": "3.2.0" + }, + "jest": { + "moduleFileExtensions": [ + "js" + ], + "coverageReporters": [ + "text", + [ + "lcov", + { + "projectRoot": "../../../../" + } + ] + ] + }, + "peerDependencies": { + "@aws-cdk/aws-cloudwatch": "0.0.0", + "@aws-cdk/core": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", + "@aws-cdk/aws-ecs": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", + "@aws-cdk/aws-stepfunctions": "0.0.0", + "@aws-solutions-constructs/core": "0.0.0", + "constructs": "^3.2.0" + }, + "keywords": [ + "aws", + "cdk", + "awscdk", + "AWS Solutions Constructs", + "Amazon Step Functions", + "AWS Fargate" + ] +} \ No newline at end of file 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 new file mode 100644 index 000000000..330a4b131 --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/fargate-stepfunctions.test.ts @@ -0,0 +1,313 @@ +/** + * Copyright 2022 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. + */ + +import '@aws-cdk/assert/jest'; +import * as defaults from '@aws-solutions-constructs/core'; +import * as cdk from "@aws-cdk/core"; +import { FargateToStepfunctions } from "../lib"; +import * as stepfunctions from '@aws-cdk/aws-stepfunctions'; +import * as ecs from '@aws-cdk/aws-ecs'; + +const clusterName = "custom-cluster-name"; +const containerName = "custom-container-name"; +const serviceName = "custom-service-name"; +const familyName = "family-name"; +const testCidr = "172.0.0.0/16"; + +test('Check for construct properties', () => { + const stack = new cdk.Stack(); + const publicApi = true; + + const construct = createFargateConstructWithNewResources(stack, publicApi); + + expect(construct.vpc).toBeDefined(); + expect(construct.service).toBeDefined(); + expect(construct.container).toBeDefined(); + expect(construct.stateMachine).toBeDefined(); + expect(construct.stateMachineLogGroup).toBeDefined(); + expect(construct.cloudwatchAlarms).toBeDefined(); +}); + +test('Check for new service', () => { + const stack = new cdk.Stack(); + const publicApi = false; + + createFargateConstructWithNewResources(stack, publicApi); + + expect(stack).toHaveResourceLike("AWS::ECS::Service", { + ServiceName: serviceName, + LaunchType: 'FARGATE', + DesiredCount: 2, + DeploymentConfiguration: { + MaximumPercent: 150, + MinimumHealthyPercent: 75 + }, + PlatformVersion: ecs.FargatePlatformVersion.LATEST, + }); +}); + +test('Check for an existing service', () => { + const stack = new cdk.Stack(); + const publicApi = true; + + const existingVpc = defaults.getTestVpc(stack); + + const [testService, testContainer] = defaults.CreateFargateService(stack, + 'test', + existingVpc, + { clusterName }, + defaults.fakeEcrRepoArn, + undefined, + { family: familyName }, + { containerName }, + { serviceName }); + + new FargateToStepfunctions(stack, 'test-construct', { + publicApi, + existingFargateServiceObject: testService, + existingContainerDefinitionObject: testContainer, + existingVpc, + stateMachineProps: testStateMachineProps(stack) + }); + + expect(stack).toHaveResourceLike("AWS::ECS::Service", { + ServiceName: serviceName, + LaunchType: 'FARGATE', + DesiredCount: 2, + DeploymentConfiguration: { + MaximumPercent: 150, + MinimumHealthyPercent: 75 + }, + PlatformVersion: ecs.FargatePlatformVersion.LATEST, + }); +}); + +test('Check for IAM startExecution policy', () => { + const stack = new cdk.Stack(); + const publicApi = false; + + createFargateConstructWithNewResources(stack, publicApi); + + expect(stack).toHaveResourceLike("AWS::IAM::Policy", { + PolicyDocument: { + Statement: [ + { + Action: "states:StartExecution", + Effect: "Allow", + Resource: { + Ref: "testconstructStateMachine3333AAA9" + } + } + ], + Version: "2012-10-17" + }, + PolicyName: "testconstructtaskdefTaskRoleDefaultPolicyF34A1535", + Roles: [ + { + Ref: "testconstructtaskdefTaskRoleC60414C4" + } + ] + }); +}); + +test('Check for public/private VPC', () => { + const stack = new cdk.Stack(); + const publicApi = true; + + createFargateConstructWithNewResources(stack, publicApi); + + expect(stack).toHaveResourceLike("AWS::EC2::VPC", { + CidrBlock: testCidr + }); + + expect(stack).toHaveResourceLike('AWS::EC2::InternetGateway', {}); + expect(stack).toCountResources('AWS::EC2::VPC', 1); + expect(stack).toCountResources('AWS::StepFunctions::StateMachine', 1); + expect(stack).toCountResources('AWS::ECS::Service', 1); +}); + +test('Check for isolated VPC', () => { + const stack = new cdk.Stack(); + const publicApi = false; + + createFargateConstructWithNewResources(stack, publicApi); + + expect(stack).toHaveResourceLike("AWS::EC2::VPC", { + CidrBlock: testCidr + }); + + expect(stack).not.toHaveResourceLike('AWS::EC2::InternetGateway', {}); + expect(stack).toCountResources('AWS::EC2::VPC', 1); + expect(stack).toCountResources('AWS::StepFunctions::StateMachine', 1); + expect(stack).toCountResources('AWS::ECS::Service', 1); +}); + +test('Check for an existing VPC', () => { + const stack = new cdk.Stack(); + const publicApi = false; + + const existingVpc = defaults.getTestVpc(stack, publicApi); + + new FargateToStepfunctions(stack, 'test-construct', { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + existingVpc, + stateMachineProps: testStateMachineProps(stack) + }); + + expect(stack).toHaveResourceLike("AWS::EC2::VPC", { + CidrBlock: "172.168.0.0/16" + }); + + expect(stack).toCountResources("AWS::EC2::VPC", 1); +}); + +test('Check for custom ARN resource', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const customEnvName = "TEST_CUSTOM_ARN"; + + new FargateToStepfunctions(stack, 'test-construct', { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + vpcProps: { cidr: testCidr }, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + stateMachineProps: testStateMachineProps(stack), + stateMachineEnvironmentVariableName: customEnvName + }); + + expect(stack).toHaveResourceLike("AWS::ECS::TaskDefinition", { + Family: familyName, + ContainerDefinitions: [ + { + Environment: [ + { + Name: customEnvName, + Value: { + Ref: "testconstructStateMachine3333AAA9" + } + } + ], + Essential: true, + Image: { + "Fn::Join": [ + "", + [ + "123456789012.dkr.ecr.us-east-1.", + { + Ref: "AWS::URLSuffix" + }, + "/fake-repo:latest" + ] + ] + }, + MemoryReservation: 512, + Name: containerName, + PortMappings: [ + { + ContainerPort: 8080, + Protocol: "tcp" + } + ] + } + ] + }); +}); + +test('Check for no cloudwatch creation', () => { + const stack = new cdk.Stack(); + const publicApi = true; + + const construct = new FargateToStepfunctions(stack, 'test-construct', { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + vpcProps: { cidr: testCidr }, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + stateMachineProps: testStateMachineProps(stack), + createCloudWatchAlarms: false + }); + + expect(construct.cloudwatchAlarms).not.toBeDefined(); + expect(stack).not.toHaveResource("AWS::CloudWatch::Alarm", { + ComparisonOperator: "GreaterThanOrEqualToThreshold", + EvaluationPeriods: 1, + AlarmDescription: "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + Dimensions: [ + { + Name: "StateMachineArn", + Value: { + Ref: "testconstructStateMachine3333AAA9" + } + } + ], + MetricName: "ExecutionsAborted", + Namespace: "AWS/States", + Period: 300, + Statistic: "Maximum", + Threshold: 1 + }); +}); + +test('Check for custom log group props', () => { + const stack = new cdk.Stack(); + const publicApi = true; + const logGroupName = "custom-log-group"; + + new FargateToStepfunctions(stack, 'test-construct', { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + vpcProps: { cidr: testCidr }, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + stateMachineProps: testStateMachineProps(stack), + logGroupProps: { + logGroupName + } + }); + + expect(stack).toHaveResourceLike("AWS::Logs::LogGroup", { + LogGroupName: logGroupName + }); +}); + +function createFargateConstructWithNewResources(stack: cdk.Stack, publicApi: boolean) { + return new FargateToStepfunctions(stack, 'test-construct', { + publicApi, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + vpcProps: { cidr: testCidr }, + clusterProps: { clusterName }, + containerDefinitionProps: { containerName }, + fargateTaskDefinitionProps: { family: familyName }, + fargateServiceProps: { serviceName }, + stateMachineProps: testStateMachineProps(stack), + }); +} + +function testStateMachineProps(stack: cdk.Stack, userProps?: stepfunctions.StateMachineProps): + stepfunctions.StateMachineProps { + const defaultTestProp = { definition: new stepfunctions.Pass(stack, 'StartState') }; + + return defaults.consolidateProps(defaultTestProp, userProps); +} \ No newline at end of file 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 new file mode 100644 index 000000000..ba5c88912 --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.expected.json @@ -0,0 +1,1355 @@ +{ + "Description": "Integration Test with new VPC, Service and a state machine", + "Resources": { + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "172.168.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc" + } + ] + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1a", + "CidrBlock": "172.168.0.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet1" + } + ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W33", + "reason": "Allow Public Subnets to have MapPublicIpOnLaunch set to true" + } + ] + } + } + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1RouteTableAssociation97140677": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet1EIPD7E02669": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1NATGateway4D7517AA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet2Subnet691E08A3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1b", + "CidrBlock": "172.168.32.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet2" + } + ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W33", + "reason": "Allow Public Subnets to have MapPublicIpOnLaunch set to true" + } + ] + } + } + }, + "VpcPublicSubnet2RouteTable94F7E489": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "VpcPublicSubnet2DefaultRoute97F91067": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet2EIP3C605A87": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2NATGateway9182C01D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet3SubnetBE12F0B6": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1c", + "CidrBlock": "172.168.64.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet3" + } + ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W33", + "reason": "Allow Public Subnets to have MapPublicIpOnLaunch set to true" + } + ] + } + } + }, + "VpcPublicSubnet3RouteTable93458DBB": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet3" + } + ] + } + }, + "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + } + } + }, + "VpcPublicSubnet3DefaultRoute4697774F": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet3EIP3A666A23": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet3" + } + ] + } + }, + "VpcPublicSubnet3NATGateway7640CD1D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet3EIP3A666A23", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PublicSubnet3" + } + ] + } + }, + "VpcPrivateSubnet1Subnet536B997A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1a", + "CidrBlock": "172.168.96.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "new-resources/Vpc/PrivateSubnet1" + } + ] + } + }, + "VpcPrivateSubnet1RouteTableB2C5B500": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PrivateSubnet1" + } + ] + } + }, + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "VpcPrivateSubnet1DefaultRouteBE02A9ED": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + } + } + }, + "VpcPrivateSubnet2Subnet3788AAA1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1b", + "CidrBlock": "172.168.128.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "new-resources/Vpc/PrivateSubnet2" + } + ] + } + }, + "VpcPrivateSubnet2RouteTableA678073B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PrivateSubnet2" + } + ] + } + }, + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "VpcPrivateSubnet2DefaultRoute060D2087": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + } + } + }, + "VpcPrivateSubnet3SubnetF258B56E": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1c", + "CidrBlock": "172.168.160.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "new-resources/Vpc/PrivateSubnet3" + } + ] + } + }, + "VpcPrivateSubnet3RouteTableD98824C7": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc/PrivateSubnet3" + } + ] + } + }, + "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + } + }, + "VpcPrivateSubnet3DefaultRoute94B74F0D": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + } + } + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + } + } + }, + "VpcFlowLogIAMRole6A475D41": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "vpc-flow-logs.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc" + } + ] + } + }, + "VpcFlowLogIAMRoleDefaultPolicy406FB995": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogStreams" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "VpcFlowLogLogGroup7B5C56B9", + "Arn" + ] + } + }, + { + "Action": "iam:PassRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "VpcFlowLogIAMRole6A475D41", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "VpcFlowLogIAMRoleDefaultPolicy406FB995", + "Roles": [ + { + "Ref": "VpcFlowLogIAMRole6A475D41" + } + ] + } + }, + "VpcFlowLogLogGroup7B5C56B9": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "RetentionInDays": 731, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc" + } + ] + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)" + } + ] + } + } + }, + "VpcFlowLog8FF33A73": { + "Type": "AWS::EC2::FlowLog", + "Properties": { + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", + "TrafficType": "ALL", + "DeliverLogsPermissionArn": { + "Fn::GetAtt": [ + "VpcFlowLogIAMRole6A475D41", + "Arn" + ] + }, + "LogDestinationType": "cloud-watch-logs", + "LogGroupName": { + "Ref": "VpcFlowLogLogGroup7B5C56B9" + }, + "Tags": [ + { + "Key": "Name", + "Value": "new-resources/Vpc" + } + ] + } + }, + "VpcECRAPI9A3B6A2B": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "ServiceName": "com.amazonaws.us-east-1.ecr.api", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "newresourcesECRAPIsecuritygroupE52BAE3F", + "GroupId" + ] + } + ], + "SubnetIds": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ], + "VpcEndpointType": "Interface" + } + }, + "VpcECRDKR604E039F": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "newresourcesECRDKRsecuritygroupBA34F94F", + "GroupId" + ] + } + ], + "SubnetIds": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ], + "VpcEndpointType": "Interface" + } + }, + "VpcS3A5408339": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "RouteTableIds": [ + { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" + }, + { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" + } + ], + "VpcEndpointType": "Gateway" + } + }, + "VpcSTEPFUNCTIONS550F8CB6": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "ServiceName": "com.amazonaws.us-east-1.states", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "newresourcesSTEPFUNCTIONSsecuritygroupFB5E4F76", + "GroupId" + ] + } + ], + "SubnetIds": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ], + "VpcEndpointType": "Interface" + } + }, + "newresourcesECRAPIsecuritygroupE52BAE3F": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "new-resources/new-resources-ECR_API-security-group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + "Description": { + "Fn::Join": [ + "", + [ + "from ", + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + ":443" + ] + ] + }, + "FromPort": 443, + "IpProtocol": "tcp", + "ToPort": 443 + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Egress of 0.0.0.0/0 is default and generally considered OK" + }, + { + "id": "W40", + "reason": "Egress IPProtocol of -1 is default and generally considered OK" + } + ] + } + } + }, + "newresourcesECRDKRsecuritygroupBA34F94F": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "new-resources/new-resources-ECR_DKR-security-group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + "Description": { + "Fn::Join": [ + "", + [ + "from ", + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + ":443" + ] + ] + }, + "FromPort": 443, + "IpProtocol": "tcp", + "ToPort": 443 + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Egress of 0.0.0.0/0 is default and generally considered OK" + }, + { + "id": "W40", + "reason": "Egress IPProtocol of -1 is default and generally considered OK" + } + ] + } + } + }, + "testclusterDF8B0D19": { + "Type": "AWS::ECS::Cluster" + }, + "testtaskdefTaskRoleB2DEF113": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "testtaskdefTaskRoleDefaultPolicy5D591D1C": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "testconstructStateMachine3333AAA9" + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "Roles": [ + { + "Ref": "testtaskdefTaskRoleB2DEF113" + } + ] + } + }, + "testtaskdefF924AD58": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Environment": [ + { + "Name": "CUSTOM_NAME", + "Value": { + "Ref": "testconstructStateMachine3333AAA9" + } + } + ], + "Essential": true, + "Image": "nginx", + "MemoryReservation": 512, + "Name": "test-container", + "PortMappings": [ + { + "ContainerPort": 8080, + "Protocol": "tcp" + } + ] + } + ], + "Cpu": "256", + "Family": "newresourcestesttaskdef75720C83", + "Memory": "512", + "NetworkMode": "awsvpc", + "RequiresCompatibilities": [ + "FARGATE" + ], + "TaskRoleArn": { + "Fn::GetAtt": [ + "testtaskdefTaskRoleB2DEF113", + "Arn" + ] + } + } + }, + "testsg872EB48A": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Construct created security group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Egress of 0.0.0.0/0 is default and generally considered OK" + }, + { + "id": "W40", + "reason": "Egress IPProtocol of -1 is default and generally considered OK" + } + ] + } + } + }, + "testserviceService2730C249": { + "Type": "AWS::ECS::Service", + "Properties": { + "Cluster": { + "Ref": "testclusterDF8B0D19" + }, + "DeploymentConfiguration": { + "MaximumPercent": 150, + "MinimumHealthyPercent": 75 + }, + "DesiredCount": 2, + "EnableECSManagedTags": false, + "LaunchType": "FARGATE", + "NetworkConfiguration": { + "AwsvpcConfiguration": { + "AssignPublicIp": "DISABLED", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "testsg872EB48A", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ] + } + }, + "PlatformVersion": "LATEST", + "TaskDefinition": { + "Ref": "testtaskdefF924AD58" + } + } + }, + "testconstructStateMachineLogGroup2EB4F48B": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "/aws/vendedlogs/states/newresourcestestconstructstatemachinelog63b3cb15f80b" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely" + }, + { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)" + } + ] + } + } + }, + "testconstructStateMachineRoleA396E5D3": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.us-east-1.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "testconstructStateMachineRoleDefaultPolicyF10A684E": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogDelivery", + "logs:GetLogDelivery", + "logs:UpdateLogDelivery", + "logs:DeleteLogDelivery", + "logs:ListLogDeliveries" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:PutResourcePolicy", + "logs:DescribeResourcePolicies", + "logs:DescribeLogGroups" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "testconstructStateMachineRoleDefaultPolicyF10A684E", + "Roles": [ + { + "Ref": "testconstructStateMachineRoleA396E5D3" + } + ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W12", + "reason": "The 'LogDelivery' actions do not support resource-level authorizations" + } + ] + } + } + }, + "testconstructStateMachine3333AAA9": { + "Type": "AWS::StepFunctions::StateMachine", + "Properties": { + "RoleArn": { + "Fn::GetAtt": [ + "testconstructStateMachineRoleA396E5D3", + "Arn" + ] + }, + "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", + "LoggingConfiguration": { + "Destinations": [ + { + "CloudWatchLogsLogGroup": { + "LogGroupArn": { + "Fn::GetAtt": [ + "testconstructStateMachineLogGroup2EB4F48B", + "Arn" + ] + } + } + } + ], + "Level": "ERROR" + } + }, + "DependsOn": [ + "testconstructStateMachineRoleDefaultPolicyF10A684E", + "testconstructStateMachineRoleA396E5D3" + ] + }, + "testconstructExecutionFailedAlarmE9CEA29E": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 1, + "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "Dimensions": [ + { + "Name": "StateMachineArn", + "Value": { + "Ref": "testconstructStateMachine3333AAA9" + } + } + ], + "MetricName": "ExecutionsFailed", + "Namespace": "AWS/States", + "Period": 300, + "Statistic": "Sum", + "Threshold": 1 + } + }, + "testconstructExecutionThrottledAlarmEE993A2A": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 1, + "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "Dimensions": [ + { + "Name": "StateMachineArn", + "Value": { + "Ref": "testconstructStateMachine3333AAA9" + } + } + ], + "MetricName": "ExecutionThrottled", + "Namespace": "AWS/States", + "Period": 300, + "Statistic": "Sum", + "Threshold": 1 + } + }, + "testconstructExecutionAbortedAlarm2BC3DDB8": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 1, + "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "Dimensions": [ + { + "Name": "StateMachineArn", + "Value": { + "Ref": "testconstructStateMachine3333AAA9" + } + } + ], + "MetricName": "ExecutionsAborted", + "Namespace": "AWS/States", + "Period": 300, + "Statistic": "Maximum", + "Threshold": 1 + } + }, + "newresourcesSTEPFUNCTIONSsecuritygroupFB5E4F76": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "new-resources/new-resources-STEP_FUNCTIONS-security-group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + "Description": { + "Fn::Join": [ + "", + [ + "from ", + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + ":443" + ] + ] + }, + "FromPort": 443, + "IpProtocol": "tcp", + "ToPort": 443 + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Egress of 0.0.0.0/0 is default and generally considered OK" + }, + { + "id": "W40", + "reason": "Egress IPProtocol of -1 is default and generally considered OK" + } + ] + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.ts new file mode 100644 index 000000000..68cdedc3e --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.new-resources.ts @@ -0,0 +1,59 @@ +/** + * Copyright 2022 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 { Aws, App, Stack, RemovalPolicy } from "@aws-cdk/core"; +import { FargateToStepfunctions, FargateToStepfunctionsProps } from "../lib"; +import * as ecs from '@aws-cdk/aws-ecs'; +import * as defaults from '@aws-solutions-constructs/core'; +import * as stepfunctions from '@aws-cdk/aws-stepfunctions'; + +// Setup +const app = new App(); +const stack = new Stack(app, defaults.generateIntegStackName(__filename), { + env: { account: Aws.ACCOUNT_ID, region: 'us-east-1' }, +}); +stack.templateOptions.description = 'Integration Test with new VPC, Service and a state machine'; + +const existingVpc = defaults.getTestVpc(stack); +const startState = new stepfunctions.Pass(stack, 'StartState'); +const image = ecs.ContainerImage.fromRegistry('nginx'); + +const [testService, testContainer] = defaults.CreateFargateService(stack, + 'test', + existingVpc, + undefined, + undefined, + undefined, + undefined, + { image }, +); + +const constructProps: FargateToStepfunctionsProps = { + publicApi: true, + existingVpc, + stateMachineProps: { + definition: startState + }, + existingContainerDefinitionObject: testContainer, + existingFargateServiceObject: testService, + stateMachineEnvironmentVariableName: 'CUSTOM_NAME', + logGroupProps: { + removalPolicy: RemovalPolicy.DESTROY + } +}; + +new FargateToStepfunctions(stack, 'test-construct', constructProps); + +// Synth +app.synth(); \ No newline at end of file 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 new file mode 100644 index 000000000..1eb6a03a8 --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.expected.json @@ -0,0 +1,1292 @@ +{ + "Description": "Integration Test with new VPC, Service and a state machine with no CloudWatch alarms", + "Resources": { + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "172.168.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc" + } + ] + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1a", + "CidrBlock": "172.168.0.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet1" + } + ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W33", + "reason": "Allow Public Subnets to have MapPublicIpOnLaunch set to true" + } + ] + } + } + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1RouteTableAssociation97140677": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet1EIPD7E02669": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1NATGateway4D7517AA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet2Subnet691E08A3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1b", + "CidrBlock": "172.168.32.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet2" + } + ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W33", + "reason": "Allow Public Subnets to have MapPublicIpOnLaunch set to true" + } + ] + } + } + }, + "VpcPublicSubnet2RouteTable94F7E489": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "VpcPublicSubnet2DefaultRoute97F91067": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet2EIP3C605A87": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2NATGateway9182C01D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet3SubnetBE12F0B6": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1c", + "CidrBlock": "172.168.64.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet3" + } + ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W33", + "reason": "Allow Public Subnets to have MapPublicIpOnLaunch set to true" + } + ] + } + } + }, + "VpcPublicSubnet3RouteTable93458DBB": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet3" + } + ] + } + }, + "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + } + } + }, + "VpcPublicSubnet3DefaultRoute4697774F": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet3EIP3A666A23": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet3" + } + ] + } + }, + "VpcPublicSubnet3NATGateway7640CD1D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet3EIP3A666A23", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PublicSubnet3" + } + ] + } + }, + "VpcPrivateSubnet1Subnet536B997A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1a", + "CidrBlock": "172.168.96.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet1" + } + ] + } + }, + "VpcPrivateSubnet1RouteTableB2C5B500": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet1" + } + ] + } + }, + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "VpcPrivateSubnet1DefaultRouteBE02A9ED": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + } + } + }, + "VpcPrivateSubnet2Subnet3788AAA1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1b", + "CidrBlock": "172.168.128.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet2" + } + ] + } + }, + "VpcPrivateSubnet2RouteTableA678073B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet2" + } + ] + } + }, + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "VpcPrivateSubnet2DefaultRoute060D2087": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + } + } + }, + "VpcPrivateSubnet3SubnetF258B56E": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "AvailabilityZone": "test-region-1c", + "CidrBlock": "172.168.160.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet3" + } + ] + } + }, + "VpcPrivateSubnet3RouteTableD98824C7": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc/PrivateSubnet3" + } + ] + } + }, + "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + } + }, + "VpcPrivateSubnet3DefaultRoute94B74F0D": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet3NATGateway7640CD1D" + } + } + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + } + } + }, + "VpcFlowLogIAMRole6A475D41": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "vpc-flow-logs.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc" + } + ] + } + }, + "VpcFlowLogIAMRoleDefaultPolicy406FB995": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogStreams" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "VpcFlowLogLogGroup7B5C56B9", + "Arn" + ] + } + }, + { + "Action": "iam:PassRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "VpcFlowLogIAMRole6A475D41", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "VpcFlowLogIAMRoleDefaultPolicy406FB995", + "Roles": [ + { + "Ref": "VpcFlowLogIAMRole6A475D41" + } + ] + } + }, + "VpcFlowLogLogGroup7B5C56B9": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "RetentionInDays": 731, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc" + } + ] + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)" + } + ] + } + } + }, + "VpcFlowLog8FF33A73": { + "Type": "AWS::EC2::FlowLog", + "Properties": { + "ResourceId": { + "Ref": "Vpc8378EB38" + }, + "ResourceType": "VPC", + "TrafficType": "ALL", + "DeliverLogsPermissionArn": { + "Fn::GetAtt": [ + "VpcFlowLogIAMRole6A475D41", + "Arn" + ] + }, + "LogDestinationType": "cloud-watch-logs", + "LogGroupName": { + "Ref": "VpcFlowLogLogGroup7B5C56B9" + }, + "Tags": [ + { + "Key": "Name", + "Value": "no-cloudwatch-alarms/Vpc" + } + ] + } + }, + "VpcECRAPI9A3B6A2B": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "ServiceName": "com.amazonaws.us-east-1.ecr.api", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "nocloudwatchalarmsECRAPIsecuritygroupA72029F8", + "GroupId" + ] + } + ], + "SubnetIds": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ], + "VpcEndpointType": "Interface" + } + }, + "VpcECRDKR604E039F": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "ServiceName": "com.amazonaws.us-east-1.ecr.dkr", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "nocloudwatchalarmsECRDKRsecuritygroup11863825", + "GroupId" + ] + } + ], + "SubnetIds": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ], + "VpcEndpointType": "Interface" + } + }, + "VpcS3A5408339": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "RouteTableIds": [ + { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + { + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" + }, + { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + { + "Ref": "VpcPublicSubnet3RouteTable93458DBB" + } + ], + "VpcEndpointType": "Gateway" + } + }, + "VpcSTEPFUNCTIONS550F8CB6": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "ServiceName": "com.amazonaws.us-east-1.states", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "nocloudwatchalarmsSTEPFUNCTIONSsecuritygroupE67433DC", + "GroupId" + ] + } + ], + "SubnetIds": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ], + "VpcEndpointType": "Interface" + } + }, + "nocloudwatchalarmsECRAPIsecuritygroupA72029F8": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "no-cloudwatch-alarms/no-cloudwatch-alarms-ECR_API-security-group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + "Description": { + "Fn::Join": [ + "", + [ + "from ", + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + ":443" + ] + ] + }, + "FromPort": 443, + "IpProtocol": "tcp", + "ToPort": 443 + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Egress of 0.0.0.0/0 is default and generally considered OK" + }, + { + "id": "W40", + "reason": "Egress IPProtocol of -1 is default and generally considered OK" + } + ] + } + } + }, + "nocloudwatchalarmsECRDKRsecuritygroup11863825": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "no-cloudwatch-alarms/no-cloudwatch-alarms-ECR_DKR-security-group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + "Description": { + "Fn::Join": [ + "", + [ + "from ", + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + ":443" + ] + ] + }, + "FromPort": 443, + "IpProtocol": "tcp", + "ToPort": 443 + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Egress of 0.0.0.0/0 is default and generally considered OK" + }, + { + "id": "W40", + "reason": "Egress IPProtocol of -1 is default and generally considered OK" + } + ] + } + } + }, + "testclusterDF8B0D19": { + "Type": "AWS::ECS::Cluster" + }, + "testtaskdefTaskRoleB2DEF113": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "testtaskdefTaskRoleDefaultPolicy5D591D1C": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "testconstructStateMachine3333AAA9" + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "testtaskdefTaskRoleDefaultPolicy5D591D1C", + "Roles": [ + { + "Ref": "testtaskdefTaskRoleB2DEF113" + } + ] + } + }, + "testtaskdefF924AD58": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Environment": [ + { + "Name": "STATE_MACHINE_ARN", + "Value": { + "Ref": "testconstructStateMachine3333AAA9" + } + } + ], + "Essential": true, + "Image": "nginx", + "MemoryReservation": 512, + "Name": "test-container", + "PortMappings": [ + { + "ContainerPort": 8080, + "Protocol": "tcp" + } + ] + } + ], + "Cpu": "256", + "Family": "nocloudwatchalarmstesttaskdef18D90B7C", + "Memory": "512", + "NetworkMode": "awsvpc", + "RequiresCompatibilities": [ + "FARGATE" + ], + "TaskRoleArn": { + "Fn::GetAtt": [ + "testtaskdefTaskRoleB2DEF113", + "Arn" + ] + } + } + }, + "testsg872EB48A": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Construct created security group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Egress of 0.0.0.0/0 is default and generally considered OK" + }, + { + "id": "W40", + "reason": "Egress IPProtocol of -1 is default and generally considered OK" + } + ] + } + } + }, + "testserviceService2730C249": { + "Type": "AWS::ECS::Service", + "Properties": { + "Cluster": { + "Ref": "testclusterDF8B0D19" + }, + "DeploymentConfiguration": { + "MaximumPercent": 150, + "MinimumHealthyPercent": 75 + }, + "DesiredCount": 2, + "EnableECSManagedTags": false, + "LaunchType": "FARGATE", + "NetworkConfiguration": { + "AwsvpcConfiguration": { + "AssignPublicIp": "DISABLED", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "testsg872EB48A", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ] + } + }, + "PlatformVersion": "LATEST", + "TaskDefinition": { + "Ref": "testtaskdefF924AD58" + } + } + }, + "testconstructStateMachineLogGroup2EB4F48B": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "/aws/vendedlogs/states/nocloudwatchalarmstestconstructstatemachinelogdbb9902b27ea" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely" + }, + { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)" + } + ] + } + } + }, + "testconstructStateMachineRoleA396E5D3": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.us-east-1.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "testconstructStateMachineRoleDefaultPolicyF10A684E": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogDelivery", + "logs:GetLogDelivery", + "logs:UpdateLogDelivery", + "logs:DeleteLogDelivery", + "logs:ListLogDeliveries" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:PutResourcePolicy", + "logs:DescribeResourcePolicies", + "logs:DescribeLogGroups" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "testconstructStateMachineRoleDefaultPolicyF10A684E", + "Roles": [ + { + "Ref": "testconstructStateMachineRoleA396E5D3" + } + ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W12", + "reason": "The 'LogDelivery' actions do not support resource-level authorizations" + } + ] + } + } + }, + "testconstructStateMachine3333AAA9": { + "Type": "AWS::StepFunctions::StateMachine", + "Properties": { + "RoleArn": { + "Fn::GetAtt": [ + "testconstructStateMachineRoleA396E5D3", + "Arn" + ] + }, + "DefinitionString": "{\"StartAt\":\"StartState\",\"States\":{\"StartState\":{\"Type\":\"Pass\",\"End\":true}}}", + "LoggingConfiguration": { + "Destinations": [ + { + "CloudWatchLogsLogGroup": { + "LogGroupArn": { + "Fn::GetAtt": [ + "testconstructStateMachineLogGroup2EB4F48B", + "Arn" + ] + } + } + } + ], + "Level": "ERROR" + } + }, + "DependsOn": [ + "testconstructStateMachineRoleDefaultPolicyF10A684E", + "testconstructStateMachineRoleA396E5D3" + ] + }, + "nocloudwatchalarmsSTEPFUNCTIONSsecuritygroupE67433DC": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "no-cloudwatch-alarms/no-cloudwatch-alarms-STEP_FUNCTIONS-security-group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + "Description": { + "Fn::Join": [ + "", + [ + "from ", + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "CidrBlock" + ] + }, + ":443" + ] + ] + }, + "FromPort": 443, + "IpProtocol": "tcp", + "ToPort": 443 + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Egress of 0.0.0.0/0 is default and generally considered OK" + }, + { + "id": "W40", + "reason": "Egress IPProtocol of -1 is default and generally considered OK" + } + ] + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.ts new file mode 100644 index 000000000..1f8081f64 --- /dev/null +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-stepfunctions/test/integ.no-cloudwatch-alarms.ts @@ -0,0 +1,59 @@ +/** + * Copyright 2022 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 { Aws, App, Stack, RemovalPolicy } from "@aws-cdk/core"; +import { FargateToStepfunctions, FargateToStepfunctionsProps } from "../lib"; +import * as ecs from '@aws-cdk/aws-ecs'; +import * as defaults from '@aws-solutions-constructs/core'; +import * as stepfunctions from '@aws-cdk/aws-stepfunctions'; + +// Setup +const app = new App(); +const stack = new Stack(app, defaults.generateIntegStackName(__filename), { + env: { account: Aws.ACCOUNT_ID, region: 'us-east-1' }, +}); +stack.templateOptions.description = 'Integration Test with new VPC, Service and a state machine with no CloudWatch alarms'; + +const existingVpc = defaults.getTestVpc(stack); +const startState = new stepfunctions.Pass(stack, 'StartState'); +const image = ecs.ContainerImage.fromRegistry('nginx'); + +const [testService, testContainer] = defaults.CreateFargateService(stack, + 'test', + existingVpc, + undefined, + undefined, + undefined, + undefined, + { image }, +); + +const constructProps: FargateToStepfunctionsProps = { + publicApi: true, + existingVpc, + stateMachineProps: { + definition: startState + }, + existingContainerDefinitionObject: testContainer, + existingFargateServiceObject: testService, + createCloudWatchAlarms: false, + logGroupProps: { + removalPolicy: RemovalPolicy.DESTROY + } +}; + +new FargateToStepfunctions(stack, 'test-construct', constructProps); + +// Synth +app.synth(); \ No newline at end of file