11import * as cloudwatch from '@aws-cdk/aws-cloudwatch' ;
22import * as ecs from '@aws-cdk/aws-ecs' ;
33import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2' ;
4- import { ApplicationTargetGroup , CfnTargetGroup , NetworkTargetGroup } from '@aws-cdk/aws-elasticloadbalancingv2' ;
54import * as iam from '@aws-cdk/aws-iam' ;
65import * as cdk from '@aws-cdk/core' ;
76import { Construct } from 'constructs' ;
@@ -45,47 +44,6 @@ export interface IEcsDeploymentGroup extends cdk.IResource {
4544 readonly deploymentConfig : IEcsDeploymentConfig ;
4645}
4746
48- /**
49- * Details about an ECS service and its corresponding ECS cluster
50- */
51- export type EcsService = ecs . Ec2Service | ecs . FargateService | ecs . ExternalService ;
52-
53- /**
54- * A route with an ELB listener and target group.
55- */
56- export interface EcsTrafficRoute {
57- /**
58- * The load balancer for the traffic route.
59- *
60- * @default - blank if empty on test traffic route. Required for prod traffic route.
61- */
62- readonly listener : elbv2 . IApplicationListener | elbv2 . INetworkListener | undefined ;
63- /**
64- * The target group for the traffic route.
65- */
66- readonly targetGroup : elbv2 . ITargetGroup ;
67- }
68-
69- /**
70- * Configuration for the blue/green CodeDeploy deployment.
71- */
72- export interface EcsBlueGreenDeploymentConfig {
73- /**
74- * The time to wait for a ContinueDeployment after the deployment is ready.
75- * Leave blank to automatically continue once the deployment is ready.
76- *
77- * @default - automatically continue once deployment is ready
78- */
79- readonly waitTimeForContinueDeployment ?: cdk . Duration ;
80- /**
81- * The time to wait before terminating old tasks.
82- * Leave blank to keep the old tasks alive and deregistered from the load balancer.
83- *
84- * @default - keep the old tasks alive and deregistered from the load balancer.
85- */
86- readonly waitTimeForTermination ?: cdk . Duration ;
87- }
88-
8947/**
9048 * Construction properties for {@link EcsDeploymentGroup}.
9149 */
@@ -95,22 +53,7 @@ export interface EcsDeploymentGroupProps {
9553 *
9654 * [disable-awslint:ref-via-interface] because the service needs to have the deploy controller changed to Code Deploy
9755 */
98- readonly services : EcsService [ ] ;
99-
100- /**
101- * The reference to the production traffic group for the deployment.
102- * Leave blank to disable traffic shifting
103- *
104- * @default - Traffic shifting will be disabled
105- */
106- readonly prodTrafficRoute ?: EcsTrafficRoute ;
107-
108- /**
109- * The reference to the test traffic group for the deployment.
110- *
111- * @default - One will be created for you
112- */
113- readonly testTrafficRoute ?: EcsTrafficRoute ;
56+ readonly services : ecs . BaseService [ ] ;
11457
11558 /**
11659 * The reference to the CodeDeploy ECS Application
@@ -171,11 +114,8 @@ export interface EcsDeploymentGroupProps {
171114
172115 /**
173116 * The blue/green deployment configuration
174- *
175- * @default - default BlueGreenDeploymentConfiguration which is configured to
176- * continue deployment when ready and terminate old instances immediately.
177117 */
178- readonly blueGreenDeploymentConfiguration ? : EcsBlueGreenDeploymentConfig ;
118+ readonly blueGreenDeploymentConfiguration : EcsBlueGreenDeploymentConfig ;
179119}
180120
181121/**
@@ -220,7 +160,7 @@ export class EcsDeploymentGroup extends cdk.Resource implements IEcsDeploymentGr
220160 this . role = props . role || new iam . Role ( this , 'ServiceRole' , {
221161 assumedBy : new iam . ServicePrincipal ( 'codedeploy.amazonaws.com' ) ,
222162 } ) ;
223- this . role . addManagedPolicy ( iam . ManagedPolicy . fromAwsManagedPolicyName ( 'AWSCodeDeployRoleForECS ' ) ) ;
163+ this . role . addManagedPolicy ( iam . ManagedPolicy . fromAwsManagedPolicyName ( 'AWSCodeDeployRoleForECSLimited ' ) ) ;
224164 this . deploymentConfig = props . deploymentConfig || EcsDeploymentConfig . ALL_AT_ONCE ;
225165
226166 // Change ECS Service deployment controller to codedeploy
@@ -233,69 +173,26 @@ export class EcsDeploymentGroup extends cdk.Resource implements IEcsDeploymentGr
233173 service . node . addDependency ( service . taskDefinition ) ;
234174 }
235175
236- // create a testTrafficRoute if missing
237- let testTrafficRoute = props . testTrafficRoute ;
238- if ( props . prodTrafficRoute && ! testTrafficRoute ) {
239- const prodCfnTargetGroup = props . prodTrafficRoute . targetGroup . node . defaultChild as CfnTargetGroup ;
240- const testCfnTargetGroup = new CfnTargetGroup ( this , 'TestTargetGroup' , {
241- healthCheckEnabled : prodCfnTargetGroup . healthCheckEnabled ,
242- healthCheckIntervalSeconds : prodCfnTargetGroup . healthCheckIntervalSeconds ,
243- healthCheckPath : prodCfnTargetGroup . healthCheckPath ,
244- healthCheckPort : prodCfnTargetGroup . healthCheckPort ,
245- healthCheckProtocol : prodCfnTargetGroup . healthCheckProtocol ,
246- healthCheckTimeoutSeconds : prodCfnTargetGroup . healthCheckTimeoutSeconds ,
247- healthyThresholdCount : prodCfnTargetGroup . healthyThresholdCount ,
248- ipAddressType : prodCfnTargetGroup . ipAddressType ,
249- matcher : prodCfnTargetGroup . matcher ,
250- name : prodCfnTargetGroup . name ,
251- port : prodCfnTargetGroup . port ,
252- protocol : prodCfnTargetGroup . protocol ,
253- protocolVersion : prodCfnTargetGroup . protocolVersion ,
254- targetGroupAttributes : prodCfnTargetGroup . targetGroupAttributes ,
255- targets : prodCfnTargetGroup . targets ,
256- targetType : prodCfnTargetGroup . targetType ,
257- unhealthyThresholdCount : prodCfnTargetGroup . unhealthyThresholdCount ,
258- vpcId : prodCfnTargetGroup . vpcId ,
259- } ) ;
260- if ( props . prodTrafficRoute . targetGroup instanceof ApplicationTargetGroup ) {
261- testTrafficRoute = {
262- targetGroup : ApplicationTargetGroup . fromTargetGroupAttributes ( this , 'TestTargetGroupRef' , {
263- targetGroupArn : testCfnTargetGroup . ref ,
264- } ) ,
265- listener : undefined ,
266- } ;
267- } else if ( props . prodTrafficRoute . targetGroup instanceof NetworkTargetGroup ) {
268- testTrafficRoute = {
269- targetGroup : NetworkTargetGroup . fromTargetGroupAttributes ( this , 'TestTargetGroupRef' , {
270- targetGroupArn : testCfnTargetGroup . ref ,
271- } ) ,
272- listener : undefined ,
273- } ;
274- }
275- }
276-
277176 const resource = new CfnDeploymentGroup ( this , 'Resource' , {
278177 applicationName : this . application . applicationName ,
279178 serviceRoleArn : this . role . roleArn ,
280179 deploymentGroupName : this . physicalName ,
281180 deploymentConfigName : this . deploymentConfig . deploymentConfigName ,
282- deploymentStyle : ( props . prodTrafficRoute && testTrafficRoute ) ? {
181+ deploymentStyle : {
283182 deploymentType : 'BLUE_GREEN' ,
284183 deploymentOption : 'WITH_TRAFFIC_CONTROL' ,
285- } : {
286- deploymentType : 'IN_PLACE' ,
287- deploymentOption : 'WITHOUT_TRAFFIC_CONTROL' ,
288184 } ,
289185 ecsServices : props . services . map ( s => {
290186 return {
291187 clusterName : s . cluster . clusterName ,
292188 serviceName : s . serviceName ,
293189 } ;
294190 } ) ,
295- loadBalancerInfo : ( props . prodTrafficRoute && testTrafficRoute ) ?
296- renderLoadBalancerInfo ( props . prodTrafficRoute , testTrafficRoute ) : undefined ,
191+ loadBalancerInfo : cdk . Lazy . any ( {
192+ produce : ( ) => renderLoadBalancerInfo ( props . blueGreenDeploymentConfiguration ) ,
193+ } ) ,
297194 blueGreenDeploymentConfiguration : cdk . Lazy . any ( {
298- produce : ( ) => renderBlueGreenDeploymentConfiguration ( props . blueGreenDeploymentConfiguration ) ,
195+ produce : ( ) => renderBlueGreenDeploymentConfiguration ( props . blueGreenDeploymentConfiguration ) ,
299196 } ) ,
300197 alarmConfiguration : cdk . Lazy . any ( { produce : ( ) => renderAlarmConfiguration ( this . alarms , props . ignorePollAlarmsFailure ) } ) ,
301198 autoRollbackConfiguration : cdk . Lazy . any ( { produce : ( ) => renderAutoRollbackConfiguration ( this . alarms , props . autoRollback ) } ) ,
@@ -370,43 +267,50 @@ class ImportedEcsDeploymentGroup extends cdk.Resource implements IEcsDeploymentG
370267}
371268
372269/**
373- * { @link Duration } of infinite days
270+ * Configuraiton for blue green deployments.
374271 */
375- //export const DurationInfinity = cdk.Duration.days(Number.POSITIVE_INFINITY);
272+ export interface EcsBlueGreenDeploymentConfig {
273+ /**
274+ * The reference to the production listener for the deployment.
275+ */
276+ readonly prodListener : elbv2 . IApplicationListener | elbv2 . INetworkListener ;
277+
278+ /**
279+ * The reference to the test listener for the deployment.
280+ *
281+ * @default - No test listener will be used
282+ */
283+ readonly testListener ?: elbv2 . IApplicationListener | elbv2 . INetworkListener ;
376284
377- export class EcsBlueGreenDeploymentConfig {
378- static DurationInfinity = cdk . Duration . days ( Number . POSITIVE_INFINITY ) ;
285+ /**
286+ * The target group for the blue task set.
287+ */
288+ readonly blueTargetGroup : elbv2 . ITargetGroup ;
289+
290+ /**
291+ * The target group for the green task set.
292+ */
293+ readonly greenTargetGroup : elbv2 . ITargetGroup ;
379294
380295 /**
381296 * The time to wait for a ContinueDeployment after the deployment is ready.
382297 *
383- * @default - undefined - automatically continue once the deployment is ready.
298+ * @default 0 - automatically continue once the deployment is ready.
384299 */
385300 readonly waitTimeForContinueDeployment ?: cdk . Duration ;
301+
386302 /**
387303 * The time to wait before terminating old tasks.
388- * Set to {@link DurationInfinity} to keep the old tasks alive and deregistered from the load balancer.
389304 *
390- * @default - undefined - terminate tasks immediately.
305+ * @default 0 - terminate immediately
391306 */
392307 readonly waitTimeForTermination ?: cdk . Duration ;
393308}
394309
395310function renderBlueGreenDeploymentConfiguration (
396- blueGreenDeploymentConfig ? : EcsBlueGreenDeploymentConfig ,
311+ blueGreenDeploymentConfig : EcsBlueGreenDeploymentConfig ,
397312) : CfnDeploymentGroup . BlueGreenDeploymentConfigurationProperty {
398313 let deploymentReadyOption : CfnDeploymentGroup . DeploymentReadyOptionProperty ;
399- if ( ! blueGreenDeploymentConfig ) {
400- return {
401- deploymentReadyOption : {
402- actionOnTimeout : 'CONTINUE_DEPLOYMENT' ,
403- } ,
404- terminateBlueInstancesOnDeploymentSuccess : {
405- action : 'TERMINATE' ,
406- terminationWaitTimeInMinutes : 0 ,
407- } ,
408- } ;
409- }
410314 if ( blueGreenDeploymentConfig . waitTimeForContinueDeployment ) {
411315 deploymentReadyOption = {
412316 actionOnTimeout : 'STOP_DEPLOYMENT' ,
@@ -417,38 +321,31 @@ function renderBlueGreenDeploymentConfiguration(
417321 actionOnTimeout : 'CONTINUE_DEPLOYMENT' ,
418322 } ;
419323 }
420- let terminateBlueInstancesOnDeploymentSuccess : CfnDeploymentGroup . BlueInstanceTerminationOptionProperty ;
421- if ( ! blueGreenDeploymentConfig . waitTimeForTermination
422- || blueGreenDeploymentConfig . waitTimeForTermination === EcsBlueGreenDeploymentConfig . DurationInfinity ) {
423- terminateBlueInstancesOnDeploymentSuccess = {
424- action : 'KEEP_ALIVE' ,
425- } ;
426- } else {
427- terminateBlueInstancesOnDeploymentSuccess = {
428- action : 'TERMINATE' ,
429- terminationWaitTimeInMinutes : blueGreenDeploymentConfig . waitTimeForTermination . toMinutes ( ) ,
430- } ;
431- }
324+ let terminateBlueInstancesOnDeploymentSuccess = {
325+ action : 'TERMINATE' ,
326+ terminationWaitTimeInMinutes : blueGreenDeploymentConfig . waitTimeForTermination ?
327+ blueGreenDeploymentConfig . waitTimeForTermination . toMinutes ( ) : 0 ,
328+ } ;
432329 return {
433330 deploymentReadyOption,
434331 terminateBlueInstancesOnDeploymentSuccess,
435332 } ;
436333}
334+
437335function renderLoadBalancerInfo (
438- prodTrafficRoute : EcsTrafficRoute ,
439- testTrafficRoute : EcsTrafficRoute ,
336+ blueGreenDeploymentConfig : EcsBlueGreenDeploymentConfig ,
440337) : CfnDeploymentGroup . LoadBalancerInfoProperty {
441338 const targetGroupPairInfo : CfnDeploymentGroup . TargetGroupPairInfoProperty = {
442339 targetGroups : [ {
443- name : prodTrafficRoute . targetGroup . targetGroupName ,
340+ name : blueGreenDeploymentConfig . blueTargetGroup . targetGroupName ,
444341 } , {
445- name : testTrafficRoute . targetGroup . targetGroupName ,
342+ name : blueGreenDeploymentConfig . greenTargetGroup . targetGroupName ,
446343 } ] ,
447344 prodTrafficRoute : {
448- listenerArns : [ prodTrafficRoute . listener ! . listenerArn ] ,
345+ listenerArns : [ blueGreenDeploymentConfig . prodListener . listenerArn ] ,
449346 } ,
450- testTrafficRoute : testTrafficRoute . listener ? {
451- listenerArns : [ testTrafficRoute . listener . listenerArn ] ,
347+ testTrafficRoute : blueGreenDeploymentConfig . testListener ? {
348+ listenerArns : [ blueGreenDeploymentConfig . testListener . listenerArn ] ,
452349 } : undefined ,
453350 } ;
454351 return {
0 commit comments