@jadenrazo/cloudcost-mcp 0.2.0 → 0.4.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/README.md +129 -39
- package/data/region-price-multipliers.json +49 -0
- package/data/resource-equivalents.json +154 -14
- package/dist/{chunk-KZJSZMWM.js → chunk-TRRAOOVF.js} +14 -13
- package/dist/chunk-VP34WG7Z.js +9341 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +345 -0
- package/dist/index.js +894 -4380
- package/dist/{loader-WIX54B7L.js → loader-VXYJYDIH.js} +4 -2
- package/package.json +33 -11
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<h1 align="center">CloudCost MCP Server</h1>
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
Multi-cloud cost analysis for Terraform
|
|
4
|
+
Multi-cloud cost analysis for Terraform. Live pricing from AWS, Azure, and GCP.
|
|
5
5
|
<br />
|
|
6
6
|
Built on the <a href="https://modelcontextprotocol.io">Model Context Protocol</a> for seamless AI agent integration.
|
|
7
7
|
</p>
|
|
@@ -28,16 +28,20 @@
|
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
-
CloudCost MCP is a [Model Context Protocol](https://modelcontextprotocol.io)
|
|
31
|
+
CloudCost MCP is a [Model Context Protocol](https://modelcontextprotocol.io) server that lets AI agents parse Terraform codebases, query real-time pricing data, and generate multi-cloud cost comparison reports. It connects directly to public pricing APIs from AWS, Azure, and GCP. No API keys or cloud credentials required.
|
|
32
32
|
|
|
33
33
|
### What it does
|
|
34
34
|
|
|
35
|
-
- Parses Terraform HCL files and extracts resource inventories with variable resolution
|
|
36
|
-
- Queries live on-demand pricing from AWS Bulk Pricing CSV and Azure Retail Prices REST API
|
|
37
|
-
- Maps equivalent resources across AWS, Azure, and GCP (compute, database, storage, networking, Kubernetes)
|
|
38
|
-
- Generates cost estimates with per-resource breakdowns (monthly and yearly)
|
|
39
|
-
- Compares costs across all three providers side-by-side in markdown, JSON, or
|
|
40
|
-
- Provides optimization recommendations: right-sizing, reserved pricing, provider switching
|
|
35
|
+
- Parses Terraform HCL files and extracts resource inventories with variable resolution, including referenced modules and OpenTofu `.tofu` files
|
|
36
|
+
- Queries live on-demand pricing from AWS Bulk Pricing CSV and Azure Retail Prices REST API; GCP via live Cloud Billing Catalog API with bundled fallback
|
|
37
|
+
- Maps equivalent resources across AWS, Azure, and GCP (compute, database, storage, networking, Kubernetes, container registries, secrets management, DNS)
|
|
38
|
+
- Generates cost estimates with per-resource breakdowns (monthly and yearly) across multiple currencies
|
|
39
|
+
- Compares costs across all three providers side-by-side in markdown, JSON, CSV, or FOCUS format
|
|
40
|
+
- Provides optimization recommendations: right-sizing, reserved pricing, provider switching, spot/preemptible instances
|
|
41
|
+
- Models hypothetical scenarios (instance type changes, region moves, commitment levels) without modifying Terraform files
|
|
42
|
+
- Projects costs over 3, 6, 12, and 36-month horizons with reserved instance comparisons
|
|
43
|
+
- Tags resources for cost attribution and groups report output by team, environment, or any custom label
|
|
44
|
+
- Posts cost estimate comments to pull requests via a reusable GitHub Actions composite action
|
|
41
45
|
|
|
42
46
|
---
|
|
43
47
|
|
|
@@ -113,7 +117,7 @@ node dist/index.js
|
|
|
113
117
|
|
|
114
118
|
## Tools
|
|
115
119
|
|
|
116
|
-
The server exposes
|
|
120
|
+
The server exposes seven MCP tools. Each accepts JSON input and returns structured JSON output.
|
|
117
121
|
|
|
118
122
|
### `analyze_terraform`
|
|
119
123
|
|
|
@@ -134,6 +138,7 @@ Calculate costs for parsed resources on a specific provider. Returns monthly and
|
|
|
134
138
|
| `tfvars` | `string` | No | Variable overrides |
|
|
135
139
|
| `provider` | `aws \| azure \| gcp` | Yes | Target provider for pricing |
|
|
136
140
|
| `region` | `string` | No | Target region (auto-mapped if omitted) |
|
|
141
|
+
| `currency` | `string` | No | Output currency (default: `USD`). Supports: USD, EUR, GBP, JPY, CAD, AUD, INR, BRL |
|
|
137
142
|
|
|
138
143
|
### `compare_providers`
|
|
139
144
|
|
|
@@ -143,8 +148,9 @@ Full pipeline: parse Terraform, map resources across providers, fetch pricing, a
|
|
|
143
148
|
|-----------|------|----------|-------------|
|
|
144
149
|
| `files` | `{path, content}[]` | Yes | Terraform files |
|
|
145
150
|
| `tfvars` | `string` | No | Variable overrides |
|
|
146
|
-
| `format` | `markdown \| json \| csv` | No | Report format (default: `markdown`) |
|
|
151
|
+
| `format` | `markdown \| json \| csv \| focus` | No | Report format (default: `markdown`) |
|
|
147
152
|
| `providers` | `string[]` | No | Providers to compare (default: all three) |
|
|
153
|
+
| `currency` | `string` | No | Output currency (default: `USD`). Supports: USD, EUR, GBP, JPY, CAD, AUD, INR, BRL |
|
|
148
154
|
|
|
149
155
|
### `get_equivalents`
|
|
150
156
|
|
|
@@ -178,6 +184,30 @@ Analyze Terraform resources and return optimization recommendations. Includes ri
|
|
|
178
184
|
| `tfvars` | `string` | No | Variable overrides |
|
|
179
185
|
| `providers` | `string[]` | No | Providers to evaluate (default: all three) |
|
|
180
186
|
|
|
187
|
+
### `what_if`
|
|
188
|
+
|
|
189
|
+
Run hypothetical pricing scenarios against existing Terraform resources. Change instance types, regions, providers, or commitment levels and see the cost delta without modifying your actual configuration.
|
|
190
|
+
|
|
191
|
+
| Parameter | Type | Required | Description |
|
|
192
|
+
|-----------|------|----------|-------------|
|
|
193
|
+
| `files` | `{path, content}[]` | Yes | Terraform files |
|
|
194
|
+
| `tfvars` | `string` | No | Variable overrides |
|
|
195
|
+
| `scenarios` | `object[]` | Yes | Changes to model. Each specifies a resource name and the attributes to override |
|
|
196
|
+
| `providers` | `string[]` | No | Providers to evaluate (default: all three) |
|
|
197
|
+
| `currency` | `string` | No | Output currency (default: `USD`) |
|
|
198
|
+
|
|
199
|
+
**Example**: model the cost impact of switching compute from on-demand to spot across providers:
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{
|
|
203
|
+
"files": [{ "path": "main.tf", "content": "..." }],
|
|
204
|
+
"scenarios": [
|
|
205
|
+
{ "resource": "aws_instance.web", "pricing_model": "spot" },
|
|
206
|
+
{ "resource": "aws_instance.app", "instance_type": "m6i.2xlarge" }
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
181
211
|
---
|
|
182
212
|
|
|
183
213
|
## How Pricing Works
|
|
@@ -186,30 +216,32 @@ CloudCost uses a tiered approach to get the most accurate pricing available with
|
|
|
186
216
|
|
|
187
217
|
### AWS
|
|
188
218
|
|
|
189
|
-
1. **Live CSV streaming** (primary)
|
|
219
|
+
1. **Live CSV streaming** (primary). For EC2 compute pricing, the server streams the AWS Bulk Pricing CSV for the target region line-by-line. This avoids loading the full ~267 MB file into memory. All on-demand compute prices for the region are extracted in a single pass and cached in SQLite for 24 hours. Concurrent requests for the same region share a single download.
|
|
190
220
|
|
|
191
|
-
2. **Live JSON API** (secondary)
|
|
221
|
+
2. **Live JSON API** (secondary). For RDS (~24 MB), S3, ELB, and VPC, the server fetches regional JSON from the [AWS Price List Bulk API](https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/index.json). These files are small enough to parse directly.
|
|
192
222
|
|
|
193
|
-
3. **Fallback tables + interpolation
|
|
223
|
+
3. **Fallback tables + interpolation**. If live fetching fails (network issues, timeouts), the server falls back to built-in pricing tables covering 85+ EC2 and 29 RDS instance types. A size-interpolation algorithm estimates prices for unlisted sizes within known families by following AWS's predictable doubling pattern (e.g., `large` to `xlarge` doubles the price).
|
|
194
224
|
|
|
195
225
|
### Azure
|
|
196
226
|
|
|
197
|
-
1. **Live REST API** (primary)
|
|
227
|
+
1. **Live REST API** (primary). Queries the [Azure Retail Prices API](https://prices.azure.com/api/retail/prices) with OData filters for exact SKU matching (`armSkuName`). Fast, free, unauthenticated. Returns precise per-SKU pricing. Results are paginated and fully consumed.
|
|
198
228
|
|
|
199
|
-
2. **Fallback tables + interpolation
|
|
229
|
+
2. **Fallback tables + interpolation**. If the API is unreachable, falls back to built-in tables covering 40+ VM sizes and 14 database tiers. A vCPU-proportional interpolation algorithm estimates prices for unlisted sizes.
|
|
200
230
|
|
|
201
231
|
### GCP
|
|
202
232
|
|
|
203
|
-
1. **
|
|
233
|
+
1. **Live Cloud Billing Catalog API** (primary). Queries the GCP Cloud Billing Catalog API (`cloudbilling.googleapis.com`) using unauthenticated public endpoints. Results are cached for 24 hours.
|
|
234
|
+
|
|
235
|
+
2. **Bundled pricing data** (fallback). If the live API is unreachable, falls back to curated pricing data in `data/gcp-pricing/` that ships with the package. Covers Compute Engine machine types, Cloud SQL tiers, Cloud Storage classes, and Persistent Disk types across all major regions.
|
|
204
236
|
|
|
205
|
-
|
|
237
|
+
3. **Infrastructure services**. Load balancer, Cloud NAT, and GKE pricing use fixed public rates.
|
|
206
238
|
|
|
207
239
|
### Pricing Source Transparency
|
|
208
240
|
|
|
209
241
|
Every price returned includes a `pricing_source` attribute indicating its origin:
|
|
210
|
-
- `"live"
|
|
211
|
-
- `"fallback"
|
|
212
|
-
- `"bundled"
|
|
242
|
+
- `"live"`: fetched from a public API in real time
|
|
243
|
+
- `"fallback"`: from built-in tables (approximate, but reasonable for estimates)
|
|
244
|
+
- `"bundled"`: from bundled data files shipped with the package
|
|
213
245
|
|
|
214
246
|
All pricing data is cached in a local SQLite database (`~/.cloudcost/cache.db`) with a 24-hour TTL to minimize redundant API calls.
|
|
215
247
|
|
|
@@ -288,6 +320,12 @@ All configuration is optional. The server works out of the box with sensible def
|
|
|
288
320
|
| `CLOUDCOST_CACHE_PATH` | `~/.cloudcost/cache.db` | SQLite cache file location |
|
|
289
321
|
| `CLOUDCOST_LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
|
290
322
|
| `CLOUDCOST_MONTHLY_HOURS` | `730` | Hours per month for cost calculations |
|
|
323
|
+
| `CLOUDCOST_INCLUDE_DATA_TRANSFER` | `false` | Include estimated data transfer costs in reports |
|
|
324
|
+
| `CLOUDCOST_PRICING_MODEL` | `on_demand` | Default pricing model: `on_demand`, `spot`, or `reserved` |
|
|
325
|
+
| `CLOUDCOST_RESOLVE_MODULES` | `true` | Expand referenced Terraform modules during parsing |
|
|
326
|
+
| `CLOUDCOST_BUDGET_MONTHLY` | | Monthly budget cap in USD. Triggers a warning when exceeded |
|
|
327
|
+
| `CLOUDCOST_BUDGET_PER_RESOURCE` | | Per-resource monthly budget cap in USD |
|
|
328
|
+
| `CLOUDCOST_BUDGET_WARN_PCT` | `80` | Percentage of budget at which a warning is surfaced (default: 80%) |
|
|
291
329
|
|
|
292
330
|
### Config File
|
|
293
331
|
|
|
@@ -351,11 +389,11 @@ Configuration priority: environment variables > config file > built-in defaults.
|
|
|
351
389
|
|
|
352
390
|
### Key Design Decisions
|
|
353
391
|
|
|
354
|
-
- **Zero API keys
|
|
355
|
-
- **SQLite cache
|
|
356
|
-
- **Streaming for large files
|
|
357
|
-
- **Graceful degradation
|
|
358
|
-
- **ESM-only
|
|
392
|
+
- **Zero API keys.** All pricing comes from public endpoints. AWS uses the unauthenticated Bulk Pricing files. Azure uses the free Retail Prices REST API. GCP queries the Cloud Billing Catalog API with bundled fallback.
|
|
393
|
+
- **SQLite cache.** A single `better-sqlite3` database caches all pricing lookups with configurable TTL. Shared across all tools per server lifetime.
|
|
394
|
+
- **Streaming for large files.** AWS EC2 pricing data (~267 MB CSV) is streamed line-by-line rather than loaded into memory. Prices for a region are extracted in one pass and cached.
|
|
395
|
+
- **Graceful degradation.** If any live pricing source is unavailable, the server falls back to built-in tables with size-interpolation. Every response includes the pricing source so the consumer knows the confidence level.
|
|
396
|
+
- **ESM-only.** Requires Node 20+. All internal imports use `.js` extensions.
|
|
359
397
|
|
|
360
398
|
---
|
|
361
399
|
|
|
@@ -368,6 +406,9 @@ Configuration priority: environment variables > config file > built-in defaults.
|
|
|
368
406
|
| **Storage** | `aws_ebs_volume`, `aws_s3_bucket` | `azurerm_managed_disk`, `azurerm_storage_account` | `google_compute_disk`, `google_storage_bucket` |
|
|
369
407
|
| **Network** | `aws_lb`, `aws_nat_gateway` | `azurerm_lb`, `azurerm_nat_gateway` | `google_compute_forwarding_rule` |
|
|
370
408
|
| **Kubernetes** | `aws_eks_cluster` | `azurerm_kubernetes_cluster` | `google_container_cluster` |
|
|
409
|
+
| **Container Registries** | `aws_ecr_repository` | `azurerm_container_registry` | `google_artifact_registry_repository` |
|
|
410
|
+
| **Secrets Management** | `aws_secretsmanager_secret` | `azurerm_key_vault` | `google_secret_manager_secret` |
|
|
411
|
+
| **DNS** | `aws_route53_zone` | `azurerm_dns_zone` | `google_dns_managed_zone` |
|
|
371
412
|
|
|
372
413
|
Instance type mapping covers 70+ AWS instance types (including Graviton/ARM families: m6g, m7g, c6g, c7g, r6g, r7g, t4g), 40+ Azure VM sizes, and 20+ GCP machine types with full bidirectional cross-provider mapping.
|
|
373
414
|
|
|
@@ -375,10 +416,8 @@ Instance type mapping covers 70+ AWS instance types (including Graviton/ARM fami
|
|
|
375
416
|
|
|
376
417
|
## Limitations
|
|
377
418
|
|
|
378
|
-
- **
|
|
379
|
-
- **
|
|
380
|
-
- **No Terraform module expansion**. Only direct resource blocks in the provided files are parsed. Resources defined inside referenced modules (`source = "..."`) are not resolved.
|
|
381
|
-
- **GCP pricing is bundled**, not live. Prices may lag behind actual rates. AWS and Azure pricing is fetched in real time.
|
|
419
|
+
- **On-demand pricing only** by default. Prices reflect pay-as-you-go rates. The `optimize_cost` tool will recommend reserved instances and savings plans, but base estimates use on-demand. Pass `pricing_model: "spot"` in `what_if` scenarios to model spot/preemptible pricing.
|
|
420
|
+
- **GCP live pricing** is fetched from the Cloud Billing Catalog API with automatic fallback to bundled data when the API is unreachable. Bundled prices may lag slightly behind actual rates.
|
|
382
421
|
- **First request latency**. The initial EC2 pricing lookup for a new AWS region may take 30-120 seconds as the CSV file is streamed. Subsequent lookups for the same region are instant (cached for 24 hours).
|
|
383
422
|
- **Specialty instance types**. GPU instances (p4d, g5, etc.), high-memory (x2idn), and bare-metal types may fall back to interpolated pricing if not in the built-in tables and live fetch fails.
|
|
384
423
|
|
|
@@ -386,13 +425,49 @@ Instance type mapping covers 70+ AWS instance types (including Graviton/ARM fami
|
|
|
386
425
|
|
|
387
426
|
## Troubleshooting
|
|
388
427
|
|
|
389
|
-
**$0 cost estimates
|
|
428
|
+
**$0 cost estimates.** The instance type string in your Terraform code probably doesn't match any known pricing data. Check that you're using a real instance type (e.g., `t3.xlarge`) rather than a variable reference that wasn't resolved. Pass your `terraform.tfvars` content via the `tfvars` parameter to resolve variables.
|
|
390
429
|
|
|
391
|
-
**Slow first request
|
|
430
|
+
**Slow first request.** The first EC2 pricing lookup for a new region streams the full AWS pricing CSV (~267 MB). One-time cost per region; subsequent lookups hit the local SQLite cache. Set `CLOUDCOST_LOG_LEVEL=debug` to see progress.
|
|
392
431
|
|
|
393
|
-
**Cache issues
|
|
432
|
+
**Cache issues.** Delete `~/.cloudcost/cache.db` to clear all cached pricing data. The cache rebuilds automatically on the next request.
|
|
433
|
+
|
|
434
|
+
**Node version.** Requires Node.js 20+. Uses ESM modules, Web Streams API (`TextDecoderStream`), and `AbortSignal.timeout()`.
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## GitHub Actions
|
|
439
|
+
|
|
440
|
+
A reusable composite action is included at `.github/actions/cost-estimate/`. It detects changed `.tf` files, runs a cost comparison, and posts the result as a PR comment.
|
|
441
|
+
|
|
442
|
+
```yaml
|
|
443
|
+
# .github/workflows/cost-estimate.yml
|
|
444
|
+
name: Terraform Cost Estimate
|
|
445
|
+
|
|
446
|
+
on:
|
|
447
|
+
pull_request:
|
|
448
|
+
types: [opened, synchronize]
|
|
449
|
+
|
|
450
|
+
jobs:
|
|
451
|
+
cost-estimate:
|
|
452
|
+
runs-on: ubuntu-latest
|
|
453
|
+
permissions:
|
|
454
|
+
contents: read
|
|
455
|
+
pull-requests: write
|
|
456
|
+
steps:
|
|
457
|
+
- uses: actions/checkout@v4
|
|
458
|
+
with:
|
|
459
|
+
fetch-depth: 0
|
|
460
|
+
|
|
461
|
+
- uses: ./.github/actions/cost-estimate
|
|
462
|
+
with:
|
|
463
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
464
|
+
# terraform_dir: "./terraform"
|
|
465
|
+
# providers: "aws,azure,gcp"
|
|
466
|
+
# format: "markdown"
|
|
467
|
+
# currency: "USD"
|
|
468
|
+
```
|
|
394
469
|
|
|
395
|
-
|
|
470
|
+
The action auto-detects the directory containing changed `.tf` files and skips gracefully when no Terraform changes are present in the PR.
|
|
396
471
|
|
|
397
472
|
---
|
|
398
473
|
|
|
@@ -414,17 +489,32 @@ src/
|
|
|
414
489
|
├── server.ts # MCP server setup, tool registration
|
|
415
490
|
├── config.ts # Config loader (defaults → file → env vars)
|
|
416
491
|
├── logger.ts # Structured logger
|
|
417
|
-
├──
|
|
418
|
-
├──
|
|
492
|
+
├── currency.ts # Multi-currency conversion and formatting
|
|
493
|
+
├── tools/
|
|
494
|
+
│ ├── ... # MCP tool handlers + Zod schemas
|
|
495
|
+
│ └── what-if.ts # Hypothetical scenario modeling
|
|
496
|
+
├── parsers/
|
|
497
|
+
│ ├── ... # HCL parsing, variable resolution
|
|
498
|
+
│ ├── module-resolver.ts # Terraform module expansion
|
|
499
|
+
│ └── dependency-graph.ts # Resource dependency graph builder
|
|
419
500
|
├── pricing/
|
|
420
501
|
│ ├── pricing-engine.ts # Router: dispatches to provider adapters
|
|
421
502
|
│ ├── cache.ts # SQLite-backed pricing cache
|
|
422
503
|
│ ├── aws/ # Bulk CSV streaming + JSON + fallback
|
|
423
504
|
│ ├── azure/ # Retail Prices REST API + fallback
|
|
424
|
-
│ └── gcp/
|
|
425
|
-
├──
|
|
505
|
+
│ └── gcp/
|
|
506
|
+
│ ├── bundled-loader.ts # Static bundled pricing fallback
|
|
507
|
+
│ └── cloud-billing-client.ts # Live GCP Cloud Billing Catalog API
|
|
508
|
+
├── calculator/
|
|
509
|
+
│ ├── ... # Cost calculations per resource type
|
|
510
|
+
│ ├── projection.ts # Multi-horizon cost projections
|
|
511
|
+
│ ├── container-registry.ts
|
|
512
|
+
│ ├── secrets.ts
|
|
513
|
+
│ └── dns.ts
|
|
426
514
|
├── mapping/ # Cross-provider resource/instance mapping
|
|
427
|
-
├── reporting/
|
|
515
|
+
├── reporting/
|
|
516
|
+
│ ├── ... # Markdown, JSON, CSV formatters
|
|
517
|
+
│ └── focus-report.ts # FOCUS-compliant export format
|
|
428
518
|
└── types/ # Shared TypeScript interfaces
|
|
429
519
|
|
|
430
520
|
data/
|
|
@@ -438,4 +528,4 @@ data/
|
|
|
438
528
|
|
|
439
529
|
## License
|
|
440
530
|
|
|
441
|
-
MIT
|
|
531
|
+
MIT. See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"aws": {
|
|
3
|
+
"us-east-1": 1.0,
|
|
4
|
+
"us-east-2": 1.0,
|
|
5
|
+
"us-west-1": 1.02,
|
|
6
|
+
"us-west-2": 1.0,
|
|
7
|
+
"eu-west-1": 1.05,
|
|
8
|
+
"eu-west-2": 1.07,
|
|
9
|
+
"eu-central-1": 1.08,
|
|
10
|
+
"ap-southeast-1": 1.10,
|
|
11
|
+
"ap-southeast-2": 1.12,
|
|
12
|
+
"ap-northeast-1": 1.12,
|
|
13
|
+
"ap-south-1": 1.05,
|
|
14
|
+
"sa-east-1": 1.20,
|
|
15
|
+
"ca-central-1": 1.03,
|
|
16
|
+
"me-south-1": 1.10,
|
|
17
|
+
"af-south-1": 1.15
|
|
18
|
+
},
|
|
19
|
+
"azure": {
|
|
20
|
+
"eastus": 1.0,
|
|
21
|
+
"eastus2": 1.0,
|
|
22
|
+
"westus": 1.0,
|
|
23
|
+
"westus2": 1.0,
|
|
24
|
+
"westeurope": 1.07,
|
|
25
|
+
"northeurope": 1.05,
|
|
26
|
+
"uksouth": 1.06,
|
|
27
|
+
"southeastasia": 1.08,
|
|
28
|
+
"eastasia": 1.10,
|
|
29
|
+
"japaneast": 1.12,
|
|
30
|
+
"australiaeast": 1.10,
|
|
31
|
+
"brazilsouth": 1.18,
|
|
32
|
+
"canadacentral": 1.03,
|
|
33
|
+
"centralindia": 1.05
|
|
34
|
+
},
|
|
35
|
+
"gcp": {
|
|
36
|
+
"us-central1": 1.0,
|
|
37
|
+
"us-east1": 1.0,
|
|
38
|
+
"us-west1": 1.02,
|
|
39
|
+
"europe-west1": 1.05,
|
|
40
|
+
"europe-west2": 1.08,
|
|
41
|
+
"europe-west3": 1.08,
|
|
42
|
+
"asia-southeast1": 1.08,
|
|
43
|
+
"asia-east1": 1.08,
|
|
44
|
+
"asia-northeast1": 1.12,
|
|
45
|
+
"australia-southeast1": 1.12,
|
|
46
|
+
"southamerica-east1": 1.20,
|
|
47
|
+
"northamerica-northeast1": 1.03
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,16 +1,156 @@
|
|
|
1
1
|
[
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
{
|
|
3
|
+
"category": "compute_instance",
|
|
4
|
+
"aws": "aws_instance",
|
|
5
|
+
"azure": "azurerm_linux_virtual_machine",
|
|
6
|
+
"gcp": "google_compute_instance",
|
|
7
|
+
"notes": "General purpose VM"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"category": "compute_instance_windows",
|
|
11
|
+
"aws": "aws_instance",
|
|
12
|
+
"azure": "azurerm_windows_virtual_machine",
|
|
13
|
+
"gcp": "google_compute_instance",
|
|
14
|
+
"notes": "Windows VM"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"category": "managed_database_postgres",
|
|
18
|
+
"aws": "aws_db_instance",
|
|
19
|
+
"azure": "azurerm_postgresql_flexible_server",
|
|
20
|
+
"gcp": "google_sql_database_instance",
|
|
21
|
+
"notes": "Managed PostgreSQL"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"category": "managed_database_mysql",
|
|
25
|
+
"aws": "aws_db_instance",
|
|
26
|
+
"azure": "azurerm_mysql_flexible_server",
|
|
27
|
+
"gcp": "google_sql_database_instance",
|
|
28
|
+
"notes": "Managed MySQL"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"category": "object_storage",
|
|
32
|
+
"aws": "aws_s3_bucket",
|
|
33
|
+
"azure": "azurerm_storage_account",
|
|
34
|
+
"gcp": "google_storage_bucket",
|
|
35
|
+
"notes": "Object storage"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"category": "block_storage",
|
|
39
|
+
"aws": "aws_ebs_volume",
|
|
40
|
+
"azure": "azurerm_managed_disk",
|
|
41
|
+
"gcp": "google_compute_disk",
|
|
42
|
+
"notes": "Block storage volume"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"category": "load_balancer",
|
|
46
|
+
"aws": "aws_lb",
|
|
47
|
+
"azure": "azurerm_lb",
|
|
48
|
+
"gcp": "google_compute_forwarding_rule",
|
|
49
|
+
"notes": "Load balancer"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"category": "nat_gateway",
|
|
53
|
+
"aws": "aws_nat_gateway",
|
|
54
|
+
"azure": "azurerm_nat_gateway",
|
|
55
|
+
"gcp": "google_compute_router_nat",
|
|
56
|
+
"notes": "NAT gateway"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"category": "kubernetes_cluster",
|
|
60
|
+
"aws": "aws_eks_cluster",
|
|
61
|
+
"azure": "azurerm_kubernetes_cluster",
|
|
62
|
+
"gcp": "google_container_cluster",
|
|
63
|
+
"notes": "Managed Kubernetes"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"category": "kubernetes_node_group",
|
|
67
|
+
"aws": "aws_eks_node_group",
|
|
68
|
+
"azure": "azurerm_kubernetes_cluster_node_pool",
|
|
69
|
+
"gcp": "google_container_node_pool",
|
|
70
|
+
"notes": "Kubernetes node pool"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"category": "dns_zone",
|
|
74
|
+
"aws": "aws_route53_zone",
|
|
75
|
+
"azure": "azurerm_dns_zone",
|
|
76
|
+
"gcp": "google_dns_managed_zone",
|
|
77
|
+
"notes": "DNS hosted zone"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"category": "cdn",
|
|
81
|
+
"aws": "aws_cloudfront_distribution",
|
|
82
|
+
"azure": "azurerm_cdn_profile",
|
|
83
|
+
"gcp": "google_compute_backend_bucket",
|
|
84
|
+
"notes": "CDN distribution"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"category": "redis_cache",
|
|
88
|
+
"aws": "aws_elasticache_cluster",
|
|
89
|
+
"azure": "azurerm_redis_cache",
|
|
90
|
+
"gcp": "google_redis_instance",
|
|
91
|
+
"notes": "Managed Redis"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"category": "container_registry",
|
|
95
|
+
"aws": "aws_ecr_repository",
|
|
96
|
+
"azure": "azurerm_container_registry",
|
|
97
|
+
"gcp": "google_artifact_registry_repository",
|
|
98
|
+
"notes": "Container registry"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"category": "secrets",
|
|
102
|
+
"aws": "aws_secretsmanager_secret",
|
|
103
|
+
"azure": "azurerm_key_vault",
|
|
104
|
+
"gcp": "google_secret_manager_secret",
|
|
105
|
+
"notes": "Secrets management"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"category": "api_gateway",
|
|
109
|
+
"aws": "aws_api_gateway_rest_api",
|
|
110
|
+
"azure": "azurerm_api_management",
|
|
111
|
+
"gcp": "google_apigateway_api",
|
|
112
|
+
"notes": "API Gateway / Management"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"category": "waf",
|
|
116
|
+
"aws": "aws_wafv2_web_acl",
|
|
117
|
+
"azure": "azurerm_web_application_firewall_policy",
|
|
118
|
+
"gcp": "google_compute_security_policy",
|
|
119
|
+
"notes": "Web Application Firewall"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"category": "search",
|
|
123
|
+
"aws": "aws_opensearch_domain",
|
|
124
|
+
"azure": "azurerm_search_service",
|
|
125
|
+
"gcp": "google_elasticsearch_domain",
|
|
126
|
+
"notes": "Managed search / OpenSearch"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"category": "messaging",
|
|
130
|
+
"aws": "aws_sns_topic",
|
|
131
|
+
"azure": "azurerm_servicebus_namespace",
|
|
132
|
+
"gcp": "google_pubsub_topic",
|
|
133
|
+
"notes": "Messaging / notifications"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"category": "ml_inference_endpoint",
|
|
137
|
+
"aws": "aws_sagemaker_endpoint",
|
|
138
|
+
"azure": "azurerm_machine_learning_inference_cluster",
|
|
139
|
+
"gcp": "google_vertex_ai_endpoint",
|
|
140
|
+
"notes": "ML/AI inference endpoint"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"category": "message_broker",
|
|
144
|
+
"aws": "aws_mq_broker",
|
|
145
|
+
"azure": "azurerm_eventhub_namespace",
|
|
146
|
+
"gcp": "google_pubsub_subscription",
|
|
147
|
+
"notes": "Message broker / event streaming"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"category": "redis_replication_group",
|
|
151
|
+
"aws": "aws_elasticache_replication_group",
|
|
152
|
+
"azure": "azurerm_redis_cache",
|
|
153
|
+
"gcp": "google_redis_instance",
|
|
154
|
+
"notes": "Redis replication / HA cache"
|
|
155
|
+
}
|
|
16
156
|
]
|
|
@@ -40,11 +40,10 @@ var _gcpComputePricing = null;
|
|
|
40
40
|
var _gcpSqlPricing = null;
|
|
41
41
|
var _gcpStoragePricing = null;
|
|
42
42
|
var _gcpDiskPricing = null;
|
|
43
|
+
var _regionPriceMultipliers = null;
|
|
43
44
|
function getResourceEquivalents() {
|
|
44
45
|
if (_resourceEquivalents === null) {
|
|
45
|
-
_resourceEquivalents = loadJsonFile(
|
|
46
|
-
"resource-equivalents.json"
|
|
47
|
-
);
|
|
46
|
+
_resourceEquivalents = loadJsonFile("resource-equivalents.json");
|
|
48
47
|
}
|
|
49
48
|
return _resourceEquivalents;
|
|
50
49
|
}
|
|
@@ -68,25 +67,19 @@ function getStorageMap() {
|
|
|
68
67
|
}
|
|
69
68
|
function getAwsInstances() {
|
|
70
69
|
if (_awsInstances === null) {
|
|
71
|
-
_awsInstances = loadJsonFile(
|
|
72
|
-
"instance-types/aws-instances.json"
|
|
73
|
-
);
|
|
70
|
+
_awsInstances = loadJsonFile("instance-types/aws-instances.json");
|
|
74
71
|
}
|
|
75
72
|
return _awsInstances;
|
|
76
73
|
}
|
|
77
74
|
function getAzureVmSizes() {
|
|
78
75
|
if (_azureVmSizes === null) {
|
|
79
|
-
_azureVmSizes = loadJsonFile(
|
|
80
|
-
"instance-types/azure-vm-sizes.json"
|
|
81
|
-
);
|
|
76
|
+
_azureVmSizes = loadJsonFile("instance-types/azure-vm-sizes.json");
|
|
82
77
|
}
|
|
83
78
|
return _azureVmSizes;
|
|
84
79
|
}
|
|
85
80
|
function getGcpMachineTypes() {
|
|
86
81
|
if (_gcpMachineTypes === null) {
|
|
87
|
-
_gcpMachineTypes = loadJsonFile(
|
|
88
|
-
"instance-types/gcp-machine-types.json"
|
|
89
|
-
);
|
|
82
|
+
_gcpMachineTypes = loadJsonFile("instance-types/gcp-machine-types.json");
|
|
90
83
|
}
|
|
91
84
|
return _gcpMachineTypes;
|
|
92
85
|
}
|
|
@@ -122,6 +115,12 @@ function getGcpDiskPricing() {
|
|
|
122
115
|
}
|
|
123
116
|
return _gcpDiskPricing;
|
|
124
117
|
}
|
|
118
|
+
function getRegionPriceMultipliers() {
|
|
119
|
+
if (_regionPriceMultipliers === null) {
|
|
120
|
+
_regionPriceMultipliers = loadJsonFile("region-price-multipliers.json");
|
|
121
|
+
}
|
|
122
|
+
return _regionPriceMultipliers;
|
|
123
|
+
}
|
|
125
124
|
function _resetLoaderCache() {
|
|
126
125
|
_resourceEquivalents = null;
|
|
127
126
|
_instanceMap = null;
|
|
@@ -134,6 +133,7 @@ function _resetLoaderCache() {
|
|
|
134
133
|
_gcpSqlPricing = null;
|
|
135
134
|
_gcpStoragePricing = null;
|
|
136
135
|
_gcpDiskPricing = null;
|
|
136
|
+
_regionPriceMultipliers = null;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
export {
|
|
@@ -148,6 +148,7 @@ export {
|
|
|
148
148
|
getGcpSqlPricing,
|
|
149
149
|
getGcpStoragePricing,
|
|
150
150
|
getGcpDiskPricing,
|
|
151
|
+
getRegionPriceMultipliers,
|
|
151
152
|
_resetLoaderCache
|
|
152
153
|
};
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
154
|
+
//# sourceMappingURL=chunk-TRRAOOVF.js.map
|