konokenj.cdk-api-mcp-server 0.39.0__py3-none-any.whl → 0.41.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. cdk_api_mcp_server/__about__.py +1 -1
  2. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/custom-resource-handlers/README.md +78 -15
  3. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/README.md/README.md +364 -16
  4. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/README.md +144 -0
  5. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api-dualstack.ts +4 -3
  6. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api.ts +4 -2
  7. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.stage.ts +20 -7
  8. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.usage-plan.ts +80 -0
  9. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-authorizers/integ.iam.ts +38 -34
  10. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.sqs.ts +71 -58
  11. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-autoscaling/README.md +1 -1
  12. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codedeploy/integ.deployment-config.ts +15 -4
  13. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codedeploy/integ.deployment-group.ts +40 -218
  14. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/README.md +21 -68
  15. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.availability-zone-rebalancing.ts +4 -14
  16. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.blue-green-deployment-strategy.ts +13 -71
  17. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.enable-execute-command.ts +29 -35
  18. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.exec-command.ts +22 -16
  19. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.lb-awsvpc-nw.ts +16 -26
  20. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.pseudo-terminal.ts +8 -18
  21. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/README.md +2 -2
  22. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53/integ.delete-existing-record-set.ts +0 -1
  23. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-stack-ssm-source.ts +91 -0
  24. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-notifications/integ.bucket-notifications.ts +80 -42
  25. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-signer/integ.signing-profile.ts +5 -0
  26. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/README.md +9 -3
  27. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.invoke-jsonata.ts +80 -87
  28. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.invoke.ts +69 -87
  29. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.start-job-run.ts +104 -102
  30. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/core/README.md +2 -1893
  31. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +25 -0
  32. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/README.md +24 -1
  33. {konokenj_cdk_api_mcp_server-0.39.0.dist-info → konokenj_cdk_api_mcp_server-0.41.0.dist-info}/METADATA +2 -2
  34. {konokenj_cdk_api_mcp_server-0.39.0.dist-info → konokenj_cdk_api_mcp_server-0.41.0.dist-info}/RECORD +37 -35
  35. {konokenj_cdk_api_mcp_server-0.39.0.dist-info → konokenj_cdk_api_mcp_server-0.41.0.dist-info}/WHEEL +0 -0
  36. {konokenj_cdk_api_mcp_server-0.39.0.dist-info → konokenj_cdk_api_mcp_server-0.41.0.dist-info}/entry_points.txt +0 -0
  37. {konokenj_cdk_api_mcp_server-0.39.0.dist-info → konokenj_cdk_api_mcp_server-0.41.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,240 +1,62 @@
1
+ import * as path from 'path';
1
2
  import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
2
- import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
- import * as ecs from 'aws-cdk-lib/aws-ecs';
4
- import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
3
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
5
4
  import * as cdk from 'aws-cdk-lib';
6
- import * as integ from '@aws-cdk/integ-tests-alpha';
7
5
  import * as codedeploy from 'aws-cdk-lib/aws-codedeploy';
6
+ import { STANDARD_NODEJS_RUNTIME } from '../../../config';
8
7
 
9
- /**
10
- * Follow these instructions to manually test running a CodeDeploy deployment with the resources provisioned in this stack:
11
- *
12
- * 1. Deploy the stack:
13
- ```
14
- $ cdk deploy --app 'node integ.deployment-group.js' aws-cdk-codedeploy-ecs-dg
15
- ```
16
- *
17
- * 2. Create a file called `appspec.json` with the following contents, replacing the placeholders with output values from the deployed stack:
18
- ```
19
- {
20
- "version": 0.0,
21
- "Resources": [
22
- {
23
- "TargetService": {
24
- "Type": "AWS::ECS::Service",
25
- "Properties": {
26
- "TaskDefinition": "<PLACEHOLDER - NEW TASK DEFINITION>",
27
- "LoadBalancerInfo": {
28
- "ContainerName": "Container",
29
- "ContainerPort": 80
30
- },
31
- "PlatformVersion": "LATEST",
32
- "NetworkConfiguration": {
33
- "awsvpcConfiguration": {
34
- "subnets": [
35
- "<PLACEHOLDER - SUBNET 1 ID>",
36
- "<PLACEHOLDER - SUBNET 2 ID>",
37
- ],
38
- "securityGroups": [
39
- "<PLACEHOLDER - SECURITY GROUP ID>"
40
- ],
41
- "assignPublicIp": "DISABLED"
42
- }
43
- }
44
- }
45
- }
46
- }
47
- ]
48
- }
49
- ```
50
- *
51
- * 3. Start the deployment:
52
- ```
53
- $ appspec=$(jq -R -s '.' < appspec.json | sed 's/\\n//g')
54
- $ aws deploy create-deployment \
55
- --application-name <PLACEHOLDER - CODEDEPLOY APPLICATION NAME> \
56
- --deployment-group-name <PLACEHOLDER - CODEDEPLOY DEPLOYMENT GROUP NAME> \
57
- --description "AWS CDK integ test" \
58
- --revision revisionType=AppSpecContent,appSpecContent={content="$appspec"}
59
- ```
60
- *
61
- * 4. Wait for the deployment to complete successfully, providing the deployment ID from the previous step:
62
- ```
63
- $ aws deploy wait deployment-successful --deployment-id <PLACEHOLDER - DEPLOYMENT ID>
64
- ```
65
- *
66
- * 5. Destroy the stack:
67
- ```
68
- $ cdk destroy --app 'node integ.deployment-group.js' aws-cdk-codedeploy-ecs-dg
69
- ```
70
- */
71
-
72
- const app = new cdk.App();
73
- const stack = new cdk.Stack(app, 'aws-cdk-codedeploy-ecs-dg');
74
-
75
- // Network infrastructure
76
- const vpc = new ec2.Vpc(stack, 'VPC', { maxAzs: 2, restrictDefaultSecurityGroup: false });
77
-
78
- // ECS service
79
- const cluster = new ecs.Cluster(stack, 'EcsCluster', {
80
- vpc,
81
- });
82
- const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef');
83
- taskDefinition.addContainer('Container', {
84
- image: ecs.ContainerImage.fromRegistry('public.ecr.aws/ecs-sample-image/amazon-ecs-sample:latest'),
85
- portMappings: [{ containerPort: 80 }],
86
- });
87
- const service = new ecs.FargateService(stack, 'FargateService', {
88
- cluster,
89
- taskDefinition,
90
- deploymentController: {
91
- type: ecs.DeploymentControllerType.CODE_DEPLOY,
8
+ const app = new cdk.App({
9
+ postCliContext: {
10
+ '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
92
11
  },
93
12
  });
13
+ const stack = new cdk.Stack(app, 'aws-cdk-codedeploy-lambda');
94
14
 
95
- // A second task definition for testing a CodeDeploy deployment of the ECS service to a new task definition
96
- const taskDefinition2 = new ecs.FargateTaskDefinition(stack, 'TaskDef2');
97
- taskDefinition2.addContainer('Container', {
98
- image: ecs.ContainerImage.fromRegistry('public.ecr.aws/ecs-sample-image/amazon-ecs-sample:latest'),
99
- portMappings: [{ containerPort: 80 }],
15
+ const handler = new lambda.Function(stack, 'Handler', {
16
+ code: lambda.Code.fromAsset(path.join(__dirname, 'handler')),
17
+ handler: 'index.handler',
18
+ runtime: STANDARD_NODEJS_RUNTIME,
100
19
  });
101
- service.node.addDependency(taskDefinition2);
102
-
103
- // Load balancer
104
- const loadBalancer = new elbv2.ApplicationLoadBalancer(stack, 'ServiceLB', {
105
- vpc,
106
- internetFacing: false,
20
+ const version = handler.currentVersion;
21
+ const blueGreenAlias = new lambda.Alias(stack, 'Alias', {
22
+ aliasName: 'alias',
23
+ version,
107
24
  });
108
25
 
109
- // Listeners
110
- const prodListener = loadBalancer.addListener('ProdListener', {
111
- port: 80, // port for production traffic
112
- protocol: elbv2.ApplicationProtocol.HTTP,
26
+ const preHook = new lambda.Function(stack, 'PreHook', {
27
+ code: lambda.Code.fromAsset(path.join(__dirname, 'preHook')),
28
+ handler: 'index.handler',
29
+ runtime: STANDARD_NODEJS_RUNTIME,
113
30
  });
114
- const testListener = loadBalancer.addListener('TestListener', {
115
- port: 9002, // port for testing
116
- protocol: elbv2.ApplicationProtocol.HTTP,
31
+ const postHook = new lambda.Function(stack, 'PostHook', {
32
+ code: lambda.Code.fromAsset(path.join(__dirname, 'postHook')),
33
+ handler: 'index.handler',
34
+ runtime: STANDARD_NODEJS_RUNTIME,
117
35
  });
118
36
 
119
- // Target groups
120
- const blueTG = prodListener.addTargets('BlueTG', {
121
- port: 80,
122
- protocol: elbv2.ApplicationProtocol.HTTP,
123
- targets: [
124
- service.loadBalancerTarget({
125
- containerName: 'Container',
126
- containerPort: 80,
37
+ new codedeploy.LambdaDeploymentGroup(stack, 'BlueGreenDeployment', {
38
+ alias: blueGreenAlias,
39
+ deploymentConfig: codedeploy.LambdaDeploymentConfig.LINEAR_10PERCENT_EVERY_1MINUTE,
40
+ alarms: [
41
+ new cloudwatch.Alarm(stack, 'BlueGreenErrors', {
42
+ comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
43
+ threshold: 1,
44
+ evaluationPeriods: 1,
45
+ metric: blueGreenAlias.metricErrors(),
127
46
  }),
128
47
  ],
129
- deregistrationDelay: cdk.Duration.seconds(30),
130
- healthCheck: {
131
- interval: cdk.Duration.seconds(5),
132
- healthyHttpCodes: '200',
133
- healthyThresholdCount: 2,
134
- unhealthyThresholdCount: 3,
135
- timeout: cdk.Duration.seconds(4),
136
- },
48
+ preHook,
49
+ postHook,
137
50
  });
138
51
 
139
- const greenTG = new elbv2.ApplicationTargetGroup(stack, 'GreenTG', {
140
- vpc,
141
- port: 80,
142
- protocol: elbv2.ApplicationProtocol.HTTP,
143
- targetType: elbv2.TargetType.IP,
144
- deregistrationDelay: cdk.Duration.seconds(30),
145
- healthCheck: {
146
- interval: cdk.Duration.seconds(5),
147
- healthyHttpCodes: '200',
148
- healthyThresholdCount: 2,
149
- unhealthyThresholdCount: 3,
150
- timeout: cdk.Duration.seconds(4),
151
- },
152
- });
153
-
154
- testListener.addTargetGroups('GreenTGTest', {
155
- targetGroups: [greenTG],
52
+ const secondAlias = new lambda.Alias(stack, 'SecondAlias', {
53
+ aliasName: 'secondAlias',
54
+ version,
156
55
  });
157
56
 
158
- prodListener.node.addDependency(greenTG);
159
- testListener.node.addDependency(blueTG);
160
- service.node.addDependency(testListener);
161
- service.node.addDependency(greenTG);
162
-
163
- // Alarms: monitor 500s and unhealthy hosts on target groups
164
- const blueUnhealthyHosts = new cloudwatch.Alarm(stack, 'BlueUnhealthyHosts', {
165
- alarmName: stack.stackName + '-Unhealthy-Hosts-Blue',
166
- metric: blueTG.metricUnhealthyHostCount(),
167
- threshold: 1,
168
- evaluationPeriods: 2,
169
- });
170
-
171
- const blueApiFailure = new cloudwatch.Alarm(stack, 'Blue5xx', {
172
- alarmName: stack.stackName + '-Http-500-Blue',
173
- metric: blueTG.metricHttpCodeTarget(
174
- elbv2.HttpCodeTarget.TARGET_5XX_COUNT,
175
- { period: cdk.Duration.minutes(1) },
176
- ),
177
- threshold: 1,
178
- evaluationPeriods: 1,
179
- });
180
-
181
- const greenUnhealthyHosts = new cloudwatch.Alarm(stack, 'GreenUnhealthyHosts', {
182
- alarmName: stack.stackName + '-Unhealthy-Hosts-Green',
183
- metric: greenTG.metricUnhealthyHostCount(),
184
- threshold: 1,
185
- evaluationPeriods: 2,
186
- });
187
-
188
- const greenApiFailure = new cloudwatch.Alarm(stack, 'Green5xx', {
189
- alarmName: stack.stackName + '-Http-500-Green',
190
- metric: greenTG.metricHttpCodeTarget(
191
- elbv2.HttpCodeTarget.TARGET_5XX_COUNT,
192
- { period: cdk.Duration.minutes(1) },
193
- ),
194
- threshold: 1,
195
- evaluationPeriods: 1,
196
- });
197
-
198
- // Deployment group
199
- const deploymentConfig = new codedeploy.EcsDeploymentConfig(stack, 'CanaryConfig', {
200
- trafficRouting: codedeploy.TrafficRouting.timeBasedCanary({
201
- interval: cdk.Duration.minutes(1),
202
- percentage: 20,
203
- }),
204
- });
205
-
206
- const dg = new codedeploy.EcsDeploymentGroup(stack, 'BlueGreenDG', {
207
- alarms: [
208
- blueUnhealthyHosts,
209
- blueApiFailure,
210
- greenUnhealthyHosts,
211
- greenApiFailure,
212
- ],
213
- service,
214
- blueGreenDeploymentConfig: {
215
- blueTargetGroup: blueTG,
216
- greenTargetGroup: greenTG,
217
- listener: prodListener,
218
- testListener,
219
- terminationWaitTime: cdk.Duration.minutes(1),
220
- },
221
- deploymentConfig,
222
- autoRollback: {
223
- stoppedDeployment: true,
224
- },
225
- ignoreAlarmConfiguration: true,
226
- });
227
-
228
- // Outputs to use for manual testing
229
- new cdk.CfnOutput(stack, 'NewTaskDefinition', { value: taskDefinition2.taskDefinitionArn });
230
- new cdk.CfnOutput(stack, 'Subnet1Id', { value: vpc.privateSubnets[0].subnetId });
231
- new cdk.CfnOutput(stack, 'Subnet2Id', { value: vpc.privateSubnets[1].subnetId });
232
- new cdk.CfnOutput(stack, 'SecurityGroupId', { value: service.connections.securityGroups[0].securityGroupId });
233
- new cdk.CfnOutput(stack, 'CodeDeployApplicationName', { value: dg.application.applicationName });
234
- new cdk.CfnOutput(stack, 'CodeDeployDeploymentGroupName', { value: dg.deploymentGroupName });
235
-
236
- new integ.IntegTest(app, 'EcsDeploymentGroupTest', {
237
- testCases: [stack],
57
+ new codedeploy.LambdaDeploymentGroup(stack, 'SecondDeployment', {
58
+ alias: secondAlias,
59
+ deploymentConfig: codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_5MINUTES,
238
60
  });
239
61
 
240
62
  app.synth();
@@ -2076,84 +2076,37 @@ Amazon ECS supports native blue/green deployments that allow you to deploy new v
2076
2076
 
2077
2077
  [Amazon ECS blue/green deployments](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-blue-green.html)
2078
2078
 
2079
- ### Using Escape Hatches for Blue/Green Features
2080
-
2081
- The new blue/green deployment features are added to CloudFormation but not yet available in the CDK L2 constructs, you can use escape hatches to access them through the L1 (CfnService) construct.
2082
-
2083
- #### Load Balancer Advanced Configuration
2084
-
2085
- Configure advanced load balancer settings for blue/green deployments with alternate target groups and listener rules:
2086
-
2087
2079
  ```ts
2088
- declare const service: ecs.FargateService;
2089
-
2090
- const cfnService = service.node.defaultChild as ecs.CfnService;
2091
- cfnService.loadBalancers = [{
2092
- containerName: 'web',
2093
- containerPort: 80,
2094
- targetGroupArn: 'arn:aws:elasticloadbalancing:region:account:targetgroup/production',
2095
- advancedConfiguration: {
2096
- alternateTargetGroupArn: 'arn:aws:elasticloadbalancing:region:account:targetgroup/test',
2097
- productionListenerRule: 'arn:aws:elasticloadbalancing:region:account:listener-rule/production-rule',
2098
- testListenerRule: 'arn:aws:elasticloadbalancing:region:account:listener-rule/test-rule',
2099
- roleArn: 'arn:aws:iam::account:role/ecs-blue-green-role'
2100
- }
2101
- }];
2102
- ```
2103
-
2104
- #### Blue/Green Deployment Configuration
2105
-
2106
- Configure deployment strategy with bake time and lifecycle hooks:
2107
-
2108
- ```ts
2109
- declare const service: ecs.FargateService;
2110
-
2111
- const cfnService = service.node.defaultChild as ecs.CfnService;
2112
- cfnService.deploymentConfiguration = {
2113
- maximumPercent: 200,
2114
- minimumHealthyPercent: 100,
2115
- strategy: 'BLUE_GREEN',
2116
- bakeTimeInMinutes: 15,
2117
- lifecycleHooks: [{
2118
- hookTargetArn: 'arn:aws:lambda:region:account:function:pre-deployment-hook',
2119
- roleArn: 'arn:aws:iam::account:role/deployment-hook-role',
2120
- lifecycleStages: ['PRE_STOP', 'POST_START']
2121
- }]
2122
- };
2123
- ```
2124
-
2125
- #### Service Connect Test Traffic Rules
2126
-
2127
- Configure test traffic routing for Service Connect during blue/green deployments:
2080
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
2128
2081
 
2129
- ```ts
2130
2082
  declare const cluster: ecs.Cluster;
2131
2083
  declare const taskDefinition: ecs.TaskDefinition;
2084
+ declare const lambdaHook: lambda.Function;
2085
+ declare const blueTargetGroup: elbv2.ApplicationTargetGroup;
2086
+ declare const greenTargetGroup: elbv2.ApplicationTargetGroup;
2087
+ declare const prodListenerRule: elbv2.ApplicationListenerRule;
2132
2088
 
2133
2089
  const service = new ecs.FargateService(this, 'Service', {
2134
2090
  cluster,
2135
2091
  taskDefinition,
2092
+ deploymentStrategy: ecs.DeploymentStrategy.BLUE_GREEN,
2136
2093
  });
2137
2094
 
2138
- const cfnService = service.node.defaultChild as ecs.CfnService;
2139
- cfnService.serviceConnectConfiguration = {
2140
- enabled: true,
2141
- services: [{
2142
- portName: 'api',
2143
- clientAliases: [{
2144
- port: 80,
2145
- dnsName: 'my-service',
2146
- testTrafficRules: {
2147
- header: {
2148
- name: 'x-canary-test',
2149
- value: {
2150
- exact: 'beta-version'
2151
- }
2152
- }
2153
- }
2154
- }]
2155
- }]
2156
- };
2095
+ service.addLifecycleHook(new ecs.DeploymentLifecycleLambdaTarget(lambdaHook, 'PreScaleHook', {
2096
+ lifecycleStages: [ecs.DeploymentLifecycleStage.PRE_SCALE_UP],
2097
+ }));
2098
+
2099
+ const target = service.loadBalancerTarget({
2100
+ containerName: 'nginx',
2101
+ containerPort: 80,
2102
+ protocol: ecs.Protocol.TCP,
2103
+ alternateTarget: new ecs.AlternateTarget('AlternateTarget', {
2104
+ alternateTargetGroup: greenTargetGroup,
2105
+ productionListener: ecs.ListenerRuleConfiguration.applicationListenerRule(prodListenerRule),
2106
+ }),
2107
+ });
2108
+
2109
+ target.attachToApplicationTargetGroup(blueTargetGroup);
2157
2110
  ```
2158
2111
 
2159
2112
  ## Daemon Scheduling Strategy
@@ -3,30 +3,20 @@ import * as cdk from 'aws-cdk-lib';
3
3
  import * as ecs from 'aws-cdk-lib/aws-ecs';
4
4
  import { IntegTest } from '@aws-cdk/integ-tests-alpha';
5
5
 
6
- const app = new cdk.App({
7
- postCliContext: {
8
- '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
9
- '@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy': false,
10
- },
11
- });
6
+ const app = new cdk.App();
12
7
  const stack = new cdk.Stack(app, 'aws-ecs-integ-availability-zone-rebalancing');
13
8
 
14
9
  const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false });
15
10
 
16
- const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc });
17
-
18
- cluster.addCapacity('DefaultAutoScalingGroup', {
19
- instanceType: new ec2.InstanceType('t2.micro'),
20
- });
11
+ const cluster = new ecs.Cluster(stack, 'Cluster', { vpc });
21
12
 
22
- const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef');
13
+ const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef');
23
14
 
24
15
  taskDefinition.addContainer('web', {
25
16
  image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
26
- memoryLimitMiB: 256,
27
17
  });
28
18
 
29
- new ecs.Ec2Service(stack, 'FrontendService', {
19
+ new ecs.FargateService(stack, 'FargateService', {
30
20
  cluster,
31
21
  taskDefinition,
32
22
  availabilityZoneRebalancing: ecs.AvailabilityZoneRebalancing.ENABLED,
@@ -1,6 +1,5 @@
1
1
  import * as ec2 from 'aws-cdk-lib/aws-ec2';
2
2
  import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
3
- import * as iam from 'aws-cdk-lib/aws-iam';
4
3
  import * as lambda from 'aws-cdk-lib/aws-lambda';
5
4
  import * as cdk from 'aws-cdk-lib';
6
5
  import * as ecs from 'aws-cdk-lib/aws-ecs';
@@ -89,45 +88,6 @@ const prodListenerRule = new elbv2.ApplicationListenerRule(stack, 'ALBProduction
89
88
  ]),
90
89
  });
91
90
 
92
- // Create granular IAM roles
93
- const ecsTaskExecutionRole = new iam.Role(stack, 'EcsTaskExecutionRole', {
94
- assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
95
- managedPolicies: [
96
- iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonECSTaskExecutionRolePolicy'),
97
- ],
98
- });
99
-
100
- // Create Blue/Green deployment service role
101
- const ecsServiceRole = new iam.Role(stack, 'ServiceRole', {
102
- assumedBy: new iam.CompositePrincipal(
103
- new iam.ServicePrincipal('ecs.amazonaws.com'),
104
- ),
105
- managedPolicies: [
106
- iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2ContainerServiceRole'),
107
- ],
108
- inlinePolicies: {
109
- LambdaInvokePolicy: new iam.PolicyDocument({
110
- statements: [
111
- new iam.PolicyStatement({
112
- actions: ['lambda:InvokeFunction'],
113
- resources: ['*'],
114
- }),
115
- ],
116
- }),
117
- ELBPolicy: new iam.PolicyDocument({
118
- statements: [
119
- new iam.PolicyStatement({
120
- actions: [
121
- 'elasticloadbalancing:ModifyRule',
122
- 'elasticloadbalancing:ModifyListener',
123
- ],
124
- resources: [prodListenerRule.listenerRuleArn],
125
- }),
126
- ],
127
- }),
128
- },
129
- });
130
-
131
91
  // Create Lambda hook
132
92
  const lambdaHook = new lambda.Function(stack, 'LambdaHook', {
133
93
  handler: 'index.handler',
@@ -138,13 +98,10 @@ const lambdaHook = new lambda.Function(stack, 'LambdaHook', {
138
98
  };`),
139
99
  });
140
100
 
141
- lambdaHook.grantInvoke(ecsServiceRole);
142
-
143
101
  // Create task definition
144
102
  const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef', {
145
103
  memoryLimitMiB: 512,
146
104
  cpu: 256,
147
- executionRole: ecsTaskExecutionRole,
148
105
  });
149
106
 
150
107
  // Add container to task definition
@@ -163,39 +120,24 @@ const service = new ecs.FargateService(stack, 'Service', {
163
120
  cluster,
164
121
  taskDefinition,
165
122
  securityGroups: [ecsSecurityGroup],
123
+ deploymentStrategy: ecs.DeploymentStrategy.BLUE_GREEN,
166
124
  });
167
125
 
168
- service.attachToApplicationTargetGroup(blueTargetGroup);
126
+ service.addLifecycleHook(new ecs.DeploymentLifecycleLambdaTarget(lambdaHook, 'PreScaleUp', {
127
+ lifecycleStages: [ecs.DeploymentLifecycleStage.PRE_SCALE_UP],
128
+ }));
169
129
 
170
- // Use escape hatching to set B/G deployment properties
171
- const cfnService = service.node.defaultChild as ecs.CfnService;
172
- cfnService.addPropertyOverride('DeploymentController', {
173
- Type: 'ECS',
174
- });
175
-
176
- cfnService.addPropertyOverride('DeploymentConfiguration', {
177
- DeploymentCircuitBreaker: {
178
- Enable: false,
179
- Rollback: false,
180
- },
181
- MaximumPercent: 200,
182
- MinimumHealthyPercent: 100,
183
- Strategy: 'BLUE_GREEN',
184
- BakeTimeInMinutes: 0,
185
- LifecycleHooks: [{
186
- HookTargetArn: lambdaHook.functionArn,
187
- RoleArn: ecsServiceRole.roleArn,
188
- LifecycleStages: ['POST_TEST_TRAFFIC_SHIFT'],
189
- }],
130
+ const target = service.loadBalancerTarget({
131
+ containerName: 'nginx',
132
+ containerPort: 80,
133
+ protocol: ecs.Protocol.TCP,
134
+ alternateTarget: new ecs.AlternateTarget('LBAlternateOptions', {
135
+ alternateTargetGroup: greenTargetGroup,
136
+ productionListener: ecs.ListenerRuleConfiguration.applicationListenerRule(prodListenerRule),
137
+ }),
190
138
  });
191
139
 
192
- cfnService.addPropertyOverride('LoadBalancers.0', {
193
- AdvancedConfiguration: {
194
- AlternateTargetGroupArn: greenTargetGroup.targetGroupArn,
195
- RoleArn: ecsServiceRole.roleArn,
196
- ProductionListenerRule: prodListenerRule.listenerRuleArn,
197
- },
198
- });
140
+ target.attachToApplicationTargetGroup(blueTargetGroup);
199
141
 
200
142
  // Create integration test
201
143
  new integ.IntegTest(app, 'aws-ecs-blue-green', {
@@ -1,53 +1,30 @@
1
-
2
- import * as autoscaling from 'aws-cdk-lib/aws-autoscaling';
3
- import * as s3 from 'aws-cdk-lib/aws-s3';
4
1
  import * as ec2 from 'aws-cdk-lib/aws-ec2';
2
+ import * as kms from 'aws-cdk-lib/aws-kms';
3
+ import * as s3 from 'aws-cdk-lib/aws-s3';
5
4
  import * as cdk from 'aws-cdk-lib';
5
+ import { Duration } from 'aws-cdk-lib';
6
6
  import * as integ from '@aws-cdk/integ-tests-alpha';
7
7
  import * as ecs from 'aws-cdk-lib/aws-ecs';
8
8
 
9
9
  const app = new cdk.App({
10
10
  postCliContext: {
11
- '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
12
11
  '@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions': true,
13
- '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false,
14
- '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false,
15
- '@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy': false,
16
12
  },
17
13
  });
18
14
  const stack = new cdk.Stack(app, 'aws-ecs-integ-enable-execute-command');
19
15
 
20
- const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2 });
21
-
22
- const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef');
23
-
24
- taskDefinition.addContainer('web', {
25
- image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
26
- memoryReservationMiB: 256,
27
- portMappings: [
28
- {
29
- containerPort: 80,
30
- hostPort: 8080,
31
- protocol: ecs.Protocol.TCP,
32
- },
33
- ],
34
- });
16
+ const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false });
35
17
 
36
- const execBucket = new s3.Bucket(stack, 'EcsExecBucket');
18
+ const kmsKey = new kms.Key(stack, 'KmsKey');
37
19
 
38
- const cp = new ecs.AsgCapacityProvider(stack, 'EC2CapacityProvider', {
39
- autoScalingGroup: new autoscaling.AutoScalingGroup(stack, 'ASG', {
40
- vpc,
41
- instanceType: new ec2.InstanceType('t2.micro'),
42
- machineImage: ecs.EcsOptimizedImage.amazonLinux2(),
43
- }),
44
- // This is to allow cdk destroy to work; otherwise deletion will hang bc ASG cannot be deleted
45
- enableManagedTerminationProtection: false,
20
+ const execBucket = new s3.Bucket(stack, 'EcsExecBucket', {
21
+ encryptionKey: kmsKey,
46
22
  });
47
23
 
48
- const cluster = new ecs.Cluster(stack, 'EC2CPCluster', {
24
+ const cluster = new ecs.Cluster(stack, 'FargateCluster', {
49
25
  vpc,
50
26
  executeCommandConfiguration: {
27
+ kmsKey,
51
28
  logConfiguration: {
52
29
  s3Bucket: execBucket,
53
30
  s3EncryptionEnabled: true,
@@ -56,9 +33,19 @@ const cluster = new ecs.Cluster(stack, 'EC2CPCluster', {
56
33
  logging: ecs.ExecuteCommandLogging.OVERRIDE,
57
34
  },
58
35
  });
59
- cluster.addAsgCapacityProvider(cp);
60
36
 
61
- new ecs.Ec2Service(stack, 'EC2Service', {
37
+ const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef');
38
+
39
+ taskDefinition.addContainer('web', {
40
+ image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
41
+ healthCheck: {
42
+ command: ['CMD-SHELL', 'curl localhost:8000'],
43
+ interval: Duration.seconds(60),
44
+ timeout: Duration.seconds(40),
45
+ },
46
+ });
47
+
48
+ new ecs.FargateService(stack, 'FargateService', {
62
49
  cluster,
63
50
  taskDefinition,
64
51
  enableExecuteCommand: true,
@@ -66,5 +53,12 @@ new ecs.Ec2Service(stack, 'EC2Service', {
66
53
 
67
54
  new integ.IntegTest(app, 'enable-execute-command-test', {
68
55
  testCases: [stack],
56
+ diffAssets: true,
57
+ cdkCommandOptions: {
58
+ deploy: {
59
+ args: {
60
+ rollback: true,
61
+ },
62
+ },
63
+ },
69
64
  });
70
- app.synth();