@frontpoint/aws-infra-mcp 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +141 -0
- package/dist/core/aws-analyzer.d.ts +73 -0
- package/dist/core/aws-analyzer.d.ts.map +1 -0
- package/dist/core/aws-analyzer.js +429 -0
- package/dist/core/aws-analyzer.js.map +1 -0
- package/dist/core/cdk-generator.d.ts +26 -0
- package/dist/core/cdk-generator.d.ts.map +1 -0
- package/dist/core/cdk-generator.js +790 -0
- package/dist/core/cdk-generator.js.map +1 -0
- package/dist/core/template-engine.d.ts +32 -0
- package/dist/core/template-engine.d.ts.map +1 -0
- package/dist/core/template-engine.js +131 -0
- package/dist/core/template-engine.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +158 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/aws-add-compute.d.ts +8 -0
- package/dist/tools/aws-add-compute.d.ts.map +1 -0
- package/dist/tools/aws-add-compute.js +269 -0
- package/dist/tools/aws-add-compute.js.map +1 -0
- package/dist/tools/aws-add-database.d.ts +8 -0
- package/dist/tools/aws-add-database.d.ts.map +1 -0
- package/dist/tools/aws-add-database.js +230 -0
- package/dist/tools/aws-add-database.js.map +1 -0
- package/dist/tools/aws-add-network.d.ts +8 -0
- package/dist/tools/aws-add-network.d.ts.map +1 -0
- package/dist/tools/aws-add-network.js +240 -0
- package/dist/tools/aws-add-network.js.map +1 -0
- package/dist/tools/aws-add-storage.d.ts +8 -0
- package/dist/tools/aws-add-storage.d.ts.map +1 -0
- package/dist/tools/aws-add-storage.js +207 -0
- package/dist/tools/aws-add-storage.js.map +1 -0
- package/dist/tools/aws-analyze.d.ts +8 -0
- package/dist/tools/aws-analyze.d.ts.map +1 -0
- package/dist/tools/aws-analyze.js +123 -0
- package/dist/tools/aws-analyze.js.map +1 -0
- package/dist/tools/aws-generate-all.d.ts +8 -0
- package/dist/tools/aws-generate-all.d.ts.map +1 -0
- package/dist/tools/aws-generate-all.js +197 -0
- package/dist/tools/aws-generate-all.js.map +1 -0
- package/dist/tools/aws-init.d.ts +8 -0
- package/dist/tools/aws-init.d.ts.map +1 -0
- package/dist/tools/aws-init.js +114 -0
- package/dist/tools/aws-init.js.map +1 -0
- package/dist/tools/aws-status.d.ts +8 -0
- package/dist/tools/aws-status.d.ts.map +1 -0
- package/dist/tools/aws-status.js +110 -0
- package/dist/tools/aws-status.js.map +1 -0
- package/dist/tools/index.d.ts +51 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +35 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types.d.ts +644 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,790 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDK Generator - Generate AWS CDK TypeScript code from configuration
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { templateEngine } from './template-engine.js';
|
|
7
|
+
// CDK Templates
|
|
8
|
+
const CDK_APP_TEMPLATE = `#!/usr/bin/env node
|
|
9
|
+
import 'source-map-support/register';
|
|
10
|
+
import * as cdk from 'aws-cdk-lib';
|
|
11
|
+
{{#if stacks.network}}
|
|
12
|
+
import { NetworkStack } from '../lib/stacks/network-stack';
|
|
13
|
+
{{/if}}
|
|
14
|
+
{{#if stacks.database}}
|
|
15
|
+
import { DatabaseStack } from '../lib/stacks/database-stack';
|
|
16
|
+
{{/if}}
|
|
17
|
+
{{#if stacks.storage}}
|
|
18
|
+
import { StorageStack } from '../lib/stacks/storage-stack';
|
|
19
|
+
{{/if}}
|
|
20
|
+
{{#if stacks.compute}}
|
|
21
|
+
import { ComputeStack } from '../lib/stacks/compute-stack';
|
|
22
|
+
{{/if}}
|
|
23
|
+
|
|
24
|
+
const app = new cdk.App();
|
|
25
|
+
|
|
26
|
+
const env = {
|
|
27
|
+
account: process.env.CDK_DEFAULT_ACCOUNT || '{{account}}',
|
|
28
|
+
region: process.env.CDK_DEFAULT_REGION || '{{region}}',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const tags = {
|
|
32
|
+
Project: '{{projectName}}',
|
|
33
|
+
Environment: '{{environment}}',
|
|
34
|
+
ManagedBy: 'CDK',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
{{#if stacks.network}}
|
|
38
|
+
const networkStack = new NetworkStack(app, '{{pascalCase projectName}}NetworkStack', {
|
|
39
|
+
env,
|
|
40
|
+
tags,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
{{/if}}
|
|
44
|
+
{{#if stacks.database}}
|
|
45
|
+
const databaseStack = new DatabaseStack(app, '{{pascalCase projectName}}DatabaseStack', {
|
|
46
|
+
env,
|
|
47
|
+
tags,
|
|
48
|
+
{{#if stacks.network}}
|
|
49
|
+
vpc: networkStack.vpc,
|
|
50
|
+
{{/if}}
|
|
51
|
+
});
|
|
52
|
+
{{#if stacks.network}}
|
|
53
|
+
databaseStack.addDependency(networkStack);
|
|
54
|
+
{{/if}}
|
|
55
|
+
|
|
56
|
+
{{/if}}
|
|
57
|
+
{{#if stacks.storage}}
|
|
58
|
+
const storageStack = new StorageStack(app, '{{pascalCase projectName}}StorageStack', {
|
|
59
|
+
env,
|
|
60
|
+
tags,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
{{/if}}
|
|
64
|
+
{{#if stacks.compute}}
|
|
65
|
+
const computeStack = new ComputeStack(app, '{{pascalCase projectName}}ComputeStack', {
|
|
66
|
+
env,
|
|
67
|
+
tags,
|
|
68
|
+
{{#if stacks.network}}
|
|
69
|
+
vpc: networkStack.vpc,
|
|
70
|
+
{{/if}}
|
|
71
|
+
{{#if stacks.storage}}
|
|
72
|
+
ecrRepositories: storageStack.ecrRepositories,
|
|
73
|
+
{{/if}}
|
|
74
|
+
});
|
|
75
|
+
{{#if stacks.network}}
|
|
76
|
+
computeStack.addDependency(networkStack);
|
|
77
|
+
{{/if}}
|
|
78
|
+
{{#if stacks.storage}}
|
|
79
|
+
computeStack.addDependency(storageStack);
|
|
80
|
+
{{/if}}
|
|
81
|
+
{{/if}}
|
|
82
|
+
|
|
83
|
+
app.synth();
|
|
84
|
+
`;
|
|
85
|
+
const NETWORK_STACK_TEMPLATE = `import * as cdk from 'aws-cdk-lib';
|
|
86
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
87
|
+
import * as apigateway from 'aws-cdk-lib/aws-apigatewayv2';
|
|
88
|
+
import { Construct } from 'constructs';
|
|
89
|
+
|
|
90
|
+
export interface NetworkStackProps extends cdk.StackProps {}
|
|
91
|
+
|
|
92
|
+
export class NetworkStack extends cdk.Stack {
|
|
93
|
+
public readonly vpc: ec2.IVpc;
|
|
94
|
+
|
|
95
|
+
constructor(scope: Construct, id: string, props?: NetworkStackProps) {
|
|
96
|
+
super(scope, id, props);
|
|
97
|
+
|
|
98
|
+
{{#each vpcs}}
|
|
99
|
+
// VPC: {{name}}
|
|
100
|
+
const {{camelCase name}}Vpc = new ec2.Vpc(this, '{{pascalCase name}}Vpc', {
|
|
101
|
+
ipAddresses: ec2.IpAddresses.cidr('{{cidrBlock}}'),
|
|
102
|
+
maxAzs: {{length subnets}},
|
|
103
|
+
enableDnsSupport: {{enableDnsSupport}},
|
|
104
|
+
enableDnsHostnames: {{enableDnsHostnames}},
|
|
105
|
+
natGateways: {{length natGateways}},
|
|
106
|
+
subnetConfiguration: [
|
|
107
|
+
{
|
|
108
|
+
name: 'Public',
|
|
109
|
+
subnetType: ec2.SubnetType.PUBLIC,
|
|
110
|
+
cidrMask: 20,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'Private',
|
|
114
|
+
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
|
|
115
|
+
cidrMask: 20,
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
{{#if ../isFirst}}
|
|
121
|
+
this.vpc = {{camelCase name}}Vpc;
|
|
122
|
+
{{/if}}
|
|
123
|
+
|
|
124
|
+
// Security Groups
|
|
125
|
+
{{#each securityGroups}}
|
|
126
|
+
const {{camelCase name}} = new ec2.SecurityGroup(this, '{{pascalCase name}}', {
|
|
127
|
+
vpc: {{camelCase ../name}}Vpc,
|
|
128
|
+
description: '{{description}}',
|
|
129
|
+
allowAllOutbound: true,
|
|
130
|
+
});
|
|
131
|
+
{{#each ingressRules}}
|
|
132
|
+
{{camelCase ../name}}.addIngressRule(
|
|
133
|
+
ec2.Peer.ipv4('{{cidrBlocks.[0]}}'),
|
|
134
|
+
ec2.Port.tcp({{toPort}}),
|
|
135
|
+
'{{description}}'
|
|
136
|
+
);
|
|
137
|
+
{{/each}}
|
|
138
|
+
{{/each}}
|
|
139
|
+
{{/each}}
|
|
140
|
+
|
|
141
|
+
{{#each apiGateways}}
|
|
142
|
+
// API Gateway: {{name}}
|
|
143
|
+
const {{camelCase name}}Api = new apigateway.CfnApi(this, '{{pascalCase name}}Api', {
|
|
144
|
+
name: '{{name}}',
|
|
145
|
+
protocolType: '{{type}}',
|
|
146
|
+
description: '{{description}}',
|
|
147
|
+
{{#if cors}}
|
|
148
|
+
corsConfiguration: {
|
|
149
|
+
allowOrigins: {{{jsonInline cors.allowOrigins}}},
|
|
150
|
+
allowMethods: {{{jsonInline cors.allowMethods}}},
|
|
151
|
+
allowHeaders: {{{jsonInline cors.allowHeaders}}},
|
|
152
|
+
maxAge: {{cors.maxAge}},
|
|
153
|
+
},
|
|
154
|
+
{{/if}}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
{{#each stages}}
|
|
158
|
+
new apigateway.CfnStage(this, '{{pascalCase ../name}}{{pascalCase name}}Stage', {
|
|
159
|
+
apiId: {{camelCase ../name}}Api.ref,
|
|
160
|
+
stageName: '{{name}}',
|
|
161
|
+
autoDeploy: {{autoDeploy}},
|
|
162
|
+
});
|
|
163
|
+
{{/each}}
|
|
164
|
+
{{/each}}
|
|
165
|
+
|
|
166
|
+
// Outputs
|
|
167
|
+
{{#each vpcs}}
|
|
168
|
+
new cdk.CfnOutput(this, '{{pascalCase name}}VpcId', {
|
|
169
|
+
value: {{camelCase name}}Vpc.vpcId,
|
|
170
|
+
description: 'VPC ID for {{name}}',
|
|
171
|
+
});
|
|
172
|
+
{{/each}}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
`;
|
|
176
|
+
const DATABASE_STACK_TEMPLATE = `import * as cdk from 'aws-cdk-lib';
|
|
177
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
178
|
+
import * as rds from 'aws-cdk-lib/aws-rds';
|
|
179
|
+
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
|
|
180
|
+
import { Construct } from 'constructs';
|
|
181
|
+
|
|
182
|
+
export interface DatabaseStackProps extends cdk.StackProps {
|
|
183
|
+
vpc?: ec2.IVpc;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export class DatabaseStack extends cdk.Stack {
|
|
187
|
+
constructor(scope: Construct, id: string, props?: DatabaseStackProps) {
|
|
188
|
+
super(scope, id, props);
|
|
189
|
+
|
|
190
|
+
const vpc = props?.vpc;
|
|
191
|
+
|
|
192
|
+
{{#each rdsInstances}}
|
|
193
|
+
// RDS Instance: {{name}}
|
|
194
|
+
new rds.DatabaseInstance(this, '{{pascalCase name}}', {
|
|
195
|
+
engine: rds.DatabaseInstanceEngine.{{uppercase engine}}({
|
|
196
|
+
version: rds.{{pascalCase engine}}EngineVersion.VER_{{snakeCase engineVersion}},
|
|
197
|
+
}),
|
|
198
|
+
instanceType: ec2.InstanceType.of(
|
|
199
|
+
ec2.InstanceClass.{{uppercase (substring instanceClass 3 4)}},
|
|
200
|
+
ec2.InstanceSize.{{uppercase (substring instanceClass 5)}}
|
|
201
|
+
),
|
|
202
|
+
vpc: vpc!,
|
|
203
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
204
|
+
allocatedStorage: {{allocatedStorage}},
|
|
205
|
+
storageType: rds.StorageType.GP3,
|
|
206
|
+
multiAz: {{multiAZ}},
|
|
207
|
+
publiclyAccessible: {{publiclyAccessible}},
|
|
208
|
+
deletionProtection: {{deletionProtection}},
|
|
209
|
+
backupRetention: cdk.Duration.days({{backupRetentionPeriod}}),
|
|
210
|
+
enablePerformanceInsights: {{performanceInsightsEnabled}},
|
|
211
|
+
removalPolicy: cdk.RemovalPolicy.SNAPSHOT,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
{{/each}}
|
|
215
|
+
{{#each auroraClusters}}
|
|
216
|
+
// Aurora Cluster: {{name}}
|
|
217
|
+
{{#if serverlessV2ScalingConfiguration}}
|
|
218
|
+
new rds.DatabaseCluster(this, '{{pascalCase name}}', {
|
|
219
|
+
engine: rds.DatabaseClusterEngine.{{camelCase engine}}({
|
|
220
|
+
version: rds.Aurora{{pascalCase (substring engine 7)}}EngineVersion.VER_3_04_0,
|
|
221
|
+
}),
|
|
222
|
+
vpc: vpc!,
|
|
223
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
224
|
+
serverlessV2MinCapacity: {{serverlessV2ScalingConfiguration.minCapacity}},
|
|
225
|
+
serverlessV2MaxCapacity: {{serverlessV2ScalingConfiguration.maxCapacity}},
|
|
226
|
+
writer: rds.ClusterInstance.serverlessV2('writer'),
|
|
227
|
+
deletionProtection: {{deletionProtection}},
|
|
228
|
+
backup: { retention: cdk.Duration.days({{backupRetentionPeriod}}) },
|
|
229
|
+
removalPolicy: cdk.RemovalPolicy.SNAPSHOT,
|
|
230
|
+
});
|
|
231
|
+
{{else}}
|
|
232
|
+
new rds.DatabaseCluster(this, '{{pascalCase name}}', {
|
|
233
|
+
engine: rds.DatabaseClusterEngine.{{camelCase engine}}({
|
|
234
|
+
version: rds.Aurora{{pascalCase (substring engine 7)}}EngineVersion.VER_3_04_0,
|
|
235
|
+
}),
|
|
236
|
+
vpc: vpc!,
|
|
237
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
238
|
+
writer: rds.ClusterInstance.provisioned('writer', {
|
|
239
|
+
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.LARGE),
|
|
240
|
+
}),
|
|
241
|
+
readers: [
|
|
242
|
+
{{#times (dec instances) }}
|
|
243
|
+
rds.ClusterInstance.provisioned('reader{{index}}', {
|
|
244
|
+
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.LARGE),
|
|
245
|
+
}),
|
|
246
|
+
{{/times}}
|
|
247
|
+
],
|
|
248
|
+
deletionProtection: {{deletionProtection}},
|
|
249
|
+
backup: { retention: cdk.Duration.days({{backupRetentionPeriod}}) },
|
|
250
|
+
removalPolicy: cdk.RemovalPolicy.SNAPSHOT,
|
|
251
|
+
});
|
|
252
|
+
{{/if}}
|
|
253
|
+
|
|
254
|
+
{{/each}}
|
|
255
|
+
{{#each dynamoDBTables}}
|
|
256
|
+
// DynamoDB Table: {{name}}
|
|
257
|
+
new dynamodb.Table(this, '{{pascalCase name}}', {
|
|
258
|
+
tableName: '{{name}}',
|
|
259
|
+
partitionKey: { name: '{{partitionKey.name}}', type: dynamodb.AttributeType.{{partitionKey.type}} },
|
|
260
|
+
{{#if sortKey}}
|
|
261
|
+
sortKey: { name: '{{sortKey.name}}', type: dynamodb.AttributeType.{{sortKey.type}} },
|
|
262
|
+
{{/if}}
|
|
263
|
+
{{#ifEquals billingMode "PAY_PER_REQUEST"}}
|
|
264
|
+
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
|
|
265
|
+
{{else}}
|
|
266
|
+
billingMode: dynamodb.BillingMode.PROVISIONED,
|
|
267
|
+
readCapacity: {{readCapacity}},
|
|
268
|
+
writeCapacity: {{writeCapacity}},
|
|
269
|
+
{{/ifEquals}}
|
|
270
|
+
pointInTimeRecovery: {{pointInTimeRecovery}},
|
|
271
|
+
removalPolicy: cdk.RemovalPolicy.RETAIN,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
{{/each}}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
`;
|
|
278
|
+
const STORAGE_STACK_TEMPLATE = `import * as cdk from 'aws-cdk-lib';
|
|
279
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
280
|
+
import * as ecr from 'aws-cdk-lib/aws-ecr';
|
|
281
|
+
import { Construct } from 'constructs';
|
|
282
|
+
|
|
283
|
+
export interface StorageStackProps extends cdk.StackProps {}
|
|
284
|
+
|
|
285
|
+
export class StorageStack extends cdk.Stack {
|
|
286
|
+
public readonly ecrRepositories: Map<string, ecr.IRepository> = new Map();
|
|
287
|
+
|
|
288
|
+
constructor(scope: Construct, id: string, props?: StorageStackProps) {
|
|
289
|
+
super(scope, id, props);
|
|
290
|
+
|
|
291
|
+
{{#each s3Buckets}}
|
|
292
|
+
// S3 Bucket: {{name}}
|
|
293
|
+
new s3.Bucket(this, '{{pascalCase name}}', {
|
|
294
|
+
bucketName: '{{name}}',
|
|
295
|
+
versioned: {{versioning}},
|
|
296
|
+
encryption: s3.BucketEncryption.{{#ifEquals encryption.type "AES256"}}S3_MANAGED{{else}}KMS_MANAGED{{/ifEquals}},
|
|
297
|
+
{{#if publicAccessBlock}}
|
|
298
|
+
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
299
|
+
{{/if}}
|
|
300
|
+
{{#if websiteConfiguration}}
|
|
301
|
+
websiteIndexDocument: '{{websiteConfiguration.indexDocument}}',
|
|
302
|
+
websiteErrorDocument: '{{websiteConfiguration.errorDocument}}',
|
|
303
|
+
publicReadAccess: true,
|
|
304
|
+
{{/if}}
|
|
305
|
+
{{#ifNotEmpty lifecycleRules}}
|
|
306
|
+
lifecycleRules: [
|
|
307
|
+
{{#each lifecycleRules}}
|
|
308
|
+
{
|
|
309
|
+
id: '{{id}}',
|
|
310
|
+
enabled: {{enabled}},
|
|
311
|
+
{{#if expiration}}
|
|
312
|
+
expiration: cdk.Duration.days({{expiration.days}}),
|
|
313
|
+
{{/if}}
|
|
314
|
+
},
|
|
315
|
+
{{/each}}
|
|
316
|
+
],
|
|
317
|
+
{{/ifNotEmpty}}
|
|
318
|
+
removalPolicy: cdk.RemovalPolicy.RETAIN,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
{{/each}}
|
|
322
|
+
{{#each ecrRepositories}}
|
|
323
|
+
// ECR Repository: {{name}}
|
|
324
|
+
const {{camelCase name}}Repo = new ecr.Repository(this, '{{pascalCase name}}', {
|
|
325
|
+
repositoryName: '{{name}}',
|
|
326
|
+
imageScanOnPush: {{imageScanningEnabled}},
|
|
327
|
+
imageTagMutability: ecr.TagMutability.{{imageTagMutability}},
|
|
328
|
+
encryption: ecr.RepositoryEncryption.AES_256,
|
|
329
|
+
{{#if lifecyclePolicy}}
|
|
330
|
+
lifecycleRules: [
|
|
331
|
+
{{#each lifecyclePolicy.rules}}
|
|
332
|
+
{
|
|
333
|
+
rulePriority: {{rulePriority}},
|
|
334
|
+
description: '{{description}}',
|
|
335
|
+
maxImageCount: {{selection.countNumber}},
|
|
336
|
+
},
|
|
337
|
+
{{/each}}
|
|
338
|
+
],
|
|
339
|
+
{{/if}}
|
|
340
|
+
removalPolicy: cdk.RemovalPolicy.RETAIN,
|
|
341
|
+
});
|
|
342
|
+
this.ecrRepositories.set('{{name}}', {{camelCase name}}Repo);
|
|
343
|
+
|
|
344
|
+
{{/each}}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
`;
|
|
348
|
+
const COMPUTE_STACK_TEMPLATE = `import * as cdk from 'aws-cdk-lib';
|
|
349
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
350
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
351
|
+
import * as ecs from 'aws-cdk-lib/aws-ecs';
|
|
352
|
+
import * as eks from 'aws-cdk-lib/aws-eks';
|
|
353
|
+
import * as ecr from 'aws-cdk-lib/aws-ecr';
|
|
354
|
+
import { Construct } from 'constructs';
|
|
355
|
+
|
|
356
|
+
export interface ComputeStackProps extends cdk.StackProps {
|
|
357
|
+
vpc?: ec2.IVpc;
|
|
358
|
+
ecrRepositories?: Map<string, ecr.IRepository>;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export class ComputeStack extends cdk.Stack {
|
|
362
|
+
constructor(scope: Construct, id: string, props?: ComputeStackProps) {
|
|
363
|
+
super(scope, id, props);
|
|
364
|
+
|
|
365
|
+
const vpc = props?.vpc;
|
|
366
|
+
|
|
367
|
+
{{#each ec2Instances}}
|
|
368
|
+
// EC2 Instance: {{name}}
|
|
369
|
+
new ec2.Instance(this, '{{pascalCase name}}', {
|
|
370
|
+
instanceName: '{{name}}',
|
|
371
|
+
vpc: vpc!,
|
|
372
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
373
|
+
instanceType: new ec2.InstanceType('{{instanceType}}'),
|
|
374
|
+
machineImage: ec2.MachineImage.latestAmazonLinux2023(),
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
{{/each}}
|
|
378
|
+
{{#each lambdaFunctions}}
|
|
379
|
+
// Lambda Function: {{name}}
|
|
380
|
+
new lambda.Function(this, '{{pascalCase name}}', {
|
|
381
|
+
functionName: '{{name}}',
|
|
382
|
+
runtime: lambda.Runtime.{{uppercase (replace runtime "." "_")}},
|
|
383
|
+
handler: '{{handler}}',
|
|
384
|
+
code: lambda.Code.fromAsset('lambda/{{kebabCase name}}'),
|
|
385
|
+
memorySize: {{memorySize}},
|
|
386
|
+
timeout: cdk.Duration.seconds({{timeout}}),
|
|
387
|
+
{{#if vpcConfig}}
|
|
388
|
+
vpc: vpc,
|
|
389
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
390
|
+
{{/if}}
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
{{/each}}
|
|
394
|
+
{{#each ecsClusters}}
|
|
395
|
+
// ECS Cluster: {{name}}
|
|
396
|
+
const {{camelCase name}}Cluster = new ecs.Cluster(this, '{{pascalCase name}}Cluster', {
|
|
397
|
+
clusterName: '{{name}}',
|
|
398
|
+
vpc: vpc!,
|
|
399
|
+
containerInsights: {{containerInsights}},
|
|
400
|
+
enableFargateCapacityProviders: true,
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
{{/each}}
|
|
404
|
+
{{#each ecsServices}}
|
|
405
|
+
// ECS Service: {{name}}
|
|
406
|
+
const {{camelCase name}}TaskDef = new ecs.FargateTaskDefinition(this, '{{pascalCase name}}TaskDef', {
|
|
407
|
+
memoryLimitMiB: 512,
|
|
408
|
+
cpu: 256,
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
{{camelCase name}}TaskDef.addContainer('{{name}}-container', {
|
|
412
|
+
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
|
|
413
|
+
portMappings: [{ containerPort: 80 }],
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
new ecs.FargateService(this, '{{pascalCase name}}Service', {
|
|
417
|
+
serviceName: '{{name}}',
|
|
418
|
+
cluster: {{camelCase clusterId}}Cluster,
|
|
419
|
+
taskDefinition: {{camelCase name}}TaskDef,
|
|
420
|
+
desiredCount: {{desiredCount}},
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
{{/each}}
|
|
424
|
+
{{#each eksClusters}}
|
|
425
|
+
// EKS Cluster: {{name}}
|
|
426
|
+
const {{camelCase name}}Cluster = new eks.Cluster(this, '{{pascalCase name}}', {
|
|
427
|
+
clusterName: '{{name}}',
|
|
428
|
+
vpc: vpc!,
|
|
429
|
+
version: eks.KubernetesVersion.V1_29,
|
|
430
|
+
defaultCapacity: 0,
|
|
431
|
+
endpointAccess: eks.EndpointAccess.PUBLIC_AND_PRIVATE,
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
{{#each nodeGroups}}
|
|
435
|
+
{{camelCase ../name}}Cluster.addNodegroupCapacity('{{pascalCase name}}', {
|
|
436
|
+
nodegroupName: '{{name}}',
|
|
437
|
+
instanceTypes: [{{#each instanceTypes}}new ec2.InstanceType('{{this}}'){{#unless @last}}, {{/unless}}{{/each}}],
|
|
438
|
+
minSize: {{scalingConfig.minSize}},
|
|
439
|
+
maxSize: {{scalingConfig.maxSize}},
|
|
440
|
+
desiredSize: {{scalingConfig.desiredSize}},
|
|
441
|
+
diskSize: {{diskSize}},
|
|
442
|
+
});
|
|
443
|
+
{{/each}}
|
|
444
|
+
{{/each}}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
`;
|
|
448
|
+
const PACKAGE_JSON_TEMPLATE = `{
|
|
449
|
+
"name": "{{kebabCase projectName}}-cdk",
|
|
450
|
+
"version": "0.1.0",
|
|
451
|
+
"bin": {
|
|
452
|
+
"{{kebabCase projectName}}-cdk": "bin/app.js"
|
|
453
|
+
},
|
|
454
|
+
"scripts": {
|
|
455
|
+
"build": "tsc",
|
|
456
|
+
"watch": "tsc -w",
|
|
457
|
+
"cdk": "cdk",
|
|
458
|
+
"synth": "cdk synth",
|
|
459
|
+
"diff": "cdk diff",
|
|
460
|
+
"deploy": "cdk deploy --all",
|
|
461
|
+
"destroy": "cdk destroy --all"
|
|
462
|
+
},
|
|
463
|
+
"devDependencies": {
|
|
464
|
+
"@types/node": "^20.10.0",
|
|
465
|
+
"aws-cdk": "^2.120.0",
|
|
466
|
+
"typescript": "^5.3.0"
|
|
467
|
+
},
|
|
468
|
+
"dependencies": {
|
|
469
|
+
"aws-cdk-lib": "^2.120.0",
|
|
470
|
+
"constructs": "^10.3.0",
|
|
471
|
+
"source-map-support": "^0.5.21"
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
`;
|
|
475
|
+
const CDK_JSON_TEMPLATE = `{
|
|
476
|
+
"app": "npx ts-node --prefer-ts-exts bin/app.ts",
|
|
477
|
+
"watch": {
|
|
478
|
+
"include": ["**"],
|
|
479
|
+
"exclude": [
|
|
480
|
+
"README.md",
|
|
481
|
+
"cdk*.json",
|
|
482
|
+
"**/*.d.ts",
|
|
483
|
+
"**/*.js",
|
|
484
|
+
"tsconfig.json",
|
|
485
|
+
"package*.json",
|
|
486
|
+
"node_modules"
|
|
487
|
+
]
|
|
488
|
+
},
|
|
489
|
+
"context": {
|
|
490
|
+
"@aws-cdk/aws-lambda:recognizeVersionProps": true,
|
|
491
|
+
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
|
|
492
|
+
"@aws-cdk/core:checkSecretUsage": true,
|
|
493
|
+
"@aws-cdk/core:target-partitions": ["aws", "aws-cn"]
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
`;
|
|
497
|
+
const TSCONFIG_TEMPLATE = `{
|
|
498
|
+
"compilerOptions": {
|
|
499
|
+
"target": "ES2022",
|
|
500
|
+
"module": "commonjs",
|
|
501
|
+
"lib": ["ES2022"],
|
|
502
|
+
"declaration": true,
|
|
503
|
+
"strict": true,
|
|
504
|
+
"noImplicitAny": true,
|
|
505
|
+
"strictNullChecks": true,
|
|
506
|
+
"noImplicitThis": true,
|
|
507
|
+
"alwaysStrict": true,
|
|
508
|
+
"noUnusedLocals": false,
|
|
509
|
+
"noUnusedParameters": false,
|
|
510
|
+
"noImplicitReturns": true,
|
|
511
|
+
"noFallthroughCasesInSwitch": false,
|
|
512
|
+
"inlineSourceMap": true,
|
|
513
|
+
"inlineSources": true,
|
|
514
|
+
"experimentalDecorators": true,
|
|
515
|
+
"strictPropertyInitialization": false,
|
|
516
|
+
"skipLibCheck": true,
|
|
517
|
+
"outDir": "./dist",
|
|
518
|
+
"rootDir": "."
|
|
519
|
+
},
|
|
520
|
+
"exclude": ["node_modules", "cdk.out"]
|
|
521
|
+
}
|
|
522
|
+
`;
|
|
523
|
+
// Register additional helpers for CDK templates
|
|
524
|
+
Handlebars.registerHelper('substring', (str, start, end) => {
|
|
525
|
+
return str?.substring(start, end) ?? '';
|
|
526
|
+
});
|
|
527
|
+
Handlebars.registerHelper('replace', (str, search, replace) => {
|
|
528
|
+
return str?.replace(new RegExp(search, 'g'), replace) ?? '';
|
|
529
|
+
});
|
|
530
|
+
Handlebars.registerHelper('dec', (num) => {
|
|
531
|
+
return num - 1;
|
|
532
|
+
});
|
|
533
|
+
export class CDKGenerator {
|
|
534
|
+
config;
|
|
535
|
+
outputDir;
|
|
536
|
+
constructor(config, outputDir) {
|
|
537
|
+
this.config = config;
|
|
538
|
+
this.outputDir = outputDir;
|
|
539
|
+
}
|
|
540
|
+
async generate() {
|
|
541
|
+
const files = [];
|
|
542
|
+
const stacks = [];
|
|
543
|
+
try {
|
|
544
|
+
// Create directory structure
|
|
545
|
+
this.createDirectories();
|
|
546
|
+
// Determine which stacks to generate
|
|
547
|
+
const stackFlags = {
|
|
548
|
+
network: this.hasNetworkResources(),
|
|
549
|
+
database: this.hasDatabaseResources(),
|
|
550
|
+
storage: this.hasStorageResources(),
|
|
551
|
+
compute: this.hasComputeResources(),
|
|
552
|
+
};
|
|
553
|
+
// Create template context
|
|
554
|
+
const context = {
|
|
555
|
+
projectName: this.config.projectName,
|
|
556
|
+
region: this.config.region,
|
|
557
|
+
account: this.config.account,
|
|
558
|
+
environment: this.config.environment || 'default',
|
|
559
|
+
stacks: stackFlags,
|
|
560
|
+
config: this.config,
|
|
561
|
+
};
|
|
562
|
+
// Generate CDK app
|
|
563
|
+
const appContent = templateEngine.renderString(CDK_APP_TEMPLATE, context);
|
|
564
|
+
const appPath = path.join(this.outputDir, 'bin', 'app.ts');
|
|
565
|
+
fs.writeFileSync(appPath, appContent);
|
|
566
|
+
files.push(appPath);
|
|
567
|
+
// Generate stack files
|
|
568
|
+
const now = new Date().toISOString();
|
|
569
|
+
if (stackFlags.network) {
|
|
570
|
+
const networkContext = {
|
|
571
|
+
...context,
|
|
572
|
+
vpcs: (this.config.network.vpcs || []).map((vpc, i) => ({
|
|
573
|
+
...vpc,
|
|
574
|
+
isFirst: i === 0,
|
|
575
|
+
})),
|
|
576
|
+
apiGateways: this.config.network.apiGateways || [],
|
|
577
|
+
};
|
|
578
|
+
const networkContent = templateEngine.renderString(NETWORK_STACK_TEMPLATE, networkContext);
|
|
579
|
+
const networkPath = path.join(this.outputDir, 'lib', 'stacks', 'network-stack.ts');
|
|
580
|
+
fs.writeFileSync(networkPath, networkContent);
|
|
581
|
+
files.push(networkPath);
|
|
582
|
+
stacks.push({
|
|
583
|
+
name: 'NetworkStack',
|
|
584
|
+
path: networkPath,
|
|
585
|
+
type: 'network',
|
|
586
|
+
generatedAt: now,
|
|
587
|
+
contentHash: this.hashContent(networkContent),
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
if (stackFlags.database) {
|
|
591
|
+
const dbContext = {
|
|
592
|
+
...context,
|
|
593
|
+
rdsInstances: this.config.database.rdsInstances || [],
|
|
594
|
+
auroraClusters: this.config.database.auroraClusters || [],
|
|
595
|
+
dynamoDBTables: this.config.database.dynamoDBTables || [],
|
|
596
|
+
};
|
|
597
|
+
const dbContent = templateEngine.renderString(DATABASE_STACK_TEMPLATE, dbContext);
|
|
598
|
+
const dbPath = path.join(this.outputDir, 'lib', 'stacks', 'database-stack.ts');
|
|
599
|
+
fs.writeFileSync(dbPath, dbContent);
|
|
600
|
+
files.push(dbPath);
|
|
601
|
+
stacks.push({
|
|
602
|
+
name: 'DatabaseStack',
|
|
603
|
+
path: dbPath,
|
|
604
|
+
type: 'database',
|
|
605
|
+
generatedAt: now,
|
|
606
|
+
contentHash: this.hashContent(dbContent),
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
if (stackFlags.storage) {
|
|
610
|
+
const storageContext = {
|
|
611
|
+
...context,
|
|
612
|
+
s3Buckets: this.config.storage.s3Buckets || [],
|
|
613
|
+
ecrRepositories: this.config.storage.ecrRepositories || [],
|
|
614
|
+
};
|
|
615
|
+
const storageContent = templateEngine.renderString(STORAGE_STACK_TEMPLATE, storageContext);
|
|
616
|
+
const storagePath = path.join(this.outputDir, 'lib', 'stacks', 'storage-stack.ts');
|
|
617
|
+
fs.writeFileSync(storagePath, storageContent);
|
|
618
|
+
files.push(storagePath);
|
|
619
|
+
stacks.push({
|
|
620
|
+
name: 'StorageStack',
|
|
621
|
+
path: storagePath,
|
|
622
|
+
type: 'storage',
|
|
623
|
+
generatedAt: now,
|
|
624
|
+
contentHash: this.hashContent(storageContent),
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
if (stackFlags.compute) {
|
|
628
|
+
const computeContext = {
|
|
629
|
+
...context,
|
|
630
|
+
ec2Instances: this.config.compute.ec2Instances || [],
|
|
631
|
+
lambdaFunctions: this.config.compute.lambdaFunctions || [],
|
|
632
|
+
ecsClusters: this.config.compute.ecsClusters || [],
|
|
633
|
+
ecsServices: this.config.compute.ecsServices || [],
|
|
634
|
+
eksClusters: this.config.compute.eksClusters || [],
|
|
635
|
+
};
|
|
636
|
+
const computeContent = templateEngine.renderString(COMPUTE_STACK_TEMPLATE, computeContext);
|
|
637
|
+
const computePath = path.join(this.outputDir, 'lib', 'stacks', 'compute-stack.ts');
|
|
638
|
+
fs.writeFileSync(computePath, computeContent);
|
|
639
|
+
files.push(computePath);
|
|
640
|
+
stacks.push({
|
|
641
|
+
name: 'ComputeStack',
|
|
642
|
+
path: computePath,
|
|
643
|
+
type: 'compute',
|
|
644
|
+
generatedAt: now,
|
|
645
|
+
contentHash: this.hashContent(computeContent),
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
// Generate config files
|
|
649
|
+
const packageJsonContent = templateEngine.renderString(PACKAGE_JSON_TEMPLATE, context);
|
|
650
|
+
const packageJsonPath = path.join(this.outputDir, 'package.json');
|
|
651
|
+
fs.writeFileSync(packageJsonPath, packageJsonContent);
|
|
652
|
+
files.push(packageJsonPath);
|
|
653
|
+
const cdkJsonContent = templateEngine.renderString(CDK_JSON_TEMPLATE, context);
|
|
654
|
+
const cdkJsonPath = path.join(this.outputDir, 'cdk.json');
|
|
655
|
+
fs.writeFileSync(cdkJsonPath, cdkJsonContent);
|
|
656
|
+
files.push(cdkJsonPath);
|
|
657
|
+
const tsconfigContent = templateEngine.renderString(TSCONFIG_TEMPLATE, context);
|
|
658
|
+
const tsconfigPath = path.join(this.outputDir, 'tsconfig.json');
|
|
659
|
+
fs.writeFileSync(tsconfigPath, tsconfigContent);
|
|
660
|
+
files.push(tsconfigPath);
|
|
661
|
+
// Create README
|
|
662
|
+
const readmeContent = this.generateReadme(context, stackFlags);
|
|
663
|
+
const readmePath = path.join(this.outputDir, 'README.md');
|
|
664
|
+
fs.writeFileSync(readmePath, readmeContent);
|
|
665
|
+
files.push(readmePath);
|
|
666
|
+
return {
|
|
667
|
+
success: true,
|
|
668
|
+
outputDir: this.outputDir,
|
|
669
|
+
stacks,
|
|
670
|
+
files,
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
catch (error) {
|
|
674
|
+
return {
|
|
675
|
+
success: false,
|
|
676
|
+
outputDir: this.outputDir,
|
|
677
|
+
stacks: [],
|
|
678
|
+
files: [],
|
|
679
|
+
error: error instanceof Error ? error.message : String(error),
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
createDirectories() {
|
|
684
|
+
const dirs = [
|
|
685
|
+
this.outputDir,
|
|
686
|
+
path.join(this.outputDir, 'bin'),
|
|
687
|
+
path.join(this.outputDir, 'lib'),
|
|
688
|
+
path.join(this.outputDir, 'lib', 'stacks'),
|
|
689
|
+
];
|
|
690
|
+
for (const dir of dirs) {
|
|
691
|
+
if (!fs.existsSync(dir)) {
|
|
692
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
hasNetworkResources() {
|
|
697
|
+
return ((this.config.network.vpcs?.length ?? 0) > 0 ||
|
|
698
|
+
(this.config.network.apiGateways?.length ?? 0) > 0);
|
|
699
|
+
}
|
|
700
|
+
hasDatabaseResources() {
|
|
701
|
+
return ((this.config.database.rdsInstances?.length ?? 0) > 0 ||
|
|
702
|
+
(this.config.database.auroraClusters?.length ?? 0) > 0 ||
|
|
703
|
+
(this.config.database.dynamoDBTables?.length ?? 0) > 0);
|
|
704
|
+
}
|
|
705
|
+
hasStorageResources() {
|
|
706
|
+
return ((this.config.storage.s3Buckets?.length ?? 0) > 0 ||
|
|
707
|
+
(this.config.storage.ecrRepositories?.length ?? 0) > 0);
|
|
708
|
+
}
|
|
709
|
+
hasComputeResources() {
|
|
710
|
+
return ((this.config.compute.ec2Instances?.length ?? 0) > 0 ||
|
|
711
|
+
(this.config.compute.lambdaFunctions?.length ?? 0) > 0 ||
|
|
712
|
+
(this.config.compute.ecsClusters?.length ?? 0) > 0 ||
|
|
713
|
+
(this.config.compute.ecsServices?.length ?? 0) > 0 ||
|
|
714
|
+
(this.config.compute.eksClusters?.length ?? 0) > 0);
|
|
715
|
+
}
|
|
716
|
+
hashContent(content) {
|
|
717
|
+
const crypto = require('crypto');
|
|
718
|
+
return crypto.createHash('md5').update(content).digest('hex');
|
|
719
|
+
}
|
|
720
|
+
generateReadme(context, stacks) {
|
|
721
|
+
const activeStacks = Object.entries(stacks)
|
|
722
|
+
.filter(([, active]) => active)
|
|
723
|
+
.map(([name]) => name);
|
|
724
|
+
return `# ${context.projectName} CDK Infrastructure
|
|
725
|
+
|
|
726
|
+
AWS CDK 인프라 프로젝트입니다. AWS Infra MCP로 자동 생성되었습니다.
|
|
727
|
+
|
|
728
|
+
## 구조
|
|
729
|
+
|
|
730
|
+
\`\`\`
|
|
731
|
+
${context.projectName}-cdk/
|
|
732
|
+
├── bin/
|
|
733
|
+
│ └── app.ts # CDK 앱 진입점
|
|
734
|
+
├── lib/
|
|
735
|
+
│ └── stacks/
|
|
736
|
+
${activeStacks.map(s => `│ └── ${s}-stack.ts`).join('\n')}
|
|
737
|
+
├── cdk.json
|
|
738
|
+
├── package.json
|
|
739
|
+
└── tsconfig.json
|
|
740
|
+
\`\`\`
|
|
741
|
+
|
|
742
|
+
## 생성된 스택
|
|
743
|
+
|
|
744
|
+
${activeStacks.map(s => `- **${s.charAt(0).toUpperCase() + s.slice(1)}Stack**: ${this.getStackDescription(s)}`).join('\n')}
|
|
745
|
+
|
|
746
|
+
## 배포 방법
|
|
747
|
+
|
|
748
|
+
\`\`\`bash
|
|
749
|
+
# 의존성 설치
|
|
750
|
+
npm install
|
|
751
|
+
|
|
752
|
+
# CDK 부트스트랩 (최초 1회)
|
|
753
|
+
npx cdk bootstrap
|
|
754
|
+
|
|
755
|
+
# 변경사항 확인
|
|
756
|
+
npx cdk diff
|
|
757
|
+
|
|
758
|
+
# 모든 스택 배포
|
|
759
|
+
npx cdk deploy --all
|
|
760
|
+
|
|
761
|
+
# 특정 스택만 배포
|
|
762
|
+
npx cdk deploy ${context.projectName}NetworkStack
|
|
763
|
+
\`\`\`
|
|
764
|
+
|
|
765
|
+
## 삭제
|
|
766
|
+
|
|
767
|
+
\`\`\`bash
|
|
768
|
+
npx cdk destroy --all
|
|
769
|
+
\`\`\`
|
|
770
|
+
|
|
771
|
+
## 환경 변수
|
|
772
|
+
|
|
773
|
+
- \`CDK_DEFAULT_ACCOUNT\`: AWS 계정 ID (기본값: ${context.account || 'unknown'})
|
|
774
|
+
- \`CDK_DEFAULT_REGION\`: AWS 리전 (기본값: ${context.region})
|
|
775
|
+
|
|
776
|
+
---
|
|
777
|
+
🤖 Generated with [AWS Infra MCP](https://github.com/frontpoint/aws-infra-mcp)
|
|
778
|
+
`;
|
|
779
|
+
}
|
|
780
|
+
getStackDescription(stackType) {
|
|
781
|
+
const descriptions = {
|
|
782
|
+
network: 'VPC, 서브넷, NAT Gateway, API Gateway',
|
|
783
|
+
database: 'RDS, Aurora, DynamoDB',
|
|
784
|
+
storage: 'S3, ECR',
|
|
785
|
+
compute: 'EC2, Lambda, ECS, EKS',
|
|
786
|
+
};
|
|
787
|
+
return descriptions[stackType] || stackType;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
//# sourceMappingURL=cdk-generator.js.map
|