cdk-cost-analyzer 0.1.1
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/.cdk-cost-analyzer-cache/metadata.json +12 -0
- package/.gitlab-ci.yml +214 -0
- package/.husky/pre-commit +12 -0
- package/.kiro/hooks/accessibility-audit.kiro.hook +18 -0
- package/.kiro/hooks/api-schema-validation.kiro.hook +21 -0
- package/.kiro/hooks/auto-test-on-save.kiro.hook +19 -0
- package/.kiro/hooks/cdk-synth-on-change.kiro.hook +20 -0
- package/.kiro/hooks/code-coverage-check.kiro.hook +14 -0
- package/.kiro/hooks/commit-message-helper.kiro.hook +14 -0
- package/.kiro/hooks/dependency-update-check.kiro.hook +14 -0
- package/.kiro/hooks/env-file-validation.kiro.hook +18 -0
- package/.kiro/hooks/lint-and-format-on-save.kiro.hook +21 -0
- package/.kiro/hooks/mcp-config-validation.kiro.hook +17 -0
- package/.kiro/hooks/mcp-server-test.kiro.hook +14 -0
- package/.kiro/hooks/performance-analysis.kiro.hook +14 -0
- package/.kiro/hooks/readme-spell-check.kiro.hook +14 -0
- package/.kiro/hooks/security-scan-on-dependency-change.kiro.hook +21 -0
- package/.kiro/hooks/translation-update.kiro.hook +18 -0
- package/.kiro/hooks/update-documentation.kiro.hook +18 -0
- package/.kiro/settings/mcp.json +20 -0
- package/.kiro/specs/cdk-cost-analyzer/design.md +620 -0
- package/.kiro/specs/cdk-cost-analyzer/requirements.md +183 -0
- package/.kiro/specs/cdk-cost-analyzer/tasks.md +357 -0
- package/.kiro/specs/github-actions-ci/design.md +281 -0
- package/.kiro/specs/github-actions-ci/requirements.md +86 -0
- package/.kiro/specs/github-actions-ci/tasks.md +115 -0
- package/.kiro/specs/nlb-calculator-test-coverage/design.md +190 -0
- package/.kiro/specs/nlb-calculator-test-coverage/requirements.md +84 -0
- package/.kiro/specs/nlb-calculator-test-coverage/tasks.md +150 -0
- package/.kiro/specs/production-readiness/design.md +1213 -0
- package/.kiro/specs/production-readiness/requirements.md +312 -0
- package/.kiro/specs/production-readiness/tasks.md +269 -0
- package/.kiro/specs/repository-cleanup/design.md +283 -0
- package/.kiro/specs/repository-cleanup/requirements.md +74 -0
- package/.kiro/specs/repository-cleanup/tasks.md +64 -0
- package/.kiro/steering/aws-cli-best-practices.md +41 -0
- package/.kiro/steering/cdk-best-practices.md +49 -0
- package/.kiro/steering/development-standards.md +54 -0
- package/.kiro/steering/docker-best-practices.md +34 -0
- package/.kiro/steering/documentation-style.md +151 -0
- package/.kiro/steering/git-best-practices.md +37 -0
- package/.kiro/steering/mcp-best-practices.md +95 -0
- package/.kiro/steering/python-best-practices.md +48 -0
- package/.kiro/steering/react-best-practices.md +44 -0
- package/.kiro/steering/security-best-practices.md +41 -0
- package/.kiro/steering/testing-best-practices.md +59 -0
- package/.kiro/steering/typescript-best-practices.md +40 -0
- package/CHANGELOG.md +49 -0
- package/CONTRIBUTING.md +258 -0
- package/LICENSE +19 -0
- package/README.md +480 -0
- package/SECURITY.md +117 -0
- package/dist/api/index.d.ts +11 -0
- package/dist/api/index.js +65 -0
- package/dist/api/types.d.ts +15 -0
- package/dist/api/types.js +3 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +262 -0
- package/dist/config/ConfigManager.d.ts +40 -0
- package/dist/config/ConfigManager.js +238 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +19 -0
- package/dist/config/types.d.ts +72 -0
- package/dist/config/types.js +15 -0
- package/dist/diff/DiffEngine.d.ts +7 -0
- package/dist/diff/DiffEngine.js +73 -0
- package/dist/diff/index.d.ts +2 -0
- package/dist/diff/index.js +21 -0
- package/dist/diff/types.d.ts +20 -0
- package/dist/diff/types.js +3 -0
- package/dist/integrations/GitLabIntegration.d.ts +7 -0
- package/dist/integrations/GitLabIntegration.js +45 -0
- package/dist/integrations/index.d.ts +2 -0
- package/dist/integrations/index.js +21 -0
- package/dist/integrations/types.d.ts +11 -0
- package/dist/integrations/types.js +13 -0
- package/dist/parser/TemplateParser.d.ts +8 -0
- package/dist/parser/TemplateParser.js +75 -0
- package/dist/parser/index.d.ts +2 -0
- package/dist/parser/index.js +22 -0
- package/dist/parser/types.d.ts +30 -0
- package/dist/parser/types.js +3 -0
- package/dist/pipeline/PipelineOrchestrator.d.ts +23 -0
- package/dist/pipeline/PipelineOrchestrator.js +191 -0
- package/dist/pipeline/index.d.ts +2 -0
- package/dist/pipeline/index.js +19 -0
- package/dist/pipeline/types.d.ts +41 -0
- package/dist/pipeline/types.js +13 -0
- package/dist/pricing/CacheManager.d.ts +75 -0
- package/dist/pricing/CacheManager.js +195 -0
- package/dist/pricing/PricingClient.d.ts +17 -0
- package/dist/pricing/PricingClient.js +122 -0
- package/dist/pricing/PricingService.d.ts +16 -0
- package/dist/pricing/PricingService.js +149 -0
- package/dist/pricing/calculators/ALBCalculator.d.ts +16 -0
- package/dist/pricing/calculators/ALBCalculator.js +163 -0
- package/dist/pricing/calculators/APIGatewayCalculator.d.ts +10 -0
- package/dist/pricing/calculators/APIGatewayCalculator.js +177 -0
- package/dist/pricing/calculators/CloudFrontCalculator.d.ts +59 -0
- package/dist/pricing/calculators/CloudFrontCalculator.js +151 -0
- package/dist/pricing/calculators/DynamoDBCalculator.d.ts +9 -0
- package/dist/pricing/calculators/DynamoDBCalculator.js +146 -0
- package/dist/pricing/calculators/EC2Calculator.d.ts +7 -0
- package/dist/pricing/calculators/EC2Calculator.js +80 -0
- package/dist/pricing/calculators/ECSCalculator.d.ts +9 -0
- package/dist/pricing/calculators/ECSCalculator.js +116 -0
- package/dist/pricing/calculators/ElastiCacheCalculator.d.ts +8 -0
- package/dist/pricing/calculators/ElastiCacheCalculator.js +106 -0
- package/dist/pricing/calculators/LambdaCalculator.d.ts +13 -0
- package/dist/pricing/calculators/LambdaCalculator.js +111 -0
- package/dist/pricing/calculators/NLBCalculator.d.ts +16 -0
- package/dist/pricing/calculators/NLBCalculator.js +138 -0
- package/dist/pricing/calculators/NatGatewayCalculator.d.ts +12 -0
- package/dist/pricing/calculators/NatGatewayCalculator.js +116 -0
- package/dist/pricing/calculators/RDSCalculator.d.ts +9 -0
- package/dist/pricing/calculators/RDSCalculator.js +103 -0
- package/dist/pricing/calculators/S3Calculator.d.ts +8 -0
- package/dist/pricing/calculators/S3Calculator.js +68 -0
- package/dist/pricing/calculators/VPCEndpointCalculator.d.ts +12 -0
- package/dist/pricing/calculators/VPCEndpointCalculator.js +129 -0
- package/dist/pricing/index.d.ts +10 -0
- package/dist/pricing/index.js +37 -0
- package/dist/pricing/types.d.ts +53 -0
- package/dist/pricing/types.js +22 -0
- package/dist/releasetag.txt +1 -0
- package/dist/reporter/Reporter.d.ts +18 -0
- package/dist/reporter/Reporter.js +412 -0
- package/dist/reporter/index.d.ts +2 -0
- package/dist/reporter/index.js +21 -0
- package/dist/reporter/types.d.ts +72 -0
- package/dist/reporter/types.js +3 -0
- package/dist/synthesis/SynthesisOrchestrator.d.ts +26 -0
- package/dist/synthesis/SynthesisOrchestrator.js +243 -0
- package/dist/synthesis/index.d.ts +2 -0
- package/dist/synthesis/index.js +19 -0
- package/dist/synthesis/types.d.ts +17 -0
- package/dist/synthesis/types.js +13 -0
- package/dist/threshold/ThresholdEnforcer.d.ts +29 -0
- package/dist/threshold/ThresholdEnforcer.js +143 -0
- package/dist/threshold/index.d.ts +2 -0
- package/dist/threshold/index.js +19 -0
- package/dist/threshold/types.d.ts +15 -0
- package/dist/threshold/types.js +17 -0
- package/docs/CALCULATORS.md +820 -0
- package/docs/CI_CD.md +608 -0
- package/docs/CONFIGURATION.md +407 -0
- package/docs/DEVELOPMENT.md +387 -0
- package/docs/RELEASE.md +223 -0
- package/docs/TROUBLESHOOTING.md +847 -0
- package/examples/.cdk-cost-analyzer.yml +85 -0
- package/examples/.gitlab-ci.yml +125 -0
- package/examples/api-usage.js +26 -0
- package/examples/complex/base.json +16 -0
- package/examples/complex/target.json +29 -0
- package/examples/monorepo/.gitlab-ci.yml +251 -0
- package/examples/monorepo/README.md +341 -0
- package/examples/monorepo/package.json +27 -0
- package/examples/monorepo/packages/backend-infra/.cdk-cost-analyzer.yml +34 -0
- package/examples/monorepo/packages/backend-infra/bin/app.ts +16 -0
- package/examples/monorepo/packages/backend-infra/cdk.json +7 -0
- package/examples/monorepo/packages/backend-infra/lib/backend-stack.ts +128 -0
- package/examples/monorepo/packages/backend-infra/package.json +30 -0
- package/examples/monorepo/packages/backend-infra/tsconfig.json +11 -0
- package/examples/monorepo/packages/data-infra/.cdk-cost-analyzer.yml +38 -0
- package/examples/monorepo/packages/data-infra/bin/app.ts +16 -0
- package/examples/monorepo/packages/data-infra/cdk.json +7 -0
- package/examples/monorepo/packages/data-infra/lib/data-stack.ts +121 -0
- package/examples/monorepo/packages/data-infra/package.json +30 -0
- package/examples/monorepo/packages/data-infra/tsconfig.json +11 -0
- package/examples/monorepo/packages/frontend-infra/.cdk-cost-analyzer.yml +31 -0
- package/examples/monorepo/packages/frontend-infra/bin/app.ts +16 -0
- package/examples/monorepo/packages/frontend-infra/cdk.json +7 -0
- package/examples/monorepo/packages/frontend-infra/lib/frontend-stack.ts +60 -0
- package/examples/monorepo/packages/frontend-infra/package.json +30 -0
- package/examples/monorepo/packages/frontend-infra/tsconfig.json +11 -0
- package/examples/monorepo/tsconfig.json +35 -0
- package/examples/multi-stack/.cdk-cost-analyzer.yml +72 -0
- package/examples/multi-stack/.gitlab-ci.yml +184 -0
- package/examples/multi-stack/README.md +279 -0
- package/examples/multi-stack/bin/app.ts +36 -0
- package/examples/multi-stack/cdk.json +72 -0
- package/examples/multi-stack/lib/compute-stack.ts +128 -0
- package/examples/multi-stack/lib/networking-stack.ts +69 -0
- package/examples/multi-stack/lib/storage-stack.ts +141 -0
- package/examples/multi-stack/package-lock.json +4437 -0
- package/examples/multi-stack/package.json +42 -0
- package/examples/multi-stack/tsconfig.json +34 -0
- package/examples/simple/base.json +8 -0
- package/examples/simple/target.json +14 -0
- package/examples/single-stack/.NVP +0 -0
- package/examples/single-stack/.cdk-cost-analyzer.yml +52 -0
- package/examples/single-stack/.gitlab-ci.yml +126 -0
- package/examples/single-stack/README.md +184 -0
- package/examples/single-stack/UeK +0 -0
- package/examples/single-stack/bin/app.ts +16 -0
- package/examples/single-stack/cdk.json +72 -0
- package/examples/single-stack/lib/infrastructure-stack.ts +119 -0
- package/examples/single-stack/package-lock.json +4443 -0
- package/examples/single-stack/package.json +38 -0
- package/examples/single-stack/tsconfig.json +34 -0
- package/package.json +139 -0
- package/test-cdk-project/README-COMPUTE.md +141 -0
- package/test-cdk-project/README.md +95 -0
- package/test-cdk-project/app-with-compute.js +102 -0
- package/test-cdk-project/app.js +81 -0
- package/test-cdk-project/cdk-compute.json +3 -0
- package/test-cdk-project/cdk.context.json +7 -0
- package/test-cdk-project/cdk.json +3 -0
- package/test-cdk-project/cdk.out/TestStack.assets.json +21 -0
- package/test-cdk-project/cdk.out/TestStack.template.json +115 -0
- package/test-cdk-project/cdk.out/cdk.out +1 -0
- package/test-cdk-project/cdk.out/manifest.json +503 -0
- package/test-cdk-project/cdk.out/tree.json +1 -0
- package/test-cdk-project/cdk.out.base/TestStack.assets.json +21 -0
- package/test-cdk-project/cdk.out.base/TestStack.template.json +115 -0
- package/test-cdk-project/cdk.out.base/cdk.out +1 -0
- package/test-cdk-project/cdk.out.base/manifest.json +503 -0
- package/test-cdk-project/cdk.out.base/tree.json +1 -0
- package/test-cdk-project/cdk.out.target/TestStack.assets.json +21 -0
- package/test-cdk-project/cdk.out.target/TestStack.template.json +183 -0
- package/test-cdk-project/cdk.out.target/cdk.out +1 -0
- package/test-cdk-project/cdk.out.target/manifest.json +521 -0
- package/test-cdk-project/cdk.out.target/tree.json +1 -0
- package/test-cdk-project/package-lock.json +422 -0
- package/test-cdk-project/package.json +17 -0
- package/tools/workflows/README.md +102 -0
- package/tools/workflows/validate-workflows.js +109 -0
- package/tools/workflows/workflow-utils.ts +181 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
3
|
+
import * as rds from 'aws-cdk-lib/aws-rds';
|
|
4
|
+
import * as elasticache from 'aws-cdk-lib/aws-elasticache';
|
|
5
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
6
|
+
import { Construct } from 'constructs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Data infrastructure stack
|
|
10
|
+
*
|
|
11
|
+
* Creates RDS database, ElastiCache cluster, and S3 bucket for data storage
|
|
12
|
+
*/
|
|
13
|
+
export class DataStack extends cdk.Stack {
|
|
14
|
+
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
|
|
15
|
+
super(scope, id, props);
|
|
16
|
+
|
|
17
|
+
// VPC for data resources
|
|
18
|
+
const vpc = new ec2.Vpc(this, 'DataVpc', {
|
|
19
|
+
vpcName: 'data-vpc',
|
|
20
|
+
maxAzs: 2,
|
|
21
|
+
natGateways: 1,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Security group for database
|
|
25
|
+
const dbSecurityGroup = new ec2.SecurityGroup(this, 'DbSecurityGroup', {
|
|
26
|
+
vpc,
|
|
27
|
+
description: 'Security group for RDS database',
|
|
28
|
+
allowAllOutbound: false,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// RDS PostgreSQL Database
|
|
32
|
+
const database = new rds.DatabaseInstance(this, 'Database', {
|
|
33
|
+
engine: rds.DatabaseInstanceEngine.postgres({
|
|
34
|
+
version: rds.PostgresEngineVersion.VER_15_3,
|
|
35
|
+
}),
|
|
36
|
+
instanceType: ec2.InstanceType.of(
|
|
37
|
+
ec2.InstanceClass.T3,
|
|
38
|
+
ec2.InstanceSize.MEDIUM
|
|
39
|
+
),
|
|
40
|
+
vpc,
|
|
41
|
+
vpcSubnets: {
|
|
42
|
+
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
|
|
43
|
+
},
|
|
44
|
+
securityGroups: [dbSecurityGroup],
|
|
45
|
+
allocatedStorage: 100,
|
|
46
|
+
storageType: rds.StorageType.GP3,
|
|
47
|
+
multiAz: false,
|
|
48
|
+
databaseName: 'datadb',
|
|
49
|
+
backupRetention: cdk.Duration.days(7),
|
|
50
|
+
deleteAutomatedBackups: true,
|
|
51
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
52
|
+
deletionProtection: false,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Security group for cache
|
|
56
|
+
const cacheSecurityGroup = new ec2.SecurityGroup(this, 'CacheSecurityGroup', {
|
|
57
|
+
vpc,
|
|
58
|
+
description: 'Security group for ElastiCache',
|
|
59
|
+
allowAllOutbound: false,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// ElastiCache subnet group
|
|
63
|
+
const cacheSubnetGroup = new elasticache.CfnSubnetGroup(this, 'CacheSubnetGroup', {
|
|
64
|
+
description: 'Subnet group for ElastiCache',
|
|
65
|
+
subnetIds: vpc.selectSubnets({
|
|
66
|
+
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
|
|
67
|
+
}).subnetIds,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// ElastiCache Redis Cluster
|
|
71
|
+
const cacheCluster = new elasticache.CfnCacheCluster(this, 'CacheCluster', {
|
|
72
|
+
cacheNodeType: 'cache.t3.micro',
|
|
73
|
+
engine: 'redis',
|
|
74
|
+
numCacheNodes: 2,
|
|
75
|
+
vpcSecurityGroupIds: [cacheSecurityGroup.securityGroupId],
|
|
76
|
+
cacheSubnetGroupName: cacheSubnetGroup.ref,
|
|
77
|
+
engineVersion: '7.0',
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// S3 bucket for data storage
|
|
81
|
+
const dataBucket = new s3.Bucket(this, 'DataBucket', {
|
|
82
|
+
bucketName: `${cdk.Stack.of(this).account}-data-storage-${cdk.Stack.of(this).region}`,
|
|
83
|
+
versioned: true,
|
|
84
|
+
encryption: s3.BucketEncryption.S3_MANAGED,
|
|
85
|
+
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
86
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
87
|
+
autoDeleteObjects: true,
|
|
88
|
+
lifecycleRules: [
|
|
89
|
+
{
|
|
90
|
+
id: 'DeleteOldVersions',
|
|
91
|
+
noncurrentVersionExpiration: cdk.Duration.days(90),
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'TransitionToGlacier',
|
|
95
|
+
transitions: [
|
|
96
|
+
{
|
|
97
|
+
storageClass: s3.StorageClass.GLACIER,
|
|
98
|
+
transitionAfter: cdk.Duration.days(90),
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Stack outputs
|
|
106
|
+
new cdk.CfnOutput(this, 'DatabaseEndpoint', {
|
|
107
|
+
value: database.dbInstanceEndpointAddress,
|
|
108
|
+
description: 'RDS database endpoint',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
new cdk.CfnOutput(this, 'CacheEndpoint', {
|
|
112
|
+
value: cacheCluster.attrRedisEndpointAddress,
|
|
113
|
+
description: 'ElastiCache Redis endpoint',
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
new cdk.CfnOutput(this, 'DataBucketName', {
|
|
117
|
+
value: dataBucket.bucketName,
|
|
118
|
+
description: 'S3 data bucket name',
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "data-infra",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Data infrastructure CDK application",
|
|
5
|
+
"bin": {
|
|
6
|
+
"data-infra": "bin/app.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"watch": "tsc -w",
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"cdk": "cdk",
|
|
13
|
+
"synth": "cdk synth",
|
|
14
|
+
"deploy": "cdk deploy",
|
|
15
|
+
"clean": "rm -rf cdk.out node_modules"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/jest": "^29.5.14",
|
|
19
|
+
"@types/node": "^22.10.2",
|
|
20
|
+
"aws-cdk": "^2.232.1",
|
|
21
|
+
"jest": "^29.7.0",
|
|
22
|
+
"ts-jest": "^29.2.5",
|
|
23
|
+
"ts-node": "^10.9.2",
|
|
24
|
+
"typescript": "^5.7.2"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"aws-cdk-lib": "^2.232.1",
|
|
28
|
+
"constructs": "^10.4.2"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# CDK Cost Analyzer Configuration for Frontend Infrastructure
|
|
2
|
+
|
|
3
|
+
thresholds:
|
|
4
|
+
default:
|
|
5
|
+
warning: 30 # USD per month
|
|
6
|
+
error: 100 # USD per month
|
|
7
|
+
|
|
8
|
+
usageAssumptions:
|
|
9
|
+
s3:
|
|
10
|
+
storageGB: 50
|
|
11
|
+
getRequests: 100000
|
|
12
|
+
putRequests: 5000
|
|
13
|
+
dataTransferGB: 100
|
|
14
|
+
|
|
15
|
+
cloudfront:
|
|
16
|
+
dataTransferGB: 200
|
|
17
|
+
requests: 5000000
|
|
18
|
+
|
|
19
|
+
synthesis:
|
|
20
|
+
appPath: .
|
|
21
|
+
outputPath: cdk.out
|
|
22
|
+
|
|
23
|
+
exclusions:
|
|
24
|
+
resourceTypes:
|
|
25
|
+
- AWS::IAM::Role
|
|
26
|
+
- AWS::IAM::Policy
|
|
27
|
+
- AWS::CertificateManager::Certificate
|
|
28
|
+
|
|
29
|
+
cache:
|
|
30
|
+
enabled: true
|
|
31
|
+
durationHours: 24
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import 'source-map-support/register';
|
|
3
|
+
import * as cdk from 'aws-cdk-lib';
|
|
4
|
+
import { FrontendStack } from '../lib/frontend-stack';
|
|
5
|
+
|
|
6
|
+
const app = new cdk.App();
|
|
7
|
+
|
|
8
|
+
new FrontendStack(app, 'FrontendStack', {
|
|
9
|
+
env: {
|
|
10
|
+
account: process.env.CDK_DEFAULT_ACCOUNT,
|
|
11
|
+
region: process.env.CDK_DEFAULT_REGION || 'us-east-1',
|
|
12
|
+
},
|
|
13
|
+
description: 'Monorepo example - Frontend infrastructure (S3, CloudFront)',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
app.synth();
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
3
|
+
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
|
|
4
|
+
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
|
|
5
|
+
import { Construct } from 'constructs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Frontend infrastructure stack
|
|
9
|
+
*
|
|
10
|
+
* Creates S3 bucket for static website hosting and CloudFront distribution
|
|
11
|
+
*/
|
|
12
|
+
export class FrontendStack extends cdk.Stack {
|
|
13
|
+
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
|
|
14
|
+
super(scope, id, props);
|
|
15
|
+
|
|
16
|
+
// S3 bucket for static website
|
|
17
|
+
const websiteBucket = new s3.Bucket(this, 'WebsiteBucket', {
|
|
18
|
+
bucketName: `${cdk.Stack.of(this).account}-frontend-${cdk.Stack.of(this).region}`,
|
|
19
|
+
websiteIndexDocument: 'index.html',
|
|
20
|
+
websiteErrorDocument: 'error.html',
|
|
21
|
+
publicReadAccess: false,
|
|
22
|
+
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
23
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
24
|
+
autoDeleteObjects: true,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// CloudFront distribution
|
|
28
|
+
const distribution = new cloudfront.Distribution(this, 'Distribution', {
|
|
29
|
+
defaultBehavior: {
|
|
30
|
+
origin: new origins.S3Origin(websiteBucket),
|
|
31
|
+
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
32
|
+
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
|
|
33
|
+
},
|
|
34
|
+
defaultRootObject: 'index.html',
|
|
35
|
+
errorResponses: [
|
|
36
|
+
{
|
|
37
|
+
httpStatus: 404,
|
|
38
|
+
responseHttpStatus: 200,
|
|
39
|
+
responsePagePath: '/index.html',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Stack outputs
|
|
45
|
+
new cdk.CfnOutput(this, 'BucketName', {
|
|
46
|
+
value: websiteBucket.bucketName,
|
|
47
|
+
description: 'S3 bucket name',
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
new cdk.CfnOutput(this, 'DistributionDomain', {
|
|
51
|
+
value: distribution.distributionDomainName,
|
|
52
|
+
description: 'CloudFront distribution domain',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
new cdk.CfnOutput(this, 'DistributionUrl', {
|
|
56
|
+
value: `https://${distribution.distributionDomainName}`,
|
|
57
|
+
description: 'CloudFront distribution URL',
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "frontend-infra",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Frontend infrastructure CDK application",
|
|
5
|
+
"bin": {
|
|
6
|
+
"frontend-infra": "bin/app.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"watch": "tsc -w",
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"cdk": "cdk",
|
|
13
|
+
"synth": "cdk synth",
|
|
14
|
+
"deploy": "cdk deploy",
|
|
15
|
+
"clean": "rm -rf cdk.out node_modules"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/jest": "^29.5.14",
|
|
19
|
+
"@types/node": "^22.10.2",
|
|
20
|
+
"aws-cdk": "^2.232.1",
|
|
21
|
+
"jest": "^29.7.0",
|
|
22
|
+
"ts-jest": "^29.2.5",
|
|
23
|
+
"ts-node": "^10.9.2",
|
|
24
|
+
"typescript": "^5.7.2"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"aws-cdk-lib": "^2.232.1",
|
|
28
|
+
"constructs": "^10.4.2"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": [
|
|
6
|
+
"es2020"
|
|
7
|
+
],
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"noImplicitAny": true,
|
|
11
|
+
"strictNullChecks": true,
|
|
12
|
+
"noImplicitThis": true,
|
|
13
|
+
"alwaysStrict": true,
|
|
14
|
+
"noUnusedLocals": false,
|
|
15
|
+
"noUnusedParameters": false,
|
|
16
|
+
"noImplicitReturns": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": false,
|
|
18
|
+
"inlineSourceMap": true,
|
|
19
|
+
"inlineSources": true,
|
|
20
|
+
"experimentalDecorators": true,
|
|
21
|
+
"strictPropertyInitialization": false,
|
|
22
|
+
"typeRoots": [
|
|
23
|
+
"./node_modules/@types"
|
|
24
|
+
],
|
|
25
|
+
"esModuleInterop": true,
|
|
26
|
+
"skipLibCheck": true,
|
|
27
|
+
"forceConsistentCasingInFileNames": true,
|
|
28
|
+
"resolveJsonModule": true
|
|
29
|
+
},
|
|
30
|
+
"exclude": [
|
|
31
|
+
"node_modules",
|
|
32
|
+
"cdk.out",
|
|
33
|
+
"dist"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# CDK Cost Analyzer Configuration for Multi-Stack Application
|
|
2
|
+
# This file configures cost thresholds and usage assumptions for cost analysis
|
|
3
|
+
|
|
4
|
+
# Cost thresholds for pipeline enforcement
|
|
5
|
+
# Note: Thresholds apply to total cost across all stacks
|
|
6
|
+
thresholds:
|
|
7
|
+
default:
|
|
8
|
+
warning: 100 # USD per month - displays warning but passes pipeline
|
|
9
|
+
error: 500 # USD per month - fails pipeline, requires review
|
|
10
|
+
|
|
11
|
+
# Custom usage assumptions for cost estimation
|
|
12
|
+
# Adjust these values to match your expected application usage
|
|
13
|
+
usageAssumptions:
|
|
14
|
+
# NAT Gateway usage (Networking Stack)
|
|
15
|
+
natGateway:
|
|
16
|
+
dataProcessedGB: 500 # Monthly data processed through NAT Gateway
|
|
17
|
+
|
|
18
|
+
# Application Load Balancer usage (Compute Stack)
|
|
19
|
+
alb:
|
|
20
|
+
newConnectionsPerSecond: 50
|
|
21
|
+
activeConnectionsPerMinute: 5000
|
|
22
|
+
processedBytesGB: 1000
|
|
23
|
+
|
|
24
|
+
# VPC Endpoint usage (Networking Stack)
|
|
25
|
+
vpcEndpoint:
|
|
26
|
+
dataProcessedGB: 100 # Monthly data processed through interface endpoints
|
|
27
|
+
|
|
28
|
+
# ECS usage (Compute Stack)
|
|
29
|
+
ecs:
|
|
30
|
+
taskCount: 2
|
|
31
|
+
cpuUnits: 512
|
|
32
|
+
memoryMB: 1024
|
|
33
|
+
hoursPerMonth: 730
|
|
34
|
+
|
|
35
|
+
# RDS usage (Storage Stack)
|
|
36
|
+
rds:
|
|
37
|
+
instanceClass: db.t3.medium
|
|
38
|
+
storageGB: 100
|
|
39
|
+
backupRetentionDays: 7
|
|
40
|
+
multiAZ: false
|
|
41
|
+
|
|
42
|
+
# ElastiCache usage (Storage Stack)
|
|
43
|
+
elasticache:
|
|
44
|
+
nodeType: cache.t3.micro
|
|
45
|
+
numNodes: 2
|
|
46
|
+
engineType: redis
|
|
47
|
+
|
|
48
|
+
# S3 usage (Storage Stack)
|
|
49
|
+
s3:
|
|
50
|
+
storageGB: 500
|
|
51
|
+
getRequests: 100000
|
|
52
|
+
putRequests: 10000
|
|
53
|
+
dataTransferGB: 100
|
|
54
|
+
|
|
55
|
+
# CDK synthesis configuration (optional)
|
|
56
|
+
synthesis:
|
|
57
|
+
appPath: . # Path to CDK application
|
|
58
|
+
outputPath: cdk.out # CDK synthesis output directory
|
|
59
|
+
|
|
60
|
+
# Resource exclusions (optional)
|
|
61
|
+
# Exclude specific resource types from cost analysis
|
|
62
|
+
exclusions:
|
|
63
|
+
resourceTypes:
|
|
64
|
+
- AWS::IAM::Role # IAM roles have no direct cost
|
|
65
|
+
- AWS::IAM::Policy # IAM policies have no direct cost
|
|
66
|
+
- AWS::EC2::SecurityGroup # Security groups have no direct cost
|
|
67
|
+
- AWS::Logs::LogGroup # CloudWatch Logs analyzed separately
|
|
68
|
+
|
|
69
|
+
# Cache configuration
|
|
70
|
+
cache:
|
|
71
|
+
enabled: true # Enable pricing data caching
|
|
72
|
+
durationHours: 24 # Cache duration in hours
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# GitLab CI/CD Pipeline with Multi-Stack CDK Cost Analysis
|
|
2
|
+
# This pipeline runs cost analysis on merge requests for multi-stack applications
|
|
3
|
+
|
|
4
|
+
stages:
|
|
5
|
+
- build
|
|
6
|
+
- test
|
|
7
|
+
- cost-analysis
|
|
8
|
+
- deploy
|
|
9
|
+
|
|
10
|
+
variables:
|
|
11
|
+
AWS_REGION: us-east-1
|
|
12
|
+
CDK_APP_PATH: examples/multi-stack
|
|
13
|
+
NODE_VERSION: "18"
|
|
14
|
+
|
|
15
|
+
# Install dependencies for the application
|
|
16
|
+
build:
|
|
17
|
+
stage: build
|
|
18
|
+
image: node:${NODE_VERSION}
|
|
19
|
+
script:
|
|
20
|
+
- echo "Installing dependencies..."
|
|
21
|
+
- npm ci
|
|
22
|
+
- cd ${CDK_APP_PATH}
|
|
23
|
+
- npm ci
|
|
24
|
+
cache:
|
|
25
|
+
key: ${CI_COMMIT_REF_SLUG}
|
|
26
|
+
paths:
|
|
27
|
+
- node_modules/
|
|
28
|
+
- ${CDK_APP_PATH}/node_modules/
|
|
29
|
+
artifacts:
|
|
30
|
+
paths:
|
|
31
|
+
- node_modules/
|
|
32
|
+
- ${CDK_APP_PATH}/node_modules/
|
|
33
|
+
expire_in: 1 hour
|
|
34
|
+
|
|
35
|
+
# Run application tests
|
|
36
|
+
test:
|
|
37
|
+
stage: test
|
|
38
|
+
image: node:${NODE_VERSION}
|
|
39
|
+
dependencies:
|
|
40
|
+
- build
|
|
41
|
+
script:
|
|
42
|
+
- cd ${CDK_APP_PATH}
|
|
43
|
+
- npm test
|
|
44
|
+
only:
|
|
45
|
+
- merge_requests
|
|
46
|
+
- main
|
|
47
|
+
|
|
48
|
+
# Analyze infrastructure cost changes for merge requests
|
|
49
|
+
# Handles multi-stack applications automatically
|
|
50
|
+
cost-analysis:
|
|
51
|
+
stage: cost-analysis
|
|
52
|
+
image: node:${NODE_VERSION}
|
|
53
|
+
dependencies:
|
|
54
|
+
- build
|
|
55
|
+
before_script:
|
|
56
|
+
# Install CDK Cost Analyzer globally
|
|
57
|
+
- npm install -g cdk-cost-analyzer
|
|
58
|
+
# Verify AWS credentials are configured
|
|
59
|
+
- |
|
|
60
|
+
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
|
|
61
|
+
echo "ERROR: AWS credentials not configured"
|
|
62
|
+
echo "Please configure AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as CI/CD variables"
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
script:
|
|
66
|
+
- echo "Analyzing infrastructure cost changes across all stacks..."
|
|
67
|
+
- cd ${CDK_APP_PATH}
|
|
68
|
+
# Run cost analysis with automatic CDK synthesis
|
|
69
|
+
# The tool automatically detects and analyzes all stacks
|
|
70
|
+
- |
|
|
71
|
+
cdk-cost-analyzer pipeline \
|
|
72
|
+
--base-branch ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME} \
|
|
73
|
+
--target-branch ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} \
|
|
74
|
+
--cdk-app-path . \
|
|
75
|
+
--region ${AWS_REGION} \
|
|
76
|
+
--format markdown \
|
|
77
|
+
--post-to-gitlab
|
|
78
|
+
cache:
|
|
79
|
+
key: pricing-cache
|
|
80
|
+
paths:
|
|
81
|
+
- .cdk-cost-analyzer-cache/
|
|
82
|
+
artifacts:
|
|
83
|
+
reports:
|
|
84
|
+
# Store cost analysis report as artifact
|
|
85
|
+
dotenv: cost-analysis.env
|
|
86
|
+
paths:
|
|
87
|
+
- cost-report.md
|
|
88
|
+
expire_in: 30 days
|
|
89
|
+
timeout: 15m # Multi-stack analysis may take longer
|
|
90
|
+
only:
|
|
91
|
+
- merge_requests
|
|
92
|
+
allow_failure: false # Fail pipeline if cost threshold exceeded
|
|
93
|
+
|
|
94
|
+
# Deploy all stacks to production (requires manual approval)
|
|
95
|
+
deploy:all:
|
|
96
|
+
stage: deploy
|
|
97
|
+
image: node:${NODE_VERSION}
|
|
98
|
+
dependencies:
|
|
99
|
+
- build
|
|
100
|
+
before_script:
|
|
101
|
+
- npm install -g aws-cdk
|
|
102
|
+
script:
|
|
103
|
+
- cd ${CDK_APP_PATH}
|
|
104
|
+
- echo "Deploying all stacks to production..."
|
|
105
|
+
- cdk deploy --all --require-approval never
|
|
106
|
+
only:
|
|
107
|
+
- main
|
|
108
|
+
when: manual
|
|
109
|
+
environment:
|
|
110
|
+
name: production
|
|
111
|
+
action: start
|
|
112
|
+
|
|
113
|
+
# Deploy individual stacks (useful for targeted updates)
|
|
114
|
+
deploy:networking:
|
|
115
|
+
stage: deploy
|
|
116
|
+
image: node:${NODE_VERSION}
|
|
117
|
+
dependencies:
|
|
118
|
+
- build
|
|
119
|
+
before_script:
|
|
120
|
+
- npm install -g aws-cdk
|
|
121
|
+
script:
|
|
122
|
+
- cd ${CDK_APP_PATH}
|
|
123
|
+
- echo "Deploying networking stack..."
|
|
124
|
+
- cdk deploy NetworkingStack --require-approval never
|
|
125
|
+
only:
|
|
126
|
+
- main
|
|
127
|
+
when: manual
|
|
128
|
+
environment:
|
|
129
|
+
name: production/networking
|
|
130
|
+
action: start
|
|
131
|
+
|
|
132
|
+
deploy:compute:
|
|
133
|
+
stage: deploy
|
|
134
|
+
image: node:${NODE_VERSION}
|
|
135
|
+
dependencies:
|
|
136
|
+
- build
|
|
137
|
+
before_script:
|
|
138
|
+
- npm install -g aws-cdk
|
|
139
|
+
script:
|
|
140
|
+
- cd ${CDK_APP_PATH}
|
|
141
|
+
- echo "Deploying compute stack..."
|
|
142
|
+
- cdk deploy ComputeStack --require-approval never
|
|
143
|
+
only:
|
|
144
|
+
- main
|
|
145
|
+
when: manual
|
|
146
|
+
environment:
|
|
147
|
+
name: production/compute
|
|
148
|
+
action: start
|
|
149
|
+
|
|
150
|
+
deploy:storage:
|
|
151
|
+
stage: deploy
|
|
152
|
+
image: node:${NODE_VERSION}
|
|
153
|
+
dependencies:
|
|
154
|
+
- build
|
|
155
|
+
before_script:
|
|
156
|
+
- npm install -g aws-cdk
|
|
157
|
+
script:
|
|
158
|
+
- cd ${CDK_APP_PATH}
|
|
159
|
+
- echo "Deploying storage stack..."
|
|
160
|
+
- cdk deploy StorageStack --require-approval never
|
|
161
|
+
only:
|
|
162
|
+
- main
|
|
163
|
+
when: manual
|
|
164
|
+
environment:
|
|
165
|
+
name: production/storage
|
|
166
|
+
action: start
|
|
167
|
+
|
|
168
|
+
# Deploy to development environment automatically
|
|
169
|
+
deploy:dev:
|
|
170
|
+
stage: deploy
|
|
171
|
+
image: node:${NODE_VERSION}
|
|
172
|
+
dependencies:
|
|
173
|
+
- build
|
|
174
|
+
before_script:
|
|
175
|
+
- npm install -g aws-cdk
|
|
176
|
+
script:
|
|
177
|
+
- cd ${CDK_APP_PATH}
|
|
178
|
+
- echo "Deploying all stacks to development environment..."
|
|
179
|
+
- cdk deploy --all --require-approval never
|
|
180
|
+
only:
|
|
181
|
+
- develop
|
|
182
|
+
environment:
|
|
183
|
+
name: development
|
|
184
|
+
action: start
|