1- import { ApplicationLoadBalancedCodeDeployedFargateService } from '@cdklabs/cdk-ecs-codedeploy' ;
2- import { CfnOutput , Duration , RemovalPolicy , Stack , StackProps } from 'aws-cdk-lib' ;
3- import { EcsDeploymentConfig , IEcsDeploymentConfig } from 'aws-cdk-lib/aws-codedeploy' ;
1+ import {
2+ CfnOutput ,
3+ Duration ,
4+ RemovalPolicy ,
5+ Stack ,
6+ StackProps ,
7+ } from 'aws-cdk-lib' ;
8+ import {
9+ IEcsDeploymentConfig ,
10+ EcsDeploymentConfig ,
11+ } from 'aws-cdk-lib/aws-codedeploy' ;
412import * as ec2 from 'aws-cdk-lib/aws-ec2' ;
5- import { FlowLog , FlowLogResourceType , Port } from 'aws-cdk-lib/aws-ec2' ;
6- import * as ecs from 'aws-cdk-lib/aws-ecs' ;
13+ import { FlowLog , FlowLogResourceType } from 'aws-cdk-lib/aws-ec2' ;
714import { AssetImage , AwsLogDriver , Secret } from 'aws-cdk-lib/aws-ecs' ;
815import { PolicyStatement } from 'aws-cdk-lib/aws-iam' ;
916import { LogGroup , RetentionDays } from 'aws-cdk-lib/aws-logs' ;
10- import { Credentials , DatabaseClusterEngine , DatabaseSecret , ServerlessCluster } from 'aws-cdk-lib/aws-rds' ;
17+ import {
18+ AuroraMysqlEngineVersion ,
19+ ClusterInstance ,
20+ Credentials ,
21+ DatabaseCluster ,
22+ DatabaseClusterEngine ,
23+ DatabaseSecret ,
24+ } from 'aws-cdk-lib/aws-rds' ;
1125import { Construct } from 'constructs' ;
26+ import { ApplicationLoadBalancedCodeDeployedFargateService } from '@cdklabs/cdk-ecs-codedeploy' ;
27+ import * as ecs from 'aws-cdk-lib/aws-ecs' ;
1228
1329export interface DeploymentProps extends StackProps {
1430 deploymentConfigName ?: string ;
@@ -24,25 +40,35 @@ export class DeploymentStack extends Stack {
2440
2541 const image = new AssetImage ( '.' , { target : 'build' } ) ;
2642
27- const appName = Stack . of ( this ) . stackName . toLowerCase ( ) . replace ( `-${ Stack . of ( this ) . region } -` , '-' ) ;
43+ const appName = Stack . of ( this )
44+ . stackName . toLowerCase ( )
45+ . replace ( `-${ Stack . of ( this ) . region } -` , '-' ) ;
2846 const vpc = new ec2 . Vpc ( this , 'Vpc' , {
2947 maxAzs : 3 ,
3048 natGateways : props ?. natGateways ,
3149 } ) ;
32- new FlowLog ( this , 'VpcFlowLog' , { resourceType : FlowLogResourceType . fromVpc ( vpc ) } ) ;
50+ new FlowLog ( this , 'VpcFlowLog' , {
51+ resourceType : FlowLogResourceType . fromVpc ( vpc ) ,
52+ } ) ;
3353
3454 const dbName = 'fruits' ;
3555 const dbSecret = new DatabaseSecret ( this , 'AuroraSecret' , {
3656 username : 'fruitapi' ,
3757 secretName : `${ appName } -DB` ,
3858 } ) ;
39- const db = new ServerlessCluster ( this , 'AuroraCluster' , {
40- engine : DatabaseClusterEngine . AURORA_MYSQL ,
41- vpc,
59+
60+ const db = new DatabaseCluster ( this , 'Database' , {
61+ engine : DatabaseClusterEngine . auroraMysql ( {
62+ version : AuroraMysqlEngineVersion . VER_3_07_1 ,
63+ } ) ,
4264 credentials : Credentials . fromSecret ( dbSecret ) ,
65+ writer : ClusterInstance . serverlessV2 ( 'writer' ) ,
4366 defaultDatabaseName : dbName ,
44- deletionProtection : false ,
67+ serverlessV2MaxCapacity : 2 ,
68+ serverlessV2MinCapacity : 0.5 ,
69+ vpc,
4570 clusterIdentifier : appName ,
71+ storageEncrypted : true ,
4672 } ) ;
4773
4874 const cluster = new ecs . Cluster ( this , 'Cluster' , {
@@ -57,64 +83,86 @@ export class DeploymentStack extends Stack {
5783 } ) ;
5884 let deploymentConfig : IEcsDeploymentConfig | undefined = undefined ;
5985 if ( props ?. deploymentConfigName ) {
60- deploymentConfig = EcsDeploymentConfig . fromEcsDeploymentConfigName ( this , 'DeploymentConfig' , props . deploymentConfigName ) ;
86+ deploymentConfig = EcsDeploymentConfig . fromEcsDeploymentConfigName (
87+ this ,
88+ 'DeploymentConfig' ,
89+ props . deploymentConfigName ,
90+ ) ;
6191 }
62- const appConfigEnabled = props ?. appConfigRoleArn !== undefined && props . appConfigRoleArn . length > 0 ;
63- const service = new ApplicationLoadBalancedCodeDeployedFargateService ( this , 'Api' , {
64- cluster,
65- capacityProviderStrategies : [
66- {
67- capacityProvider : 'FARGATE_SPOT' ,
68- weight : 1 ,
92+ const appConfigEnabled =
93+ props ?. appConfigRoleArn !== undefined &&
94+ props . appConfigRoleArn . length > 0 ;
95+ const service = new ApplicationLoadBalancedCodeDeployedFargateService (
96+ this ,
97+ 'Api' ,
98+ {
99+ cluster,
100+ capacityProviderStrategies : [
101+ {
102+ capacityProvider : 'FARGATE_SPOT' ,
103+ weight : 1 ,
104+ } ,
105+ ] ,
106+ minHealthyPercent : 50 ,
107+ maxHealthyPercent : 200 ,
108+ desiredCount : 3 ,
109+ cpu : 512 ,
110+ memoryLimitMiB : 1024 ,
111+ taskImageOptions : {
112+ image,
113+ containerName : 'api' ,
114+ containerPort : 8080 ,
115+ family : appName ,
116+ logDriver : AwsLogDriver . awsLogs ( {
117+ logGroup : appLogGroup ,
118+ streamPrefix : 'service' ,
119+ } ) ,
120+ secrets : {
121+ SPRING_DATASOURCE_USERNAME : Secret . fromSecretsManager (
122+ dbSecret ,
123+ 'username' ,
124+ ) ,
125+ SPRING_DATASOURCE_PASSWORD : Secret . fromSecretsManager (
126+ dbSecret ,
127+ 'password' ,
128+ ) ,
129+ } ,
130+ environment : {
131+ SPRING_DATASOURCE_URL : `jdbc:mysql://${ db . clusterEndpoint . hostname } :${ db . clusterEndpoint . port } /${ dbName } ` ,
132+ APPCONFIG_AGENT_APPLICATION :
133+ this . node . tryGetContext ( 'workloadName' ) ,
134+ APPCONFIG_AGENT_ENVIRONMENT :
135+ this . node . tryGetContext ( 'environmentName' ) ,
136+ APPCONFIG_AGENT_ENABLED : appConfigEnabled . toString ( ) ,
137+ } ,
69138 } ,
70- ] ,
71- minHealthyPercent : 50 ,
72- maxHealthyPercent : 200 ,
73- desiredCount : 3 ,
74- cpu : 512 ,
75- memoryLimitMiB : 1024 ,
76- taskImageOptions : {
77- image,
78- containerName : 'api' ,
79- containerPort : 8080 ,
80- family : appName ,
81- logDriver : AwsLogDriver . awsLogs ( {
82- logGroup : appLogGroup ,
83- streamPrefix : 'service' ,
84- } ) ,
85- secrets : {
86- SPRING_DATASOURCE_USERNAME : Secret . fromSecretsManager ( dbSecret , 'username' ) ,
87- SPRING_DATASOURCE_PASSWORD : Secret . fromSecretsManager ( dbSecret , 'password' ) ,
88- } ,
89- environment : {
90- SPRING_DATASOURCE_URL : `jdbc:mysql://${ db . clusterEndpoint . hostname } :${ db . clusterEndpoint . port } /${ dbName } ` ,
91- APPCONFIG_AGENT_APPLICATION : this . node . tryGetContext ( 'workloadName' ) ,
92- APPCONFIG_AGENT_ENVIRONMENT : this . node . tryGetContext ( 'environmentName' ) ,
93- APPCONFIG_AGENT_ENABLED : appConfigEnabled . toString ( ) ,
139+ deregistrationDelay : Duration . seconds ( 5 ) ,
140+ responseTimeAlarmThreshold : Duration . seconds ( 3 ) ,
141+ targetHealthCheck : {
142+ healthyThresholdCount : 2 ,
143+ unhealthyThresholdCount : 2 ,
144+ interval : Duration . seconds ( 60 ) ,
145+ path : '/actuator/health' ,
94146 } ,
147+ deploymentConfig,
148+ terminationWaitTime : Duration . minutes ( 5 ) ,
149+ apiCanaryTimeout : Duration . seconds ( 5 ) ,
150+ apiTestSteps : [
151+ {
152+ name : 'getAll' ,
153+ path : '/api/fruits' ,
154+ jmesPath : 'length(@)' ,
155+ expectedValue : 5 ,
156+ } ,
157+ ] ,
95158 } ,
96- deregistrationDelay : Duration . seconds ( 5 ) ,
97- responseTimeAlarmThreshold : Duration . seconds ( 3 ) ,
98- targetHealthCheck : {
99- healthyThresholdCount : 2 ,
100- unhealthyThresholdCount : 2 ,
101- interval : Duration . seconds ( 60 ) ,
102- path : '/actuator/health' ,
103- } ,
104- deploymentConfig,
105- terminationWaitTime : Duration . minutes ( 5 ) ,
106- apiCanaryTimeout : Duration . seconds ( 5 ) ,
107- apiTestSteps : [ {
108- name : 'getAll' ,
109- path : '/api/fruits' ,
110- jmesPath : 'length(@)' ,
111- expectedValue : 5 ,
112- } ] ,
113- } ) ;
159+ ) ;
114160
115161 if ( appConfigEnabled ) {
116162 service . taskDefinition . addContainer ( 'appconfig-agent' , {
117- image : ecs . ContainerImage . fromRegistry ( 'public.ecr.aws/aws-appconfig/aws-appconfig-agent:2.x' ) ,
163+ image : ecs . ContainerImage . fromRegistry (
164+ 'public.ecr.aws/aws-appconfig/aws-appconfig-agent:2.x' ,
165+ ) ,
118166 essential : false ,
119167 logging : AwsLogDriver . awsLogs ( {
120168 logGroup : appLogGroup ,
@@ -129,13 +177,18 @@ export class DeploymentStack extends Stack {
129177 portMappings : [ { containerPort : 2772 } ] ,
130178 } ) ;
131179
132- service . taskDefinition . addToTaskRolePolicy ( new PolicyStatement ( {
133- actions : [ 'sts:AssumeRole' ] ,
134- resources : [ props ! . appConfigRoleArn ! ] ,
135- } ) ) ;
180+ service . taskDefinition . addToTaskRolePolicy (
181+ new PolicyStatement ( {
182+ actions : [ 'sts:AssumeRole' ] ,
183+ resources : [ props ! . appConfigRoleArn ! ] ,
184+ } ) ,
185+ ) ;
136186 }
137187
138- service . service . connections . allowTo ( db , Port . tcp ( db . clusterEndpoint . port ) ) ;
188+ service . service . connections . allowTo (
189+ db ,
190+ ec2 . Port . tcp ( db . clusterEndpoint . port ) ,
191+ ) ;
139192
140193 this . apiUrl = new CfnOutput ( this , 'endpointUrl' , {
141194 value : `http://${ service . listener . loadBalancer . loadBalancerDnsName } ` ,
0 commit comments