@jadenrazo/cloudcost-mcp 0.3.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 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 powered by live pricing data from AWS, Azure, and GCP.
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) (MCP) server — a standardized way to give AI assistants like Claude access to external tools — 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 and Azure no API keys or cloud credentials required. GCP pricing is bundled from public catalog data.
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 CSV
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 six MCP tools. Each accepts JSON input and returns structured JSON output.
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) 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.
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) 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.
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** 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` `xlarge` doubles the price).
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) Queries the [Azure Retail Prices API](https://prices.azure.com/api/retail/prices) with OData filters for exact SKU matching (`armSkuName`). This is a fast, free, unauthenticated API that returns precise per-SKU pricing. Results are paginated and fully consumed.
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** 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.
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. **Bundled pricing data** — GCP's Cloud Billing Catalog API requires an API key, so the server ships with curated pricing data in `data/gcp-pricing/`. This covers Compute Engine machine types, Cloud SQL tiers, Cloud Storage classes, and Persistent Disk types across all major regions.
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
- 2. **Infrastructure services** Load balancer, Cloud NAT, and GKE pricing use fixed public rates.
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"` fetched from a public API in real time
211
- - `"fallback"` from built-in tables (approximate, but reasonable for estimates)
212
- - `"bundled"` from bundled data files shipped with the package
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** All pricing comes from public endpoints. AWS uses the unauthenticated Bulk Pricing files. Azure uses the free Retail Prices REST API. GCP uses bundled data from public catalog information.
355
- - **SQLite cache** A single `better-sqlite3` database caches all pricing lookups with configurable TTL. Shared across all tools per server lifetime.
356
- - **Streaming for large files** AWS EC2 pricing data (~267 MB CSV) is streamed line-by-line rather than loaded into memory. All prices for a region are extracted in one pass and cached.
357
- - **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.
358
- - **ESM-only** Requires Node 20+. All internal imports use `.js` extensions.
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
- - **Data transfer costs** are not included. Inter-region, inter-AZ, and internet egress charges are excluded from estimates.
379
- - **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.
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** This usually means the instance type string in your Terraform code 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.
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** The first EC2 pricing lookup for a new region streams the full AWS pricing CSV (~267 MB). This is a one-time cost per region; all subsequent lookups hit the local SQLite cache. Set `CLOUDCOST_LOG_LEVEL=debug` to see progress.
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** Delete `~/.cloudcost/cache.db` to clear all cached pricing data. The cache rebuilds automatically on the next request.
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
- **Node version** The server requires Node.js 20+. It uses ESM modules, Web Streams API (`TextDecoderStream`), and `AbortSignal.timeout()`.
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
- ├── tools/ # MCP tool handlers + Zod schemas
418
- ├── parsers/ # HCL parsing, variable resolution
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/ # Bundled pricing data loader
425
- ├── calculator/ # Cost calculations per resource type
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/ # Output formatters (markdown, JSON, CSV)
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 see [LICENSE](LICENSE) for details.
531
+ MIT. See [LICENSE](LICENSE) for details.
@@ -1,17 +1,156 @@
1
1
  [
2
- { "category": "compute_instance", "aws": "aws_instance", "azure": "azurerm_linux_virtual_machine", "gcp": "google_compute_instance", "notes": "General purpose VM" },
3
- { "category": "compute_instance_windows", "aws": "aws_instance", "azure": "azurerm_windows_virtual_machine", "gcp": "google_compute_instance", "notes": "Windows VM" },
4
- { "category": "managed_database_postgres", "aws": "aws_db_instance", "azure": "azurerm_postgresql_flexible_server", "gcp": "google_sql_database_instance", "notes": "Managed PostgreSQL" },
5
- { "category": "managed_database_mysql", "aws": "aws_db_instance", "azure": "azurerm_mysql_flexible_server", "gcp": "google_sql_database_instance", "notes": "Managed MySQL" },
6
- { "category": "object_storage", "aws": "aws_s3_bucket", "azure": "azurerm_storage_account", "gcp": "google_storage_bucket", "notes": "Object storage" },
7
- { "category": "block_storage", "aws": "aws_ebs_volume", "azure": "azurerm_managed_disk", "gcp": "google_compute_disk", "notes": "Block storage volume" },
8
- { "category": "load_balancer", "aws": "aws_lb", "azure": "azurerm_lb", "gcp": "google_compute_forwarding_rule", "notes": "Load balancer" },
9
- { "category": "nat_gateway", "aws": "aws_nat_gateway", "azure": "azurerm_nat_gateway", "gcp": "google_compute_router_nat", "notes": "NAT gateway" },
10
- { "category": "kubernetes_cluster", "aws": "aws_eks_cluster", "azure": "azurerm_kubernetes_cluster", "gcp": "google_container_cluster", "notes": "Managed Kubernetes" },
11
- { "category": "kubernetes_node_group", "aws": "aws_eks_node_group", "azure": "azurerm_kubernetes_cluster_node_pool", "gcp": "google_container_node_pool", "notes": "Kubernetes node pool" },
12
- { "category": "dns_zone", "aws": "aws_route53_zone", "azure": "azurerm_dns_zone", "gcp": "google_dns_managed_zone", "notes": "DNS hosted zone" },
13
- { "category": "cdn", "aws": "aws_cloudfront_distribution", "azure": "azurerm_cdn_profile", "gcp": "google_compute_backend_bucket", "notes": "CDN distribution" },
14
- { "category": "redis_cache", "aws": "aws_elasticache_cluster", "azure": "azurerm_redis_cache", "gcp": "google_redis_instance", "notes": "Managed Redis" },
15
- { "category": "container_registry", "aws": "aws_ecr_repository", "azure": "azurerm_container_registry", "gcp": "google_artifact_registry_repository", "notes": "Container registry" },
16
- { "category": "secrets", "aws": "aws_secretsmanager_secret", "azure": "azurerm_key_vault", "gcp": "google_secret_manager_secret", "notes": "Secrets management" }
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
+ }
17
156
  ]
@@ -43,9 +43,7 @@ var _gcpDiskPricing = null;
43
43
  var _regionPriceMultipliers = null;
44
44
  function getResourceEquivalents() {
45
45
  if (_resourceEquivalents === null) {
46
- _resourceEquivalents = loadJsonFile(
47
- "resource-equivalents.json"
48
- );
46
+ _resourceEquivalents = loadJsonFile("resource-equivalents.json");
49
47
  }
50
48
  return _resourceEquivalents;
51
49
  }
@@ -69,25 +67,19 @@ function getStorageMap() {
69
67
  }
70
68
  function getAwsInstances() {
71
69
  if (_awsInstances === null) {
72
- _awsInstances = loadJsonFile(
73
- "instance-types/aws-instances.json"
74
- );
70
+ _awsInstances = loadJsonFile("instance-types/aws-instances.json");
75
71
  }
76
72
  return _awsInstances;
77
73
  }
78
74
  function getAzureVmSizes() {
79
75
  if (_azureVmSizes === null) {
80
- _azureVmSizes = loadJsonFile(
81
- "instance-types/azure-vm-sizes.json"
82
- );
76
+ _azureVmSizes = loadJsonFile("instance-types/azure-vm-sizes.json");
83
77
  }
84
78
  return _azureVmSizes;
85
79
  }
86
80
  function getGcpMachineTypes() {
87
81
  if (_gcpMachineTypes === null) {
88
- _gcpMachineTypes = loadJsonFile(
89
- "instance-types/gcp-machine-types.json"
90
- );
82
+ _gcpMachineTypes = loadJsonFile("instance-types/gcp-machine-types.json");
91
83
  }
92
84
  return _gcpMachineTypes;
93
85
  }
@@ -125,9 +117,7 @@ function getGcpDiskPricing() {
125
117
  }
126
118
  function getRegionPriceMultipliers() {
127
119
  if (_regionPriceMultipliers === null) {
128
- _regionPriceMultipliers = loadJsonFile(
129
- "region-price-multipliers.json"
130
- );
120
+ _regionPriceMultipliers = loadJsonFile("region-price-multipliers.json");
131
121
  }
132
122
  return _regionPriceMultipliers;
133
123
  }
@@ -161,4 +151,4 @@ export {
161
151
  getRegionPriceMultipliers,
162
152
  _resetLoaderCache
163
153
  };
164
- //# sourceMappingURL=chunk-XDBTEI42.js.map
154
+ //# sourceMappingURL=chunk-TRRAOOVF.js.map