Skip to content

Commit cbc27b1

Browse files
authored
Merge pull request #113 from cloudcomponents/fixes_112
feat: Add missing parameters
2 parents 6850e3b + ea847d7 commit cbc27b1

File tree

6 files changed

+120
-20
lines changed

6 files changed

+120
-20
lines changed

packages/cdk-blue-green-container-deployment/API.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ new DummyTaskDefinition(scope: Construct, id: string, props: DummyTaskDefinition
5757
* **scope** (<code>[Construct](#aws-cdk-core-construct)</code>) *No description*
5858
* **id** (<code>string</code>) *No description*
5959
* **props** (<code>[DummyTaskDefinitionProps](#cloudcomponents-cdk-blue-green-container-deployment-dummytaskdefinitionprops)</code>) *No description*
60-
* **image** (<code>string</code>) *No description*
61-
* **containerPort** (<code>number</code>) *No description* __*Optional*__
62-
* **family** (<code>string</code>) *No description* __*Optional*__
60+
* **image** (<code>string</code>) The image used to start a container.
61+
* **containerName** (<code>string</code>) The name of the container. __*Default*__: `sample-website`
62+
* **containerPort** (<code>number</code>) *No description* __*Default*__: 80
63+
* **family** (<code>string</code>) The name of a family that this task definition is registered to. __*Default*__: Automatically generated name.
6364

6465

6566

@@ -68,6 +69,7 @@ new DummyTaskDefinition(scope: Construct, id: string, props: DummyTaskDefinition
6869

6970
Name | Type | Description
7071
-----|------|-------------
72+
**containerName** | <code>string</code> | <span></span>
7173
**containerPort** | <code>number</code> | <span></span>
7274
**executionRole** | <code>[IRole](#aws-cdk-aws-iam-irole)</code> | <span></span>
7375
**family** | <code>string</code> | <span></span>
@@ -157,9 +159,13 @@ new EcsService(scope: Construct, id: string, props: EcsServiceProps)
157159
* **prodTargetGroup** (<code>[ITargetGroup](#aws-cdk-aws-elasticloadbalancingv2-itargetgroup)</code>) *No description*
158160
* **serviceName** (<code>string</code>) *No description*
159161
* **taskDefinition** (<code>[DummyTaskDefinition](#cloudcomponents-cdk-blue-green-container-deployment-dummytaskdefinition)</code>) *No description*
162+
* **circuitBreaker** (<code>[DeploymentCircuitBreaker](#aws-cdk-aws-ecs-deploymentcircuitbreaker)</code>) Whether to enable the deployment circuit breaker. __*Default*__: disabled
160163
* **containerPort** (<code>number</code>) *No description* __*Optional*__
161164
* **desiredCount** (<code>number</code>) *No description* __*Optional*__
165+
* **healthCheckGracePeriod** (<code>[Duration](#aws-cdk-core-duration)</code>) The period of time, in seconds, that the Amazon ECS service scheduler ignores unhealthy Elastic Load Balancing target health checks after a task has first started. __*Default*__: defaults to 60 seconds if at least one load balancer is in-use and it is not already set
162166
* **launchType** (<code>[LaunchType](#aws-cdk-aws-ecs-launchtype)</code>) *No description* __*Optional*__
167+
* **maxHealthyPercent** (<code>number</code>) The maximum number of tasks, specified as a percentage of the Amazon ECS service's DesiredCount value, that can run in a service during a deployment. __*Default*__: 100 if daemon, otherwise 200
168+
* **minHealthyPercent** (<code>number</code>) The minimum number of tasks, specified as a percentage of the Amazon ECS service's DesiredCount value, that must continue to run and remain healthy during a deployment. __*Default*__: 0 if daemon, otherwise 50
163169
* **platformVersion** (<code>string</code>) *No description* __*Optional*__
164170
* **securityGroups** (<code>Array<[SecurityGroup](#aws-cdk-aws-ec2-securitygroup)></code>) *No description* __*Optional*__
165171

@@ -215,9 +221,10 @@ new PushImageProject(scope: Construct, id: string, props: PushImageProjectProps)
215221

216222
Name | Type | Description
217223
-----|------|-------------
218-
**image** | <code>string</code> | <span></span>
219-
**containerPort**? | <code>number</code> | __*Optional*__
220-
**family**? | <code>string</code> | __*Optional*__
224+
**image** | <code>string</code> | The image used to start a container.
225+
**containerName**? | <code>string</code> | The name of the container.<br/>__*Default*__: `sample-website`
226+
**containerPort**? | <code>number</code> | __*Default*__: 80
227+
**family**? | <code>string</code> | The name of a family that this task definition is registered to.<br/>__*Default*__: Automatically generated name.
221228

222229

223230

@@ -255,9 +262,13 @@ Name | Type | Description
255262
**prodTargetGroup** | <code>[ITargetGroup](#aws-cdk-aws-elasticloadbalancingv2-itargetgroup)</code> | <span></span>
256263
**serviceName** | <code>string</code> | <span></span>
257264
**taskDefinition** | <code>[DummyTaskDefinition](#cloudcomponents-cdk-blue-green-container-deployment-dummytaskdefinition)</code> | <span></span>
265+
**circuitBreaker**? | <code>[DeploymentCircuitBreaker](#aws-cdk-aws-ecs-deploymentcircuitbreaker)</code> | Whether to enable the deployment circuit breaker.<br/>__*Default*__: disabled
258266
**containerPort**? | <code>number</code> | __*Optional*__
259267
**desiredCount**? | <code>number</code> | __*Optional*__
268+
**healthCheckGracePeriod**? | <code>[Duration](#aws-cdk-core-duration)</code> | The period of time, in seconds, that the Amazon ECS service scheduler ignores unhealthy Elastic Load Balancing target health checks after a task has first started.<br/>__*Default*__: defaults to 60 seconds if at least one load balancer is in-use and it is not already set
260269
**launchType**? | <code>[LaunchType](#aws-cdk-aws-ecs-launchtype)</code> | __*Optional*__
270+
**maxHealthyPercent**? | <code>number</code> | The maximum number of tasks, specified as a percentage of the Amazon ECS service's DesiredCount value, that can run in a service during a deployment.<br/>__*Default*__: 100 if daemon, otherwise 200
271+
**minHealthyPercent**? | <code>number</code> | The minimum number of tasks, specified as a percentage of the Amazon ECS service's DesiredCount value, that must continue to run and remain healthy during a deployment.<br/>__*Default*__: 0 if daemon, otherwise 50
261272
**platformVersion**? | <code>string</code> | __*Optional*__
262273
**securityGroups**? | <code>Array<[SecurityGroup](#aws-cdk-aws-ec2-securitygroup)></code> | __*Optional*__
263274

@@ -274,6 +285,8 @@ __Implemented by__: [DummyTaskDefinition](#cloudcomponents-cdk-blue-green-contai
274285

275286
Name | Type | Description
276287
-----|------|-------------
288+
**containerName** | <code>string</code> | <span></span>
289+
**containerPort** | <code>number</code> | <span></span>
277290
**executionRole** | <code>[IRole](#aws-cdk-aws-iam-irole)</code> | <span></span>
278291
**family** | <code>string</code> | <span></span>
279292
**taskDefinitionArn** | <code>string</code> | <span></span>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[{"timestamp":1609276390870,"files":[{"filename":"dummy-task-definition/index.js","previous":1712,"size":1726,"diff":14},{"filename":"ecs-deployment-group/index.js","previous":2123,"size":2123,"diff":0},{"filename":"ecs-service/index.js","previous":2081,"size":2081,"diff":0}]},{"timestamp":1606329521054,"files":[{"filename":"dummy-task-definition/index.js","previous":1706,"size":1712,"diff":6},{"filename":"ecs-deployment-group/index.js","previous":2116,"size":2123,"diff":7},{"filename":"ecs-service/index.js","previous":2073,"size":2081,"diff":8}]},{"timestamp":1596457247342,"files":[{"filename":"dummy-task-definition/index.js","previous":1756,"size":1706,"diff":-50},{"filename":"ecs-deployment-group/index.js","previous":2116,"size":2116,"diff":0},{"filename":"ecs-service/index.js","previous":2073,"size":2073,"diff":0}]},{"timestamp":1596454924871,"files":[{"filename":"dummy-task-definition/index.js","previous":4964,"size":1756,"diff":-3208},{"filename":"ecs-deployment-group/index.js","previous":6103,"size":2116,"diff":-3987},{"filename":"ecs-service/index.js","previous":6141,"size":2073,"diff":-4068}]},{"timestamp":1596407637937,"files":[{"filename":"blue-green-service/__entrypoint__.js","previous":6760,"size":0,"diff":-6760},{"filename":"blue-green-service/index.js","previous":3368,"size":0,"diff":-3368},{"filename":"dummy-task-definition/__entrypoint__.js","previous":6760,"size":0,"diff":-6760},{"filename":"dummy-task-definition/index.js","previous":1963,"size":4964,"diff":3001},{"filename":"ecs-deployment-group/__entrypoint__.js","previous":6760,"size":0,"diff":-6760},{"filename":"ecs-deployment-group/index.js","previous":2292,"size":6103,"diff":3811},{"filename":"ecs-service/__entrypoint__.js","previous":6760,"size":0,"diff":-6760},{"filename":"ecs-service/index.js","previous":2312,"size":6141,"diff":3829}]}]
1+
[{"timestamp":1627652613714,"files":[{"filename":"dummy-task-definition/index.js","previous":1726,"size":1728,"diff":2},{"filename":"ecs-deployment-group/index.js","previous":2123,"size":2123,"diff":0},{"filename":"ecs-service/index.js","previous":2081,"size":2152,"diff":71}]},{"timestamp":1609276390870,"files":[{"filename":"dummy-task-definition/index.js","previous":1712,"size":1726,"diff":14},{"filename":"ecs-deployment-group/index.js","previous":2123,"size":2123,"diff":0},{"filename":"ecs-service/index.js","previous":2081,"size":2081,"diff":0}]},{"timestamp":1606329521054,"files":[{"filename":"dummy-task-definition/index.js","previous":1706,"size":1712,"diff":6},{"filename":"ecs-deployment-group/index.js","previous":2116,"size":2123,"diff":7},{"filename":"ecs-service/index.js","previous":2073,"size":2081,"diff":8}]},{"timestamp":1596457247342,"files":[{"filename":"dummy-task-definition/index.js","previous":1756,"size":1706,"diff":-50},{"filename":"ecs-deployment-group/index.js","previous":2116,"size":2116,"diff":0},{"filename":"ecs-service/index.js","previous":2073,"size":2073,"diff":0}]},{"timestamp":1596454924871,"files":[{"filename":"dummy-task-definition/index.js","previous":4964,"size":1756,"diff":-3208},{"filename":"ecs-deployment-group/index.js","previous":6103,"size":2116,"diff":-3987},{"filename":"ecs-service/index.js","previous":6141,"size":2073,"diff":-4068}]},{"timestamp":1596407637937,"files":[{"filename":"blue-green-service/__entrypoint__.js","previous":6760,"size":0,"diff":-6760},{"filename":"blue-green-service/index.js","previous":3368,"size":0,"diff":-3368},{"filename":"dummy-task-definition/__entrypoint__.js","previous":6760,"size":0,"diff":-6760},{"filename":"dummy-task-definition/index.js","previous":1963,"size":4964,"diff":3001},{"filename":"ecs-deployment-group/__entrypoint__.js","previous":6760,"size":0,"diff":-6760},{"filename":"ecs-deployment-group/index.js","previous":2292,"size":6103,"diff":3811},{"filename":"ecs-service/__entrypoint__.js","previous":6760,"size":0,"diff":-6760},{"filename":"ecs-service/index.js","previous":2312,"size":6141,"diff":3829}]}]

packages/cdk-blue-green-container-deployment/src/dummy-task-definition.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,34 @@ export interface IDummyTaskDefinition {
1010
readonly family: string;
1111

1212
readonly taskDefinitionArn: string;
13+
14+
readonly containerName: string;
15+
16+
readonly containerPort: number;
1317
}
1418
export interface DummyTaskDefinitionProps {
19+
/**
20+
* The name of a family that this task definition is registered to. A family groups multiple versions of a task definition.
21+
*
22+
* @default - Automatically generated name.
23+
*/
1524
readonly family?: string;
1625

26+
/**
27+
* The image used to start a container.
28+
*/
1729
readonly image: string;
1830

31+
/**
32+
* The name of the container.
33+
*
34+
* @default `sample-website`
35+
*/
36+
readonly containerName?: string;
37+
38+
/**
39+
* @default 80
40+
*/
1941
readonly containerPort?: number;
2042
}
2143

@@ -26,6 +48,8 @@ export class DummyTaskDefinition extends Construct implements IDummyTaskDefiniti
2648

2749
public readonly taskDefinitionArn: string;
2850

51+
public readonly containerName: string;
52+
2953
public readonly containerPort: number;
3054

3155
constructor(scope: Construct, id: string, props: DummyTaskDefinitionProps) {
@@ -53,8 +77,9 @@ export class DummyTaskDefinition extends Construct implements IDummyTaskDefiniti
5377
],
5478
});
5579

56-
this.family = props.family || this.node.addr;
57-
this.containerPort = props.containerPort || 80;
80+
this.family = props.family ?? this.node.addr;
81+
this.containerName = props.containerName ?? 'sample-website';
82+
this.containerPort = props.containerPort ?? 80;
5883

5984
const taskDefinition = new CustomResource(this, 'CustomResource', {
6085
serviceToken,
@@ -64,6 +89,7 @@ export class DummyTaskDefinition extends Construct implements IDummyTaskDefiniti
6489
Image: props.image,
6590
ExecutionRoleArn: this.executionRole.roleArn,
6691
NetworkMode: NetworkMode.AWS_VPC,
92+
ContainerName: this.containerName,
6793
ContainerPort: this.containerPort,
6894
},
6995
});

packages/cdk-blue-green-container-deployment/src/ecs-service.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as path from 'path';
22
import { IConnectable, Connections, SecurityGroup, Port } from '@aws-cdk/aws-ec2';
3-
import { ICluster, LaunchType } from '@aws-cdk/aws-ecs';
3+
import { ICluster, LaunchType, DeploymentCircuitBreaker } from '@aws-cdk/aws-ecs';
44
import { ITargetGroup } from '@aws-cdk/aws-elasticloadbalancingv2';
55
import { Effect } from '@aws-cdk/aws-iam';
6-
import { Construct, CustomResource, CustomResourceProvider, CustomResourceProviderRuntime } from '@aws-cdk/core';
6+
import { Duration, Construct, CustomResource, CustomResourceProvider, CustomResourceProviderRuntime } from '@aws-cdk/core';
77

88
import { DummyTaskDefinition } from './dummy-task-definition';
99

@@ -22,6 +22,39 @@ export interface EcsServiceProps {
2222
readonly containerPort?: number;
2323
readonly prodTargetGroup: ITargetGroup;
2424
readonly taskDefinition: DummyTaskDefinition;
25+
26+
/**
27+
* The period of time, in seconds, that the Amazon ECS service scheduler ignores unhealthy
28+
* Elastic Load Balancing target health checks after a task has first started.
29+
*
30+
* @default - defaults to 60 seconds if at least one load balancer is in-use and it is not already set
31+
*/
32+
readonly healthCheckGracePeriod?: Duration;
33+
34+
/**
35+
* The maximum number of tasks, specified as a percentage of the Amazon ECS
36+
* service's DesiredCount value, that can run in a service during a
37+
* deployment.
38+
*
39+
* @default - 100 if daemon, otherwise 200
40+
*/
41+
readonly maxHealthyPercent?: number;
42+
43+
/**
44+
* The minimum number of tasks, specified as a percentage of
45+
* the Amazon ECS service's DesiredCount value, that must
46+
* continue to run and remain healthy during a deployment.
47+
*
48+
* @default - 0 if daemon, otherwise 50
49+
*/
50+
readonly minHealthyPercent?: number;
51+
52+
/**
53+
* Whether to enable the deployment circuit breaker. If this property is defined, circuit breaker will be implicitly
54+
* enabled.
55+
* @default - disabled
56+
*/
57+
readonly circuitBreaker?: DeploymentCircuitBreaker;
2558
}
2659

2760
export class EcsService extends Construct implements IConnectable, IEcsService {
@@ -40,6 +73,7 @@ export class EcsService extends Construct implements IConnectable, IEcsService {
4073
desiredCount = 1,
4174
prodTargetGroup,
4275
taskDefinition,
76+
healthCheckGracePeriod = Duration.seconds(60),
4377
} = props;
4478

4579
const containerPort = props.containerPort ?? taskDefinition.containerPort;
@@ -76,6 +110,7 @@ export class EcsService extends Construct implements IConnectable, IEcsService {
76110
properties: {
77111
Cluster: cluster.clusterName,
78112
ServiceName: serviceName,
113+
ContainerName: taskDefinition.containerName,
79114
TaskDefinition: taskDefinition.taskDefinitionArn,
80115
LaunchType: launchType,
81116
PlatformVersion: platformVersion,
@@ -85,6 +120,17 @@ export class EcsService extends Construct implements IConnectable, IEcsService {
85120
TargetGroupArn: prodTargetGroup.targetGroupArn,
86121
ContainerPort: containerPort,
87122
SchedulingStrategy: SchedulingStrategy.REPLICA,
123+
HealthCheckGracePeriod: healthCheckGracePeriod.toSeconds(),
124+
DeploymentConfiguration: {
125+
maximumPercent: props.maxHealthyPercent ?? 200,
126+
minimumHealthyPercent: props.minHealthyPercent ?? 50,
127+
deploymentCircuitBreaker: props.circuitBreaker
128+
? {
129+
enable: true,
130+
rollback: props.circuitBreaker.rollback ?? false,
131+
}
132+
: undefined,
133+
},
88134
},
89135
});
90136

packages/cdk-blue-green-container-deployment/src/lambdas/dummy-task-definition/index.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,23 @@ export interface EcsTaskDefinitionProps {
1010
image: string;
1111
executionRoleArn: string;
1212
networkMode: string;
13+
containerName: string;
1314
containerPort: number;
1415
}
1516

1617
const ecs = new ECS();
1718

1819
const getProperties = (props: CloudFormationCustomResourceEvent['ResourceProperties']): EcsTaskDefinitionProps => ({
19-
family: props.Family as string,
20-
image: props.Image as string,
21-
executionRoleArn: props.ExecutionRoleArn as string,
22-
networkMode: props.NetworkMode as string,
23-
containerPort: props.ContainerPort as number,
20+
family: props.Family,
21+
image: props.Image,
22+
executionRoleArn: props.ExecutionRoleArn,
23+
networkMode: props.NetworkMode,
24+
containerName: props.ContainerName,
25+
containerPort: props.ContainerPort,
2426
});
2527

2628
const onCreate = async (event: CloudFormationCustomResourceCreateEvent): Promise<HandlerReturn> => {
27-
const { family, image, executionRoleArn, networkMode, containerPort } = getProperties(event.ResourceProperties);
29+
const { family, image, executionRoleArn, networkMode, containerName, containerPort } = getProperties(event.ResourceProperties);
2830

2931
const { taskDefinition } = await ecs
3032
.registerTaskDefinition({
@@ -36,7 +38,7 @@ const onCreate = async (event: CloudFormationCustomResourceCreateEvent): Promise
3638
memory: '512',
3739
containerDefinitions: [
3840
{
39-
name: 'sample-website',
41+
name: containerName,
4042
image,
4143
portMappings: [
4244
{

packages/cdk-blue-green-container-deployment/src/lambdas/ecs-service/index.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface HandlerReturn {
1616
export interface BlueGreenServiceProps {
1717
cluster: string;
1818
serviceName: string;
19+
containerName: string;
1920
taskDefinition: string;
2021
launchType: string;
2122
platformVersion: string;
@@ -25,13 +26,16 @@ export interface BlueGreenServiceProps {
2526
targetGroupArn: string;
2627
containerPort: number;
2728
schedulingStrategy: string;
29+
healthCheckGracePeriodSeconds: number;
30+
deploymentConfiguration: ECS.DeploymentConfiguration;
2831
}
2932

3033
const ecs = new ECS();
3134

3235
const getProperties = (props: CloudFormationCustomResourceEvent['ResourceProperties']): BlueGreenServiceProps => ({
3336
cluster: props.Cluster,
3437
serviceName: props.ServiceName,
38+
containerName: props.ContainerName,
3539
taskDefinition: props.TaskDefinition,
3640
launchType: props.LaunchType,
3741
platformVersion: props.PlatformVersion,
@@ -41,12 +45,15 @@ const getProperties = (props: CloudFormationCustomResourceEvent['ResourcePropert
4145
targetGroupArn: props.TargetGroupArn,
4246
containerPort: props.ContainerPort,
4347
schedulingStrategy: props.SchedulingStrategy,
48+
healthCheckGracePeriodSeconds: props.HealthCheckGracePeriodSeconds,
49+
deploymentConfiguration: JSON.parse(props.DeploymentConfiguration),
4450
});
4551

4652
const onCreate = async (event: CloudFormationCustomResourceCreateEvent): Promise<HandlerReturn> => {
4753
const {
4854
cluster,
4955
serviceName,
56+
containerName,
5057
taskDefinition,
5158
launchType,
5259
platformVersion,
@@ -56,6 +63,8 @@ const onCreate = async (event: CloudFormationCustomResourceCreateEvent): Promise
5663
targetGroupArn,
5764
containerPort,
5865
schedulingStrategy,
66+
healthCheckGracePeriodSeconds,
67+
deploymentConfiguration,
5968
} = getProperties(event.ResourceProperties);
6069

6170
const { service } = await ecs
@@ -76,11 +85,13 @@ const onCreate = async (event: CloudFormationCustomResourceCreateEvent): Promise
7685
securityGroups,
7786
},
7887
},
88+
deploymentConfiguration,
89+
healthCheckGracePeriodSeconds,
7990
loadBalancers: [
8091
{
8192
targetGroupArn: targetGroupArn,
8293
containerPort,
83-
containerName: 'sample-website',
94+
containerName,
8495
},
8596
],
8697
})
@@ -105,13 +116,15 @@ const onCreate = async (event: CloudFormationCustomResourceCreateEvent): Promise
105116
* For more information, see CreateDeployment in the AWS CodeDeploy API Reference.
106117
*/
107118
const onUpdate = async (event: CloudFormationCustomResourceUpdateEvent): Promise<HandlerReturn> => {
108-
const { cluster, serviceName, desiredCount } = getProperties(event.ResourceProperties);
119+
const { cluster, serviceName, desiredCount, deploymentConfiguration, healthCheckGracePeriodSeconds } = getProperties(event.ResourceProperties);
109120

110121
const { service } = await ecs
111122
.updateService({
112123
service: serviceName,
113124
cluster,
114125
desiredCount,
126+
deploymentConfiguration,
127+
healthCheckGracePeriodSeconds,
115128
})
116129
.promise();
117130

0 commit comments

Comments
 (0)