konokenj.cdk-api-mcp-server 0.26.0__py3-none-any.whl → 0.28.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.
Potentially problematic release.
This version of konokenj.cdk-api-mcp-server might be problematic. Click here for more details.
- cdk_api_mcp_server/__about__.py +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-amplify-alpha/README.md +14 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-bedrock-alpha/README.md +608 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigateway/integ.model-schema-additional-items.ts +72 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront/README.md +8 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront/integ.distribution-basic.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codedeploy/integ.deployment-config.ts +15 -4
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codedeploy/integ.deployment-group.ts +40 -218
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/README.md +34 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/integ.pipeline-ec2-deploy-ssm-managed.ts +140 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/integ.pipeline-ec2-deploy.ts +140 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ec2/README.md +55 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ec2/integ.machine-image-cached.ts +53 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ec2/integ.volume-initialization-rate.ts +21 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/README.md +16 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.availability-zone-rebalancing.ts +4 -14
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.enable-execute-command.ts +29 -35
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.exec-command.ts +22 -16
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.lb-awsvpc-nw.ts +16 -26
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.pseudo-terminal.ts +8 -18
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/README.md +6 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/integ.custom-addons.ts +48 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-logs/README.md +1 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-logs/integ.expose-metric-with-dimensions.ts +47 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-opensearchservice/integ.opensearch.gp3.ts +16 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-opensearchservice/integ.opensearch.https.ts +54 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/README.md +25 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.cluster-serverless-v2-autopause.ts +27 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.instance-from-cluster-snapshot.ts +23 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ssm/README.md +16 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/README.md +21 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.map-jsonata-itemselector.ts +36 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.invoke-jsonata.ts +80 -87
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.invoke.ts +69 -87
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.start-job-run.ts +104 -102
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/README.md +23 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/integ.canary-dryrun-update.ts +32 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/integ.canary.ts +2 -0
- {konokenj_cdk_api_mcp_server-0.26.0.dist-info → konokenj_cdk_api_mcp_server-0.28.0.dist-info}/METADATA +2 -2
- {konokenj_cdk_api_mcp_server-0.26.0.dist-info → konokenj_cdk_api_mcp_server-0.28.0.dist-info}/RECORD +43 -30
- {konokenj_cdk_api_mcp_server-0.26.0.dist-info → konokenj_cdk_api_mcp_server-0.28.0.dist-info}/WHEEL +0 -0
- {konokenj_cdk_api_mcp_server-0.26.0.dist-info → konokenj_cdk_api_mcp_server-0.28.0.dist-info}/entry_points.txt +0 -0
- {konokenj_cdk_api_mcp_server-0.26.0.dist-info → konokenj_cdk_api_mcp_server-0.28.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
3
|
+
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
|
|
4
|
+
|
|
5
|
+
class TestStack extends cdk.Stack {
|
|
6
|
+
constructor(scope: cdk.App, id: string) {
|
|
7
|
+
super(scope, id);
|
|
8
|
+
|
|
9
|
+
const api = new apigateway.RestApi(this, 'model-schema-api', {
|
|
10
|
+
restApiName: 'Model Schema Test API',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// Create a minimal schema that uses additionalItems
|
|
14
|
+
const schema: apigateway.JsonSchema = {
|
|
15
|
+
type: apigateway.JsonSchemaType.OBJECT,
|
|
16
|
+
required: ['tags'],
|
|
17
|
+
properties: {
|
|
18
|
+
tags: {
|
|
19
|
+
type: apigateway.JsonSchemaType.ARRAY,
|
|
20
|
+
items: [
|
|
21
|
+
{ type: apigateway.JsonSchemaType.STRING, enum: ['primary'] },
|
|
22
|
+
{ type: apigateway.JsonSchemaType.STRING, enum: ['secondary'] },
|
|
23
|
+
],
|
|
24
|
+
additionalItems: {
|
|
25
|
+
type: apigateway.JsonSchemaType.STRING,
|
|
26
|
+
pattern: '^[a-z0-9-]+$',
|
|
27
|
+
},
|
|
28
|
+
minItems: 1,
|
|
29
|
+
maxItems: 5,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Create the model using our schema
|
|
35
|
+
const model = api.addModel('TagsModel', {
|
|
36
|
+
contentType: 'application/json',
|
|
37
|
+
modelName: 'Tags',
|
|
38
|
+
schema: schema,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Add a validator that requires the request body to match our model
|
|
42
|
+
const validator = api.addRequestValidator('TagsValidator', {
|
|
43
|
+
requestValidatorName: 'TagsValidator',
|
|
44
|
+
validateRequestBody: true,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Add a POST method that uses the model and validator
|
|
48
|
+
api.root.addMethod('POST', new apigateway.MockIntegration({
|
|
49
|
+
integrationResponses: [{
|
|
50
|
+
statusCode: '200',
|
|
51
|
+
}],
|
|
52
|
+
requestTemplates: {
|
|
53
|
+
'application/json': '{ "statusCode": 200 }',
|
|
54
|
+
},
|
|
55
|
+
}), {
|
|
56
|
+
requestValidator: validator,
|
|
57
|
+
requestModels: {
|
|
58
|
+
'application/json': model,
|
|
59
|
+
},
|
|
60
|
+
methodResponses: [{
|
|
61
|
+
statusCode: '200',
|
|
62
|
+
}],
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const app = new cdk.App();
|
|
68
|
+
const stack = new TestStack(app, 'model-schema-additional-items-test');
|
|
69
|
+
new IntegTest(app, 'ModelSchemaAdditionalItemsTest', {
|
|
70
|
+
testCases: [stack],
|
|
71
|
+
});
|
|
72
|
+
app.synth();
|
|
@@ -1247,6 +1247,14 @@ new cloudfront.KeyGroup(this, 'MyKeyGroup', {
|
|
|
1247
1247
|
});
|
|
1248
1248
|
```
|
|
1249
1249
|
|
|
1250
|
+
When using a CloudFront PublicKey, only the `comment` field can be updated after creation. Fields such as `encodedKey` and `publicKeyName` are immutable, as outlined in the [API Reference](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdatePublicKey.html). Attempting to modify these fields will result in an error:
|
|
1251
|
+
```
|
|
1252
|
+
Resource handler returned message: "Invalid request provided: AWS::CloudFront::PublicKey"
|
|
1253
|
+
```
|
|
1254
|
+
|
|
1255
|
+
To update the `encodedKey`, you must change the logical ID of the public key resource in your template. This causes CloudFormation to create a new `cloudfront.PublicKey` resource and delete the old one during the next deployment.
|
|
1256
|
+
|
|
1257
|
+
|
|
1250
1258
|
See:
|
|
1251
1259
|
|
|
1252
1260
|
- <https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html>
|
|
@@ -18,7 +18,7 @@ const role2 = new iam.Role(stack, 'Role2', {
|
|
|
18
18
|
assumedBy: new iam.AccountRootPrincipal(),
|
|
19
19
|
});
|
|
20
20
|
distribution.grantCreateInvalidation(role1);
|
|
21
|
-
distribution.grant(role2, 'cloudfront:ListInvalidations');
|
|
21
|
+
distribution.grant(role2, 'cloudfront:ListInvalidations', 'cloudfront:ListDistributions');
|
|
22
22
|
|
|
23
23
|
new IntegTest(stack, 'distribution-basic-test', {
|
|
24
24
|
testCases: [stack],
|
|
@@ -2,17 +2,28 @@ import * as cdk from 'aws-cdk-lib';
|
|
|
2
2
|
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
3
3
|
import * as codedeploy from 'aws-cdk-lib/aws-codedeploy';
|
|
4
4
|
|
|
5
|
-
const app = new cdk.App(
|
|
6
|
-
|
|
5
|
+
const app = new cdk.App({
|
|
6
|
+
postCliContext: {
|
|
7
|
+
'@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
const stack = new cdk.Stack(app, 'aws-cdk-codedeploy-lambda-config');
|
|
7
11
|
|
|
8
|
-
new codedeploy.
|
|
12
|
+
new codedeploy.LambdaDeploymentConfig(stack, 'LinearConfig', {
|
|
9
13
|
trafficRouting: codedeploy.TrafficRouting.timeBasedLinear({
|
|
10
14
|
interval: cdk.Duration.minutes(1),
|
|
11
15
|
percentage: 5,
|
|
12
16
|
}),
|
|
13
17
|
});
|
|
14
18
|
|
|
15
|
-
new
|
|
19
|
+
new codedeploy.CustomLambdaDeploymentConfig(stack, 'CustomConfig', {
|
|
20
|
+
interval: cdk.Duration.minutes(1),
|
|
21
|
+
percentage: 5,
|
|
22
|
+
type: cdk.aws_codedeploy.CustomLambdaDeploymentConfigType.LINEAR,
|
|
23
|
+
deploymentConfigName: 'hello',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
new integ.IntegTest(app, 'LambdaDeploymentConfigTest', {
|
|
16
27
|
testCases: [stack],
|
|
17
28
|
});
|
|
18
29
|
|
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codedeploy/integ.deployment-group.ts
CHANGED
|
@@ -1,240 +1,62 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
1
2
|
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
|
|
2
|
-
import * as
|
|
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
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
130
|
-
|
|
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
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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();
|
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/README.md
CHANGED
|
@@ -927,6 +927,40 @@ Here's an example:
|
|
|
927
927
|
|
|
928
928
|
[example ECS pipeline for an application in a separate source code repository](test/integ.pipeline-ecs-separate-source.lit.ts)
|
|
929
929
|
|
|
930
|
+
### Amazon EC2
|
|
931
|
+
|
|
932
|
+
To deploy application code to Amazon EC2 Linux instances or Linux SSM-managed nodes:
|
|
933
|
+
|
|
934
|
+
> **Note**
|
|
935
|
+
> This action is only supported for V2 type pipelines.
|
|
936
|
+
|
|
937
|
+
```ts
|
|
938
|
+
const sourceOutput = new codepipeline.Artifact();
|
|
939
|
+
|
|
940
|
+
const pipeline = new codepipeline.Pipeline(this, 'MyPipeline', {
|
|
941
|
+
pipelineType: codepipeline.PipelineType.V2,
|
|
942
|
+
});
|
|
943
|
+
const deployAction = new codepipeline_actions.Ec2DeployAction({
|
|
944
|
+
actionName: 'Ec2Deploy',
|
|
945
|
+
input: sourceOutput,
|
|
946
|
+
instanceType: codepipeline_actions.Ec2InstanceType.EC2,
|
|
947
|
+
instanceTagKey: 'Name',
|
|
948
|
+
instanceTagValue: 'MyInstance',
|
|
949
|
+
deploySpecifications: codepipeline_actions.Ec2DeploySpecifications.inline({
|
|
950
|
+
targetDirectory: '/home/ec2-user/deploy',
|
|
951
|
+
preScript: 'scripts/pre-deploy.sh',
|
|
952
|
+
postScript: 'scripts/post-deploy.sh',
|
|
953
|
+
}),
|
|
954
|
+
});
|
|
955
|
+
const deployStage = pipeline.addStage({
|
|
956
|
+
stageName: 'Deploy',
|
|
957
|
+
actions: [deployAction],
|
|
958
|
+
});
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
To learn more about using the EC2 deploy action in your pipeline, visit [tutorial](https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-ec2-deploy.html) and [documentation](https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-EC2Deploy.html).
|
|
962
|
+
|
|
963
|
+
|
|
930
964
|
### AWS S3 Deployment
|
|
931
965
|
|
|
932
966
|
To use an S3 Bucket as a deployment target in CodePipeline:
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import * as codepipeline from 'aws-cdk-lib/aws-codepipeline';
|
|
2
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
3
|
+
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
|
|
4
|
+
import * as targets from 'aws-cdk-lib/aws-elasticloadbalancingv2-targets';
|
|
5
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
6
|
+
import * as s3deployment from 'aws-cdk-lib/aws-s3-deployment';
|
|
7
|
+
import * as cdk from 'aws-cdk-lib';
|
|
8
|
+
import * as cpactions from 'aws-cdk-lib/aws-codepipeline-actions';
|
|
9
|
+
import { ExpectedResult, IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
|
|
12
|
+
const app = new cdk.App();
|
|
13
|
+
|
|
14
|
+
const stack = new cdk.Stack(app, 'aws-cdk-codepipeline-ec2-deploy-ssm-managed-node');
|
|
15
|
+
|
|
16
|
+
const vpc = new ec2.Vpc(stack, 'VPC', {
|
|
17
|
+
maxAzs: 2,
|
|
18
|
+
natGateways: 0,
|
|
19
|
+
restrictDefaultSecurityGroup: false,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const instances = Object.fromEntries(Object.entries({ NoLB: [0, 1], LB: [0, 1] }).map(([tagValue, indexs]) => {
|
|
23
|
+
const innerInstances = indexs.map((index) => {
|
|
24
|
+
const userData = ec2.UserData.forLinux();
|
|
25
|
+
userData.addCommands('dnf install httpd -y', 'mkdir -p /var/www/html', 'touch /var/www/html/index.html', 'systemctl start httpd');
|
|
26
|
+
const instance = new ec2.Instance(stack, `Instance-${tagValue}-${index}`, {
|
|
27
|
+
vpc,
|
|
28
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
|
|
29
|
+
availabilityZone: vpc.publicSubnets[index].availabilityZone,
|
|
30
|
+
machineImage: ec2.MachineImage.latestAmazonLinux2023({ cpuType: ec2.AmazonLinuxCpuType.ARM_64 }),
|
|
31
|
+
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE4_GRAVITON, ec2.InstanceSize.MICRO),
|
|
32
|
+
ssmSessionPermissions: true,
|
|
33
|
+
userData,
|
|
34
|
+
});
|
|
35
|
+
instance.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
|
|
36
|
+
instance.connections.allowFromAnyIpv4(ec2.Port.HTTP);
|
|
37
|
+
cdk.Tags.of(instance).add('EC2-Target', tagValue);
|
|
38
|
+
return instance;
|
|
39
|
+
});
|
|
40
|
+
return [tagValue, innerInstances];
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
const alb = new elbv2.ApplicationLoadBalancer(stack, 'ALB', { vpc, internetFacing: true });
|
|
44
|
+
const albTg = new elbv2.ApplicationTargetGroup(stack, 'ALB-TG', {
|
|
45
|
+
vpc,
|
|
46
|
+
protocol: elbv2.ApplicationProtocol.HTTP,
|
|
47
|
+
deregistrationDelay: cdk.Duration.seconds(0),
|
|
48
|
+
});
|
|
49
|
+
alb.addListener('HTTP', {
|
|
50
|
+
protocol: elbv2.ApplicationProtocol.HTTP,
|
|
51
|
+
defaultTargetGroups: [albTg],
|
|
52
|
+
});
|
|
53
|
+
alb.connections.allowToAnyIpv4(ec2.Port.HTTP);
|
|
54
|
+
albTg.addTarget(...instances.LB.map((instance) => new targets.InstanceTarget(instance)));
|
|
55
|
+
|
|
56
|
+
const bucket = new s3.Bucket(stack, 'ArtifactBucket', {
|
|
57
|
+
versioned: true,
|
|
58
|
+
autoDeleteObjects: true,
|
|
59
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
60
|
+
});
|
|
61
|
+
instances.LB.forEach((instance) => bucket.grantRead(instance));
|
|
62
|
+
instances.NoLB.forEach((instance) => bucket.grantRead(instance));
|
|
63
|
+
const deployment = new s3deployment.BucketDeployment(stack, 'ArtifactDeployment', {
|
|
64
|
+
destinationBucket: bucket,
|
|
65
|
+
sources: [s3deployment.Source.asset(path.join(__dirname, 'ec2-deploy-artifacts', 'inline'))],
|
|
66
|
+
extract: false,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const sourceArtifact = new codepipeline.Artifact('SourceArtifact');
|
|
70
|
+
const sourceAction = new cpactions.S3SourceAction({
|
|
71
|
+
actionName: 'Source',
|
|
72
|
+
output: sourceArtifact,
|
|
73
|
+
bucket,
|
|
74
|
+
bucketKey: cdk.Fn.select(0, deployment.objectKeys),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const pipeline = new codepipeline.Pipeline(stack, 'MyPipeline', {
|
|
78
|
+
pipelineType: codepipeline.PipelineType.V2,
|
|
79
|
+
artifactBucket: bucket,
|
|
80
|
+
stages: [
|
|
81
|
+
{
|
|
82
|
+
stageName: 'Source',
|
|
83
|
+
actions: [sourceAction],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
stageName: 'Deploy',
|
|
87
|
+
actions: [
|
|
88
|
+
new cpactions.Ec2DeployAction({
|
|
89
|
+
actionName: 'EC2-NoLB',
|
|
90
|
+
input: sourceArtifact,
|
|
91
|
+
instanceType: cpactions.Ec2InstanceType.SSM_MANAGED_NODE,
|
|
92
|
+
instanceTagKey: 'EC2-Target',
|
|
93
|
+
instanceTagValue: 'NoLB',
|
|
94
|
+
deploySpecifications: cpactions.Ec2DeploySpecifications.inline({
|
|
95
|
+
targetDirectory: '/var/www/html/NoLB',
|
|
96
|
+
preScript: 'scripts/pre-deploy.sh',
|
|
97
|
+
postScript: 'scripts/post-deploy.sh',
|
|
98
|
+
}),
|
|
99
|
+
maxBatch: cpactions.Ec2MaxInstances.targets(2),
|
|
100
|
+
}),
|
|
101
|
+
new cpactions.Ec2DeployAction({
|
|
102
|
+
actionName: 'EC2-LB',
|
|
103
|
+
input: sourceArtifact,
|
|
104
|
+
instanceType: cpactions.Ec2InstanceType.SSM_MANAGED_NODE,
|
|
105
|
+
instanceTagKey: 'EC2-Target',
|
|
106
|
+
instanceTagValue: 'LB',
|
|
107
|
+
deploySpecifications: cpactions.Ec2DeploySpecifications.inline({
|
|
108
|
+
targetDirectory: '/var/www/html/LB',
|
|
109
|
+
preScript: 'scripts/pre-deploy.sh',
|
|
110
|
+
postScript: 'scripts/post-deploy.sh',
|
|
111
|
+
}),
|
|
112
|
+
targetGroups: [albTg],
|
|
113
|
+
maxBatch: cpactions.Ec2MaxInstances.targets(1),
|
|
114
|
+
}),
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const integ = new IntegTest(app, 'ec2-deploy-action-ssm-managed-node-integ', {
|
|
121
|
+
testCases: [stack],
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const pipelineExecutionId = integ.assertions
|
|
125
|
+
.awsApiCall('codepipeline', 'StartPipelineExecution', { name: pipeline.pipelineName })
|
|
126
|
+
.getAttString('pipelineExecutionId');
|
|
127
|
+
const waitPipelieneSuccess = integ.assertions
|
|
128
|
+
.awsApiCall('codepipeline', 'GetPipelineExecution', { pipelineName: pipeline.pipelineName, pipelineExecutionId })
|
|
129
|
+
.waitForAssertions({ interval: cdk.Duration.seconds(30) })
|
|
130
|
+
.expect(ExpectedResult.objectLike({ pipelineExecution: { status: 'Succeeded' } }));
|
|
131
|
+
waitPipelieneSuccess.next(
|
|
132
|
+
integ.assertions
|
|
133
|
+
.httpApiCall(`http://${alb.loadBalancerDnsName}/LB/index.html`)
|
|
134
|
+
.expect(ExpectedResult.objectLike({ status: 200 })),
|
|
135
|
+
);
|
|
136
|
+
instances.NoLB.forEach((instance) => waitPipelieneSuccess.next(
|
|
137
|
+
integ.assertions
|
|
138
|
+
.httpApiCall(`http://${instance.instancePublicDnsName}/NoLB/index.html`)
|
|
139
|
+
.expect(ExpectedResult.objectLike({ status: 200 })),
|
|
140
|
+
));
|