Skip to content

Commit 6461b35

Browse files
authored
feat(aws-fargate-eventbridge): new construct (#696)
* created README * updated README * created new construct * add service count test * empty commit
1 parent bcc1216 commit 6461b35

12 files changed

+3247
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
lib/*.js
2+
test/*.js
3+
*.d.ts
4+
coverage
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
lib/*.js
2+
test/*.js
3+
!test/lambda/*
4+
*.js.map
5+
*.ts.map
6+
*.d.ts
7+
node_modules
8+
*.generated.ts
9+
dist
10+
.jsii
11+
12+
.LAST_BUILD
13+
.nyc_output
14+
coverage
15+
.nycrc
16+
.LAST_PACKAGE
17+
*.snk
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Exclude typescript source and config
2+
*.ts
3+
tsconfig.json
4+
coverage
5+
.nyc_output
6+
*.tgz
7+
*.snk
8+
*.tsbuildinfo
9+
10+
# Include javascript files and typescript declarations
11+
!*.js
12+
!*.d.ts
13+
14+
# Exclude jsii outdir
15+
dist
16+
17+
# Include .jsii
18+
!.jsii
19+
20+
# Include .jsii
21+
!.jsii
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# aws-fargate-eventbridge module
2+
<!--BEGIN STABILITY BANNER-->
3+
4+
---
5+
6+
![Stability: Experimental](https://img.shields.io/badge/stability-Experimental-important.svg?style=for-the-badge)
7+
8+
> All classes are under active development and subject to non-backward compatible changes or removal in any
9+
> future version. These are not subject to the [Semantic Versioning](https://semver.org/) model.
10+
> 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.
11+
12+
---
13+
<!--END STABILITY BANNER-->
14+
15+
| **Reference Documentation**:| <span style="font-weight: normal">https://docs.aws.amazon.com/solutions/latest/constructs/</span>|
16+
|:-------------|:-------------|
17+
<div style="height:8px"></div>
18+
19+
| **Language** | **Package** |
20+
|:-------------|-----------------|
21+
|![Python Logo](https://docs.aws.amazon.com/cdk/api/latest/img/python32.png) Python|`aws_solutions_constructs.aws_fargate_eventbridge`|
22+
|![Typescript Logo](https://docs.aws.amazon.com/cdk/api/latest/img/typescript32.png) Typescript|`@aws-solutions-constructs/aws-fargate-eventbridge`|
23+
|![Java Logo](https://docs.aws.amazon.com/cdk/api/latest/img/java32.png) Java|`software.amazon.awsconstructs.services.fargateeventbridge`|
24+
25+
This AWS Solutions Construct implements an AWS Fargate service connected to an Amazon EventBridge.
26+
27+
Here is a minimal deployable pattern definition:
28+
29+
Typescript
30+
``` typescript
31+
import { Construct } from 'constructs';
32+
import { Stack, StackProps } from 'aws-cdk-lib';
33+
import { FargateToEventbridge, FargateToEventbridgeProps } from '@aws-solutions-constructs/aws-fargate-eventbridge';
34+
35+
const constructProps: FargateToEventbridgeProps = {
36+
publicApi: true,
37+
ecrRepositoryArn: "arn:aws:ecr:us-east-1:123456789012:repository/your-ecr-repo",
38+
};
39+
40+
new FargateToEventbridge(this, 'test-construct', constructProps);
41+
```
42+
43+
Python
44+
``` python
45+
from aws_solutions_constructs.aws_fargate_eventbridge import FargateToEventbridge, FargateToEventbridgeProps
46+
from aws_cdk import (
47+
Stack
48+
)
49+
from constructs import Construct
50+
51+
FargateToEventbridge(self, 'test_construct',
52+
public_api=True,
53+
ecr_repository_arn="arn:aws:ecr:us-east-1:123456789012:repository/your-ecr-repo")
54+
```
55+
56+
Java
57+
``` java
58+
import software.constructs.Construct;
59+
60+
import software.amazon.awscdk.Stack;
61+
import software.amazon.awscdk.StackProps;
62+
import software.amazon.awsconstructs.services.fargateeventbridge.*;
63+
64+
new FargateToEventbridge(this, "test_construct", new FargateToEventbridgeProps.Builder()
65+
.publicApi(true)
66+
.ecrRepositoryArn("arn:aws:ecr:us-east-1:123456789012:repository/your-ecr-repo")
67+
.build());
68+
```
69+
## Pattern Construct Props
70+
71+
| **Name** | **Type** | **Description** |
72+
|:-------------|:----------------|-----------------|
73+
| publicApi | boolean | Whether the construct is deploying a private or public API. This has implications for the VPC. |
74+
| 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. |
75+
| 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. |
76+
| 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. |
77+
| 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* |
78+
| ecrImageVersion? | `string` | The version of the image to use from the repository. Defaults to 'Latest'|
79+
| 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) |
80+
| 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) |
81+
| 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. |
82+
| 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 |
83+
| 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 |
84+
| existingEventBusInterface? | [`events.IEventBus`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-events.IEventBus.html)| Optional user-provided custom event bus for construct to use. Providing both this and `eventBusProps` results an error.|
85+
| eventBusProps? | [`events.EventBusProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-events.EventBusProps.html)|Optional user-provided properties to override the default properties when creating a custom event bus. Setting this value to `{}` will create a custom event bus using all default properties. If neither this nor `existingEventBusInterface` is provided the construct will use the `default` event bus. Providing both this and `existingEventBusInterface` results an error.|
86+
|eventBusEnvironmentVariableName?|`string`|Optional Name for the container environment variable set to the DynamoDB table name. Default: EVENTBUS_NAME|
87+
88+
89+
## Pattern Properties
90+
91+
| **Name** | **Type** | **Description** |
92+
|:-------------|:----------------|-----------------|
93+
| 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) |
94+
| 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) |
95+
| 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. |
96+
| eventBus? | [`events.IEventBus`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-events.IEventBus.html)|Returns the instance of `events.IEventBus` used by the construct|
97+
98+
## Default settings
99+
100+
Out of the box implementation of the Construct without any override will set the following defaults:
101+
102+
### AWS Fargate Service
103+
* Sets up an AWS Fargate service
104+
* Uses the existing service if provided
105+
* Creates a new service if none provided.
106+
* Service will run in isolated subnets if available, then private subnets if available and finally public subnets
107+
* Adds environment variables to the container with the Name of the event bus
108+
* Default: EVENTBUS_NAME
109+
* Add permissions to the container IAM role allowing it to put events in the EventBridge event bus
110+
111+
### Amazon EventBridge Event Bus
112+
* Sets up an Amazon EventBridge event bus
113+
* Uses an existing event bus if one is provided, otherwise creates a new one if `eventBusProps` is provided
114+
* If neither `eventBusProps` nor `existingEventBusInterface` is provided, the construct will use the `default` event bus.
115+
* Adds an Interface Endpoint to the VPC for EventBridge (the service by default runs in Isolated or Private subnets)
116+
117+
## Architecture
118+
![Architecture Diagram](architecture.png)
119+
120+
***
121+
&copy; Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/**
2+
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
5+
* with the License. A copy of the License is located at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
10+
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
11+
* and limitations under the License.
12+
*/
13+
14+
import * as ec2 from "@aws-cdk/aws-ec2";
15+
// Note: To ensure CDKv2 compatibility, keep the import statement for Construct separate
16+
import { Construct } from "@aws-cdk/core";
17+
import * as defaults from "@aws-solutions-constructs/core";
18+
import * as ecs from "@aws-cdk/aws-ecs";
19+
import * as events from "@aws-cdk/aws-events";
20+
21+
export interface FargateToEventbridgeProps {
22+
/**
23+
* Whether the construct is deploying a private or public API. This has implications for the VPC deployed
24+
* by this construct.
25+
*
26+
* @default - None
27+
*/
28+
readonly publicApi: boolean;
29+
/**
30+
* Optional custom properties for a VPC the construct will create. This VPC will
31+
* be used by the new Fargate service the construct creates (that's
32+
* why targetGroupProps can't include a VPC). Providing
33+
* both this and existingVpc is an error. A Step Functions Interface
34+
* endpoint will be included in this VPC.
35+
*
36+
* @default - A set of defaults from vpc-defaults.ts: DefaultPublicPrivateVpcProps() for public APIs
37+
* and DefaultIsolatedVpcProps() for private APIs.
38+
*/
39+
readonly vpcProps?: ec2.VpcProps;
40+
/**
41+
* An existing VPC in which to deploy the construct. Providing both this and
42+
* vpcProps is an error. If the client provides an existing Fargate service,
43+
* this value must be the VPC where the service is running. A Step Functions Interface
44+
* endpoint will be added to this VPC.
45+
*
46+
* @default - None
47+
*/
48+
readonly existingVpc?: ec2.IVpc;
49+
/**
50+
* Optional properties to create a new ECS cluster
51+
*
52+
* @default - None
53+
*/
54+
readonly clusterProps?: ecs.ClusterProps;
55+
/**
56+
* The arn of an ECR Repository containing the image to use
57+
* to generate the containers
58+
*
59+
* format:
60+
* arn:aws:ecr:[region]:[account number]:repository/[Repository Name]
61+
*
62+
* @default - None
63+
*/
64+
readonly ecrRepositoryArn?: string;
65+
/**
66+
* The version of the image to use from the repository
67+
*
68+
* @default - 'latest'
69+
*/
70+
readonly ecrImageVersion?: string;
71+
/*
72+
* Optional props to define the container created for the Fargate Service
73+
*
74+
* @default - fargate-defaults.ts
75+
*/
76+
readonly containerDefinitionProps?: ecs.ContainerDefinitionProps | any;
77+
/*
78+
* Optional props to define the Fargate Task Definition for this construct
79+
*
80+
* @default - fargate-defaults.ts
81+
*/
82+
readonly fargateTaskDefinitionProps?: ecs.FargateTaskDefinitionProps | any;
83+
/**
84+
* Optional values to override default Fargate Task definition properties
85+
* (fargate-defaults.ts). The construct will default to launching the service
86+
* is the most isolated subnets available (precedence: Isolated, Private and
87+
* Public). Override those and other defaults here.
88+
*
89+
* @default - fargate-defaults.ts
90+
*/
91+
readonly fargateServiceProps?: ecs.FargateServiceProps | any;
92+
/**
93+
* A Fargate Service already instantiated (probably by another Solutions Construct). If
94+
* this is specified, then no props defining a new service can be provided, including:
95+
* existingImageObject, ecrImageVersion, containerDefintionProps, fargateTaskDefinitionProps,
96+
* ecrRepositoryArn, fargateServiceProps, clusterProps, existingClusterInterface. If this value
97+
* is provided, then existingContainerDefinitionObject must be provided as well.
98+
*
99+
* @default - None
100+
*/
101+
readonly existingFargateServiceObject?: ecs.FargateService;
102+
/*
103+
* A container definition already instantiated as part of a Fargate service. This must
104+
* be the container in the existingFargateServiceObject.
105+
*
106+
* @default - None
107+
*/
108+
readonly existingContainerDefinitionObject?: ecs.ContainerDefinition;
109+
/**
110+
* Existing instance of a custom EventBus.
111+
*
112+
* @default - None
113+
*/
114+
readonly existingEventBusInterface?: events.IEventBus;
115+
/**
116+
* A new custom EventBus is created with provided props.
117+
*
118+
* @default - None
119+
*/
120+
readonly eventBusProps?: events.EventBusProps;
121+
/**
122+
* Optional Name for the container environment variable set to the DynamoDB table name.
123+
*
124+
* @default - EVENTBUS_NAME
125+
*/
126+
readonly eventBusEnvironmentVariableName?: string;
127+
}
128+
129+
export class FargateToEventbridge extends Construct {
130+
public readonly vpc: ec2.IVpc;
131+
public readonly service: ecs.FargateService;
132+
public readonly container: ecs.ContainerDefinition;
133+
public readonly eventBus?: events.IEventBus;
134+
135+
constructor(scope: Construct, id: string, props: FargateToEventbridgeProps) {
136+
super(scope, id);
137+
defaults.CheckProps(props);
138+
defaults.CheckFargateProps(props);
139+
140+
this.vpc = defaults.buildVpc(scope, {
141+
existingVpc: props.existingVpc,
142+
defaultVpcProps: props.publicApi ? defaults.DefaultPublicPrivateVpcProps() : defaults.DefaultIsolatedVpcProps(),
143+
userVpcProps: props.vpcProps,
144+
constructVpcProps: { enableDnsHostnames: true, enableDnsSupport: true }
145+
});
146+
147+
defaults.AddAwsServiceEndpoint(scope, this.vpc, defaults.ServiceEndpointTypes.EVENTS);
148+
149+
if (props.existingFargateServiceObject) {
150+
this.service = props.existingFargateServiceObject;
151+
// CheckFargateProps confirms that the container is provided
152+
this.container = props.existingContainerDefinitionObject!;
153+
} else {
154+
[this.service, this.container] = defaults.CreateFargateService(
155+
scope,
156+
id,
157+
this.vpc,
158+
props.clusterProps,
159+
props.ecrRepositoryArn,
160+
props.ecrImageVersion,
161+
props.fargateTaskDefinitionProps,
162+
props.containerDefinitionProps,
163+
props.fargateServiceProps
164+
);
165+
}
166+
167+
this.eventBus = defaults.buildEventBus(this, {
168+
existingEventBusInterface: props.existingEventBusInterface,
169+
eventBusProps: props.eventBusProps
170+
});
171+
172+
if (this.eventBus) {
173+
this.eventBus.grantPutEventsTo(this.service.taskDefinition.taskRole);
174+
} else {
175+
// Since user didn't specify custom event bus, provide permissions on default event bus
176+
const defaultEventBus = events.EventBus.fromEventBusName(this, 'default-event-bus', 'default');
177+
defaultEventBus.grantPutEventsTo(this.service.taskDefinition.taskRole);
178+
}
179+
180+
// Add environment variables
181+
const eventBusEnvironmentVariableName = props.eventBusEnvironmentVariableName || 'EVENTBUS_NAME';
182+
const eventBusName = this.eventBus?.eventBusName || 'default';
183+
this.container.addEnvironment(eventBusEnvironmentVariableName, eventBusName);
184+
}
185+
}

0 commit comments

Comments
 (0)