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,341 @@
|
|
|
1
|
+
# Monorepo CDK Cost Analyzer Example
|
|
2
|
+
|
|
3
|
+
This example demonstrates how to integrate CDK Cost Analyzer into a monorepo structure with multiple independent CDK applications.
|
|
4
|
+
|
|
5
|
+
## Project Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
monorepo/
|
|
9
|
+
├── packages/
|
|
10
|
+
│ ├── frontend-infra/ # Frontend infrastructure (S3, CloudFront)
|
|
11
|
+
│ │ ├── bin/
|
|
12
|
+
│ │ ├── lib/
|
|
13
|
+
│ │ ├── .cdk-cost-analyzer.yml
|
|
14
|
+
│ │ ├── cdk.json
|
|
15
|
+
│ │ └── package.json
|
|
16
|
+
│ ├── backend-infra/ # Backend infrastructure (Lambda, API Gateway)
|
|
17
|
+
│ │ ├── bin/
|
|
18
|
+
│ │ ├── lib/
|
|
19
|
+
│ │ ├── .cdk-cost-analyzer.yml
|
|
20
|
+
│ │ ├── cdk.json
|
|
21
|
+
│ │ └── package.json
|
|
22
|
+
│ └── data-infra/ # Data infrastructure (RDS, DynamoDB)
|
|
23
|
+
│ ├── bin/
|
|
24
|
+
│ ├── lib/
|
|
25
|
+
│ ├── .cdk-cost-analyzer.yml
|
|
26
|
+
│ ├── cdk.json
|
|
27
|
+
│ └── package.json
|
|
28
|
+
├── .gitlab-ci.yml # GitLab CI pipeline with parallel analysis
|
|
29
|
+
├── package.json # Root package.json for workspace
|
|
30
|
+
└── README.md # This file
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Architecture Overview
|
|
34
|
+
|
|
35
|
+
This monorepo contains three independent CDK applications:
|
|
36
|
+
|
|
37
|
+
### Frontend Infrastructure
|
|
38
|
+
- **Amazon S3**: Static website hosting
|
|
39
|
+
- **Amazon CloudFront**: Content delivery network
|
|
40
|
+
- **AWS Certificate Manager**: SSL/TLS certificates
|
|
41
|
+
|
|
42
|
+
### Backend Infrastructure
|
|
43
|
+
- **AWS Lambda**: Serverless API functions
|
|
44
|
+
- **Amazon API Gateway**: REST API endpoints
|
|
45
|
+
- **Amazon DynamoDB**: NoSQL database
|
|
46
|
+
|
|
47
|
+
### Data Infrastructure
|
|
48
|
+
- **Amazon RDS**: PostgreSQL database
|
|
49
|
+
- **Amazon ElastiCache**: Redis cache
|
|
50
|
+
- **AWS Backup**: Automated backup solution
|
|
51
|
+
|
|
52
|
+
## Why Monorepo?
|
|
53
|
+
|
|
54
|
+
Monorepo architectures provide several benefits:
|
|
55
|
+
|
|
56
|
+
- **Code Sharing**: Share common constructs and utilities across applications
|
|
57
|
+
- **Atomic Changes**: Update multiple applications in a single commit
|
|
58
|
+
- **Consistent Tooling**: Unified build and deployment processes
|
|
59
|
+
- **Independent Deployment**: Each application can be deployed separately
|
|
60
|
+
- **Team Autonomy**: Different teams can own different applications
|
|
61
|
+
|
|
62
|
+
## Prerequisites
|
|
63
|
+
|
|
64
|
+
- Node.js 18 or later
|
|
65
|
+
- AWS CDK CLI: `npm install -g aws-cdk`
|
|
66
|
+
- AWS account with appropriate credentials
|
|
67
|
+
- GitLab repository with CI/CD enabled
|
|
68
|
+
|
|
69
|
+
## Setup Instructions
|
|
70
|
+
|
|
71
|
+
### 1. Install Dependencies
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cd examples/monorepo
|
|
75
|
+
npm install
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This installs dependencies for all packages in the workspace.
|
|
79
|
+
|
|
80
|
+
### 2. Configure AWS Credentials
|
|
81
|
+
|
|
82
|
+
For local development:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
export AWS_ACCESS_KEY_ID=your-access-key
|
|
86
|
+
export AWS_SECRET_ACCESS_KEY=your-secret-key
|
|
87
|
+
export AWS_REGION=us-east-1
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
For GitLab CI, configure these as CI/CD variables in your GitLab project settings.
|
|
91
|
+
|
|
92
|
+
### 3. Bootstrap CDK (First Time Only)
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
cdk bootstrap aws://ACCOUNT-ID/REGION
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 4. Review Configuration
|
|
99
|
+
|
|
100
|
+
Each package has its own `.cdk-cost-analyzer.yml` with application-specific thresholds and assumptions.
|
|
101
|
+
|
|
102
|
+
## Local Development
|
|
103
|
+
|
|
104
|
+
### Work with Specific Application
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Frontend infrastructure
|
|
108
|
+
cd packages/frontend-infra
|
|
109
|
+
cdk synth
|
|
110
|
+
cdk deploy
|
|
111
|
+
|
|
112
|
+
# Backend infrastructure
|
|
113
|
+
cd packages/backend-infra
|
|
114
|
+
cdk synth
|
|
115
|
+
cdk deploy
|
|
116
|
+
|
|
117
|
+
# Data infrastructure
|
|
118
|
+
cd packages/data-infra
|
|
119
|
+
cdk synth
|
|
120
|
+
cdk deploy
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Run Cost Analysis for Specific Application
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Install cost analyzer
|
|
127
|
+
npm install -g cdk-cost-analyzer
|
|
128
|
+
|
|
129
|
+
# Analyze frontend infrastructure
|
|
130
|
+
cd packages/frontend-infra
|
|
131
|
+
cdk-cost-analyzer pipeline \
|
|
132
|
+
--base-branch main \
|
|
133
|
+
--target-branch feature/my-changes \
|
|
134
|
+
--region us-east-1
|
|
135
|
+
|
|
136
|
+
# Analyze backend infrastructure
|
|
137
|
+
cd packages/backend-infra
|
|
138
|
+
cdk-cost-analyzer pipeline \
|
|
139
|
+
--base-branch main \
|
|
140
|
+
--target-branch feature/my-changes \
|
|
141
|
+
--region us-east-1
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## GitLab CI/CD Integration
|
|
145
|
+
|
|
146
|
+
The `.gitlab-ci.yml` file configures parallel cost analysis for all applications in the monorepo.
|
|
147
|
+
|
|
148
|
+
### Pipeline Stages
|
|
149
|
+
|
|
150
|
+
1. **Build**: Install dependencies for all packages
|
|
151
|
+
2. **Test**: Run tests for all packages in parallel
|
|
152
|
+
3. **Cost Analysis**: Analyze cost changes for each application in parallel
|
|
153
|
+
4. **Deploy**: Deploy applications to AWS
|
|
154
|
+
|
|
155
|
+
### Parallel Cost Analysis
|
|
156
|
+
|
|
157
|
+
The pipeline runs cost analysis for each application independently and in parallel:
|
|
158
|
+
|
|
159
|
+
```yaml
|
|
160
|
+
cost-analysis:frontend:
|
|
161
|
+
# Analyzes frontend infrastructure changes
|
|
162
|
+
|
|
163
|
+
cost-analysis:backend:
|
|
164
|
+
# Analyzes backend infrastructure changes
|
|
165
|
+
|
|
166
|
+
cost-analysis:data:
|
|
167
|
+
# Analyzes data infrastructure changes
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Each analysis job:
|
|
171
|
+
- Has its own cost thresholds
|
|
172
|
+
- Posts separate comments to merge requests
|
|
173
|
+
- Can fail independently without blocking other analyses
|
|
174
|
+
|
|
175
|
+
### Viewing Cost Reports
|
|
176
|
+
|
|
177
|
+
Each application posts its own cost analysis comment to merge requests:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
Frontend Infrastructure Cost Analysis
|
|
181
|
+
======================================
|
|
182
|
+
Total Cost Delta: +$25.00/month
|
|
183
|
+
- CloudFront: +$20.00/month
|
|
184
|
+
- S3: +$5.00/month
|
|
185
|
+
|
|
186
|
+
Backend Infrastructure Cost Analysis
|
|
187
|
+
====================================
|
|
188
|
+
Total Cost Delta: +$45.00/month
|
|
189
|
+
- Lambda: +$30.00/month
|
|
190
|
+
- API Gateway: +$15.00/month
|
|
191
|
+
|
|
192
|
+
Data Infrastructure Cost Analysis
|
|
193
|
+
==================================
|
|
194
|
+
Total Cost Delta: +$80.00/month
|
|
195
|
+
- RDS: +$60.00/month
|
|
196
|
+
- ElastiCache: +$20.00/month
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Application-Specific Configuration
|
|
200
|
+
|
|
201
|
+
Each application has its own configuration file with appropriate thresholds:
|
|
202
|
+
|
|
203
|
+
### Frontend Infrastructure
|
|
204
|
+
```yaml
|
|
205
|
+
thresholds:
|
|
206
|
+
default:
|
|
207
|
+
warning: 30
|
|
208
|
+
error: 100
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Backend Infrastructure
|
|
212
|
+
```yaml
|
|
213
|
+
thresholds:
|
|
214
|
+
default:
|
|
215
|
+
warning: 50
|
|
216
|
+
error: 200
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Data Infrastructure
|
|
220
|
+
```yaml
|
|
221
|
+
thresholds:
|
|
222
|
+
default:
|
|
223
|
+
warning: 100
|
|
224
|
+
error: 500
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Workspace Management
|
|
228
|
+
|
|
229
|
+
This monorepo uses npm workspaces for dependency management:
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"workspaces": [
|
|
234
|
+
"packages/*"
|
|
235
|
+
]
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Benefits:
|
|
240
|
+
- Single `node_modules` at root
|
|
241
|
+
- Shared dependencies across packages
|
|
242
|
+
- Faster installation
|
|
243
|
+
- Consistent versions
|
|
244
|
+
|
|
245
|
+
## Troubleshooting
|
|
246
|
+
|
|
247
|
+
### Pipeline Runs All Analyses Even for Single Application Changes
|
|
248
|
+
|
|
249
|
+
**Issue**: All cost analysis jobs run even when only one application changed
|
|
250
|
+
|
|
251
|
+
**Solution**: This is intentional for simplicity. To optimize:
|
|
252
|
+
|
|
253
|
+
1. Use GitLab CI rules to detect changed files
|
|
254
|
+
2. Skip analysis jobs for unchanged applications
|
|
255
|
+
3. Example:
|
|
256
|
+
|
|
257
|
+
```yaml
|
|
258
|
+
cost-analysis:frontend:
|
|
259
|
+
rules:
|
|
260
|
+
- changes:
|
|
261
|
+
- packages/frontend-infra/**/*
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Different Applications Have Different Cost Thresholds
|
|
265
|
+
|
|
266
|
+
**Issue**: Need different thresholds for different applications
|
|
267
|
+
|
|
268
|
+
**Solution**: Each application has its own `.cdk-cost-analyzer.yml` file. Configure thresholds independently:
|
|
269
|
+
|
|
270
|
+
```yaml
|
|
271
|
+
# packages/frontend-infra/.cdk-cost-analyzer.yml
|
|
272
|
+
thresholds:
|
|
273
|
+
default:
|
|
274
|
+
warning: 30
|
|
275
|
+
error: 100
|
|
276
|
+
|
|
277
|
+
# packages/data-infra/.cdk-cost-analyzer.yml
|
|
278
|
+
thresholds:
|
|
279
|
+
default:
|
|
280
|
+
warning: 100
|
|
281
|
+
error: 500
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Dependency Conflicts Between Applications
|
|
285
|
+
|
|
286
|
+
**Issue**: Different applications need different versions of the same dependency
|
|
287
|
+
|
|
288
|
+
**Solution**: Use workspace overrides in root `package.json`:
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"overrides": {
|
|
293
|
+
"aws-cdk-lib": "^2.118.0"
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Cost Analysis Takes Too Long
|
|
299
|
+
|
|
300
|
+
**Issue**: Parallel analysis still takes too long
|
|
301
|
+
|
|
302
|
+
**Solution**:
|
|
303
|
+
1. Enable pricing cache across all jobs
|
|
304
|
+
2. Use GitLab CI cache with shared key
|
|
305
|
+
3. Consider running analysis only on merge requests, not all commits
|
|
306
|
+
|
|
307
|
+
## Best Practices
|
|
308
|
+
|
|
309
|
+
### Monorepo Organization
|
|
310
|
+
|
|
311
|
+
- **Keep applications independent**: Minimize cross-application dependencies
|
|
312
|
+
- **Share common code**: Create shared packages for reusable constructs
|
|
313
|
+
- **Consistent naming**: Use consistent naming conventions across applications
|
|
314
|
+
- **Clear ownership**: Document which team owns which application
|
|
315
|
+
|
|
316
|
+
### Cost Management
|
|
317
|
+
|
|
318
|
+
- **Set appropriate thresholds**: Different applications have different cost profiles
|
|
319
|
+
- **Review regularly**: Periodically review and adjust thresholds
|
|
320
|
+
- **Track trends**: Monitor cost changes over time per application
|
|
321
|
+
- **Optimize independently**: Each application can be optimized separately
|
|
322
|
+
|
|
323
|
+
### Deployment Strategy
|
|
324
|
+
|
|
325
|
+
- **Deploy independently**: Each application can be deployed on its own schedule
|
|
326
|
+
- **Test thoroughly**: Test each application independently before deployment
|
|
327
|
+
- **Use environments**: Maintain separate dev/staging/prod environments per application
|
|
328
|
+
- **Coordinate dependencies**: If applications depend on each other, coordinate deployments
|
|
329
|
+
|
|
330
|
+
## Next Steps
|
|
331
|
+
|
|
332
|
+
- Review [Configuration Documentation](../../docs/CONFIGURATION.md) for advanced options
|
|
333
|
+
- Explore [Single-Stack Example](../single-stack/) for simpler projects
|
|
334
|
+
- Check [Troubleshooting Guide](../../docs/TROUBLESHOOTING.md) for common issues
|
|
335
|
+
|
|
336
|
+
## Additional Resources
|
|
337
|
+
|
|
338
|
+
- [npm Workspaces Documentation](https://docs.npmjs.com/cli/v8/using-npm/workspaces)
|
|
339
|
+
- [AWS CDK Documentation](https://docs.aws.amazon.com/cdk/)
|
|
340
|
+
- [CDK Cost Analyzer Documentation](../../README.md)
|
|
341
|
+
- [GitLab CI/CD Documentation](https://docs.gitlab.com/ee/ci/)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cdk-cost-analyzer-monorepo-example",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Monorepo CDK application example with cost analysis",
|
|
5
|
+
"private": true,
|
|
6
|
+
"workspaces": [
|
|
7
|
+
"packages/*"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "npm run build --workspaces",
|
|
11
|
+
"test": "npm test --workspaces",
|
|
12
|
+
"clean": "npm run clean --workspaces"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"aws",
|
|
16
|
+
"cdk",
|
|
17
|
+
"monorepo",
|
|
18
|
+
"cost-analysis",
|
|
19
|
+
"example"
|
|
20
|
+
],
|
|
21
|
+
"author": "ANWB",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^22.10.2",
|
|
25
|
+
"typescript": "^5.7.2"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# CDK Cost Analyzer Configuration for Backend Infrastructure
|
|
2
|
+
|
|
3
|
+
thresholds:
|
|
4
|
+
default:
|
|
5
|
+
warning: 50 # USD per month
|
|
6
|
+
error: 200 # USD per month
|
|
7
|
+
|
|
8
|
+
usageAssumptions:
|
|
9
|
+
lambda:
|
|
10
|
+
invocationsPerMonth: 2000000
|
|
11
|
+
averageDurationMs: 300
|
|
12
|
+
memoryMB: 512
|
|
13
|
+
|
|
14
|
+
apiGateway:
|
|
15
|
+
requestsPerMonth: 2000000
|
|
16
|
+
|
|
17
|
+
dynamodb:
|
|
18
|
+
readCapacityUnits: 10
|
|
19
|
+
writeCapacityUnits: 10
|
|
20
|
+
storageGB: 25
|
|
21
|
+
|
|
22
|
+
synthesis:
|
|
23
|
+
appPath: .
|
|
24
|
+
outputPath: cdk.out
|
|
25
|
+
|
|
26
|
+
exclusions:
|
|
27
|
+
resourceTypes:
|
|
28
|
+
- AWS::IAM::Role
|
|
29
|
+
- AWS::IAM::Policy
|
|
30
|
+
- AWS::Logs::LogGroup
|
|
31
|
+
|
|
32
|
+
cache:
|
|
33
|
+
enabled: true
|
|
34
|
+
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 { BackendStack } from '../lib/backend-stack';
|
|
5
|
+
|
|
6
|
+
const app = new cdk.App();
|
|
7
|
+
|
|
8
|
+
new BackendStack(app, 'BackendStack', {
|
|
9
|
+
env: {
|
|
10
|
+
account: process.env.CDK_DEFAULT_ACCOUNT,
|
|
11
|
+
region: process.env.CDK_DEFAULT_REGION || 'us-east-1',
|
|
12
|
+
},
|
|
13
|
+
description: 'Monorepo example - Backend infrastructure (Lambda, API Gateway, DynamoDB)',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
app.synth();
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
3
|
+
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
|
|
4
|
+
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
|
|
5
|
+
import { Construct } from 'constructs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Backend infrastructure stack
|
|
9
|
+
*
|
|
10
|
+
* Creates Lambda functions, API Gateway, and DynamoDB table
|
|
11
|
+
*/
|
|
12
|
+
export class BackendStack extends cdk.Stack {
|
|
13
|
+
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
|
|
14
|
+
super(scope, id, props);
|
|
15
|
+
|
|
16
|
+
// DynamoDB table
|
|
17
|
+
const table = new dynamodb.Table(this, 'DataTable', {
|
|
18
|
+
tableName: 'backend-data',
|
|
19
|
+
partitionKey: {
|
|
20
|
+
name: 'id',
|
|
21
|
+
type: dynamodb.AttributeType.STRING,
|
|
22
|
+
},
|
|
23
|
+
sortKey: {
|
|
24
|
+
name: 'timestamp',
|
|
25
|
+
type: dynamodb.AttributeType.NUMBER,
|
|
26
|
+
},
|
|
27
|
+
billingMode: dynamodb.BillingMode.PROVISIONED,
|
|
28
|
+
readCapacity: 10,
|
|
29
|
+
writeCapacity: 10,
|
|
30
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Lambda function for API handler
|
|
34
|
+
const apiHandler = new lambda.Function(this, 'ApiHandler', {
|
|
35
|
+
functionName: 'backend-api-handler',
|
|
36
|
+
runtime: lambda.Runtime.NODEJS_18_X,
|
|
37
|
+
handler: 'index.handler',
|
|
38
|
+
code: lambda.Code.fromInline(`
|
|
39
|
+
const { DynamoDBClient, PutItemCommand, QueryCommand } = require('@aws-sdk/client-dynamodb');
|
|
40
|
+
const client = new DynamoDBClient({});
|
|
41
|
+
|
|
42
|
+
exports.handler = async (event) => {
|
|
43
|
+
const tableName = process.env.TABLE_NAME;
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
if (event.httpMethod === 'POST') {
|
|
47
|
+
const body = JSON.parse(event.body);
|
|
48
|
+
await client.send(new PutItemCommand({
|
|
49
|
+
TableName: tableName,
|
|
50
|
+
Item: {
|
|
51
|
+
id: { S: body.id },
|
|
52
|
+
timestamp: { N: Date.now().toString() },
|
|
53
|
+
data: { S: JSON.stringify(body.data) }
|
|
54
|
+
}
|
|
55
|
+
}));
|
|
56
|
+
return {
|
|
57
|
+
statusCode: 201,
|
|
58
|
+
headers: { 'Content-Type': 'application/json' },
|
|
59
|
+
body: JSON.stringify({ message: 'Item created' })
|
|
60
|
+
};
|
|
61
|
+
} else {
|
|
62
|
+
const result = await client.send(new QueryCommand({
|
|
63
|
+
TableName: tableName,
|
|
64
|
+
KeyConditionExpression: 'id = :id',
|
|
65
|
+
ExpressionAttributeValues: { ':id': { S: event.pathParameters.id } }
|
|
66
|
+
}));
|
|
67
|
+
return {
|
|
68
|
+
statusCode: 200,
|
|
69
|
+
headers: { 'Content-Type': 'application/json' },
|
|
70
|
+
body: JSON.stringify(result.Items)
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
return {
|
|
75
|
+
statusCode: 500,
|
|
76
|
+
headers: { 'Content-Type': 'application/json' },
|
|
77
|
+
body: JSON.stringify({ error: error.message })
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
`),
|
|
82
|
+
memorySize: 512,
|
|
83
|
+
timeout: cdk.Duration.seconds(30),
|
|
84
|
+
environment: {
|
|
85
|
+
TABLE_NAME: table.tableName,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Grant Lambda permissions to access DynamoDB
|
|
90
|
+
table.grantReadWriteData(apiHandler);
|
|
91
|
+
|
|
92
|
+
// API Gateway
|
|
93
|
+
const api = new apigateway.RestApi(this, 'Api', {
|
|
94
|
+
restApiName: 'Backend API',
|
|
95
|
+
description: 'Backend REST API',
|
|
96
|
+
deployOptions: {
|
|
97
|
+
stageName: 'prod',
|
|
98
|
+
throttlingRateLimit: 100,
|
|
99
|
+
throttlingBurstLimit: 200,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// API Gateway integration
|
|
104
|
+
const integration = new apigateway.LambdaIntegration(apiHandler);
|
|
105
|
+
|
|
106
|
+
const items = api.root.addResource('items');
|
|
107
|
+
items.addMethod('POST', integration);
|
|
108
|
+
|
|
109
|
+
const item = items.addResource('{id}');
|
|
110
|
+
item.addMethod('GET', integration);
|
|
111
|
+
|
|
112
|
+
// Stack outputs
|
|
113
|
+
new cdk.CfnOutput(this, 'ApiUrl', {
|
|
114
|
+
value: api.url,
|
|
115
|
+
description: 'API Gateway endpoint URL',
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
new cdk.CfnOutput(this, 'TableName', {
|
|
119
|
+
value: table.tableName,
|
|
120
|
+
description: 'DynamoDB table name',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
new cdk.CfnOutput(this, 'FunctionName', {
|
|
124
|
+
value: apiHandler.functionName,
|
|
125
|
+
description: 'Lambda function name',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "backend-infra",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Backend infrastructure CDK application",
|
|
5
|
+
"bin": {
|
|
6
|
+
"backend-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,38 @@
|
|
|
1
|
+
# CDK Cost Analyzer Configuration for Data Infrastructure
|
|
2
|
+
|
|
3
|
+
thresholds:
|
|
4
|
+
default:
|
|
5
|
+
warning: 100 # USD per month
|
|
6
|
+
error: 500 # USD per month
|
|
7
|
+
|
|
8
|
+
usageAssumptions:
|
|
9
|
+
rds:
|
|
10
|
+
instanceClass: db.t3.medium
|
|
11
|
+
storageGB: 100
|
|
12
|
+
backupRetentionDays: 7
|
|
13
|
+
multiAZ: false
|
|
14
|
+
|
|
15
|
+
elasticache:
|
|
16
|
+
nodeType: cache.t3.micro
|
|
17
|
+
numNodes: 2
|
|
18
|
+
engineType: redis
|
|
19
|
+
|
|
20
|
+
s3:
|
|
21
|
+
storageGB: 1000
|
|
22
|
+
getRequests: 500000
|
|
23
|
+
putRequests: 50000
|
|
24
|
+
dataTransferGB: 200
|
|
25
|
+
|
|
26
|
+
synthesis:
|
|
27
|
+
appPath: .
|
|
28
|
+
outputPath: cdk.out
|
|
29
|
+
|
|
30
|
+
exclusions:
|
|
31
|
+
resourceTypes:
|
|
32
|
+
- AWS::IAM::Role
|
|
33
|
+
- AWS::IAM::Policy
|
|
34
|
+
- AWS::EC2::SecurityGroup
|
|
35
|
+
|
|
36
|
+
cache:
|
|
37
|
+
enabled: true
|
|
38
|
+
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 { DataStack } from '../lib/data-stack';
|
|
5
|
+
|
|
6
|
+
const app = new cdk.App();
|
|
7
|
+
|
|
8
|
+
new DataStack(app, 'DataStack', {
|
|
9
|
+
env: {
|
|
10
|
+
account: process.env.CDK_DEFAULT_ACCOUNT,
|
|
11
|
+
region: process.env.CDK_DEFAULT_REGION || 'us-east-1',
|
|
12
|
+
},
|
|
13
|
+
description: 'Monorepo example - Data infrastructure (RDS, ElastiCache, S3)',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
app.synth();
|