From 20e5ede69dc47f9d0a57a90c1ef170a14d4dc8f5 Mon Sep 17 00:00:00 2001 From: Andrea Cappelletti Date: Tue, 29 Sep 2026 15:28:26 -0400 Subject: [PATCH] catalog: sync AWS Keyspaces, S3 Tables, CloudFront Functions, TGW peering and the transit gateway kind fix Mirrors c3x-pricing-api#71 (contributed by @juan-vg). Regenerates docs/catalog.md and CATALOG_STATUS.md. --- CATALOG_STATUS.md | 11 +- CHANGELOG.md | 13 +++ docs/catalog.md | 29 ++++- resources/aws/aws_ami_copy.toml | 28 +++++ resources/aws/aws_cloudfront_function.toml | 30 +++++ ...eway.toml => aws_ec2_transit_gateway.toml} | 2 +- ...c2_transit_gateway_peering_attachment.toml | 30 +++++ resources/aws/aws_keyspaces_table.toml | 103 ++++++++++++++++++ resources/aws/aws_s3tables_table_bucket.toml | 86 +++++++++++++++ resources/aws/free.toml | 18 +++ 10 files changed, 340 insertions(+), 10 deletions(-) create mode 100644 resources/aws/aws_ami_copy.toml create mode 100644 resources/aws/aws_cloudfront_function.toml rename resources/aws/{aws_transit_gateway.toml => aws_ec2_transit_gateway.toml} (94%) create mode 100644 resources/aws/aws_ec2_transit_gateway_peering_attachment.toml create mode 100644 resources/aws/aws_keyspaces_table.toml create mode 100644 resources/aws/aws_s3tables_table_bucket.toml diff --git a/CATALOG_STATUS.md b/CATALOG_STATUS.md index cfe77505..aab8d011 100644 --- a/CATALOG_STATUS.md +++ b/CATALOG_STATUS.md @@ -14,13 +14,14 @@ Verified against `pricing.c3x.dev` on 2026-09-24: | Result | Kinds | |---|---:| -| **LIVE** (priced from the upstream API, tracks vendor price changes) | 164 | +| **LIVE** (priced from the upstream API, tracks vendor price changes) | 168 | | **STATIC** (priced from an inline rate, does not track upstream changes) | 109 | -| **FREE** (not charged at the resource level) | 1,067 | -| **ZERO / DRIFT / NOFIX / STALE / ERRORED** | 0 | -| **Total** | **1,340** | +| **FREE** (not charged at the resource level) | 1,083 | +| **ZERO** (`aws_keyspaces_table`: its AmazonMCS prices arrive with the next pricing-API scrape) | 1 | +| **DRIFT / NOFIX / STALE / ERRORED** | 0 | +| **Total** | **1,361** | -So 273 kinds carry a price and the remaining 1,067 are legitimately free. +So 278 kinds carry a price (one waiting for its first scrape) and the remaining 1,083 are legitimately free. The per-kind matrix is generated at [`docs/catalog.md`](docs/catalog.md); it is the list, and this page is only the summary. Counts are deliberately diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ba268d9..c60b07ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,19 @@ uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- Catalog: `aws_keyspaces_table`, `aws_s3tables_table_bucket`, + `aws_cloudfront_function`, `aws_ec2_transit_gateway_peering_attachment` + and `aws_ami_copy` are priced, and 17 more AWS kinds are recognised as + free. Contributed by @juan-vg in c3x-pricing-api#71. + +### Fixed + +- Transit gateways were never priced: the catalog entry was keyed on + `aws_transit_gateway`, which is not a Terraform resource type. It is + now `aws_ec2_transit_gateway`. + ## [0.3.19] - 2026-09-29 ### Changed diff --git a/docs/catalog.md b/docs/catalog.md index 9acccc89..d17094a8 100644 --- a/docs/catalog.md +++ b/docs/catalog.md @@ -10,7 +10,7 @@ Status meaning: See `docs/upstream-gaps.md` for the per-resource explanation. - **FREE** — no per-resource charge (parent-billed, structural, IAM). -## AWS (625 resources) +## AWS (646 resources) | Kind | Status | Display name | |---|---|---| @@ -26,6 +26,7 @@ Status meaning: | `aws_alb_listener_rule` | FREE | aws_alb_listener_rule | | `aws_alb_target_group` | FREE | aws_alb_target_group | | `aws_alb_target_group_attachment` | FREE | aws_alb_target_group_attachment | +| `aws_ami_copy` | LIVE | AWS AMI Copy | | `aws_ami_launch_permission` | FREE | aws_ami_launch_permission | | `aws_amplify_app` | LIVE | AWS Amplify Hosting App | | `aws_amplify_backend_environment` | FREE | aws_amplify_backend_environment | @@ -113,8 +114,10 @@ Status meaning: | `aws_batch_job_definition` | FREE | aws_batch_job_definition | | `aws_batch_job_queue` | FREE | aws_batch_job_queue | | `aws_batch_scheduling_policy` | FREE | aws_batch_scheduling_policy | +| `aws_bcmdataexports_export` | FREE | aws_bcmdataexports_export | | `aws_chatbot_slack_channel_configuration` | FREE | AWS Chatbot Slack Channel Configuration | | `aws_cloudformation_export` | FREE | aws_cloudformation_export | +| `aws_cloudformation_stack_set` | FREE | aws_cloudformation_stack_set | | `aws_cloudformation_stack_set_instance` | FREE | aws_cloudformation_stack_set_instance | | `aws_cloudformation_type` | FREE | aws_cloudformation_type | | `aws_cloudfront_cache_policy` | FREE | aws_cloudfront_cache_policy | @@ -122,6 +125,7 @@ Status meaning: | `aws_cloudfront_distribution` | LIVE | AWS CloudFront Distribution | | `aws_cloudfront_field_level_encryption_config` | FREE | aws_cloudfront_field_level_encryption_config | | `aws_cloudfront_field_level_encryption_profile` | FREE | aws_cloudfront_field_level_encryption_profile | +| `aws_cloudfront_function` | LIVE | AWS CloudFront Function | | `aws_cloudfront_key_group` | FREE | aws_cloudfront_key_group | | `aws_cloudfront_key_value_store` | FREE | aws_cloudfront_key_value_store | | `aws_cloudfront_monitoring_subscription` | FREE | aws_cloudfront_monitoring_subscription | @@ -137,6 +141,7 @@ Status meaning: | `aws_cloudwatch_dashboard` | STATIC | AWS CloudWatch Dashboard | | `aws_cloudwatch_event_api_destination` | FREE | aws_cloudwatch_event_api_destination | | `aws_cloudwatch_event_archive` | FREE | aws_cloudwatch_event_archive | +| `aws_cloudwatch_event_bus` | FREE | aws_cloudwatch_event_bus | | `aws_cloudwatch_event_bus_policy` | FREE | aws_cloudwatch_event_bus_policy | | `aws_cloudwatch_event_connection` | FREE | aws_cloudwatch_event_connection | | `aws_cloudwatch_event_endpoint` | FREE | aws_cloudwatch_event_endpoint | @@ -201,6 +206,7 @@ Status meaning: | `aws_datasync_location_smb` | FREE | aws_datasync_location_smb | | `aws_datasync_task` | FREE | aws_datasync_task | | `aws_dax_cluster` | LIVE | AWS DAX Cluster | +| `aws_db_event_subscription` | FREE | aws_db_event_subscription | | `aws_db_instance` | LIVE | AWS RDS Instance | | `aws_db_option_group` | FREE | AWS Db Option Group | | `aws_db_parameter_group` | FREE | AWS Db Parameter Group | @@ -253,17 +259,22 @@ Status meaning: | `aws_ec2_serial_console_access` | FREE | aws_ec2_serial_console_access | | `aws_ec2_subnet_cidr_reservation` | FREE | aws_ec2_subnet_cidr_reservation | | `aws_ec2_tag` | FREE | aws_ec2_tag | +| `aws_ec2_transit_gateway` | LIVE | AWS Transit Gateway | +| `aws_ec2_transit_gateway_peering_attachment` | LIVE | AWS Transit Gateway Peering Attachment | +| `aws_ec2_transit_gateway_peering_attachment_accepter` | FREE | aws_ec2_transit_gateway_peering_attachment_accepter | | `aws_ec2_transit_gateway_route` | FREE | aws_ec2_transit_gateway_route | | `aws_ec2_transit_gateway_route_table` | FREE | aws_ec2_transit_gateway_route_table | | `aws_ec2_transit_gateway_route_table_association` | FREE | aws_ec2_transit_gateway_route_table_association | | `aws_ec2_transit_gateway_route_table_propagation` | FREE | aws_ec2_transit_gateway_route_table_propagation | | `aws_ec2_transit_gateway_vpc_attachment` | STATIC | AWS Transit Gateway VPC Attachment | +| `aws_ec2_transit_gateway_vpc_attachment_accepter` | FREE | aws_ec2_transit_gateway_vpc_attachment_accepter | | `aws_ecr_lifecycle_policy` | FREE | aws_ecr_lifecycle_policy | | `aws_ecr_pull_through_cache_rule` | FREE | aws_ecr_pull_through_cache_rule | | `aws_ecr_registry_policy` | FREE | aws_ecr_registry_policy | | `aws_ecr_registry_scanning_configuration` | FREE | aws_ecr_registry_scanning_configuration | | `aws_ecr_replication_configuration` | FREE | aws_ecr_replication_configuration | | `aws_ecr_repository` | LIVE | AWS ECR Repository | +| `aws_ecr_repository_creation_template` | FREE | aws_ecr_repository_creation_template | | `aws_ecr_repository_policy` | FREE | aws_ecr_repository_policy | | `aws_ecrpublic_repository` | FREE | aws_ecrpublic_repository | | `aws_ecrpublic_repository_policy` | FREE | aws_ecrpublic_repository_policy | @@ -306,6 +317,8 @@ Status meaning: | `aws_glacier_vault` | LIVE | AWS S3 Glacier Vault | | `aws_glacier_vault_lock` | FREE | aws_glacier_vault_lock | | `aws_globalaccelerator_accelerator` | STATIC | AWS Global Accelerator | +| `aws_globalaccelerator_endpoint_group` | FREE | aws_globalaccelerator_endpoint_group | +| `aws_globalaccelerator_listener` | FREE | aws_globalaccelerator_listener | | `aws_glue_catalog_database` | FREE | AWS Glue Data Catalog Database | | `aws_glue_catalog_table` | FREE | aws_glue_catalog_table | | `aws_glue_classifier` | FREE | aws_glue_classifier | @@ -378,6 +391,8 @@ Status meaning: | `aws_iot_topic_rule` | FREE | aws_iot_topic_rule | | `aws_kendra_index` | LIVE | AWS Kendra Index | | `aws_key_pair` | FREE | aws_key_pair | +| `aws_keyspaces_keyspace` | FREE | aws_keyspaces_keyspace | +| `aws_keyspaces_table` | LIVE | AWS Keyspaces Table | | `aws_kinesis_firehose_delivery_stream` | LIVE | AWS Kinesis Data Firehose | | `aws_kinesis_resource_policy` | FREE | aws_kinesis_resource_policy | | `aws_kinesis_stream` | LIVE | AWS Kinesis Data Stream | @@ -397,6 +412,7 @@ Status meaning: | `aws_lambda_function` | LIVE | AWS Lambda Function | | `aws_lambda_function_event_invoke_config` | FREE | aws_lambda_function_event_invoke_config | | `aws_lambda_function_url` | FREE | AWS Lambda Function Url | +| `aws_lambda_invocation` | FREE | aws_lambda_invocation | | `aws_lambda_layer_version` | FREE | AWS Lambda Layer Version | | `aws_lambda_layer_version_permission` | FREE | aws_lambda_layer_version_permission | | `aws_lambda_permission` | FREE | AWS Lambda Permission | @@ -458,6 +474,7 @@ Status meaning: | `aws_ram_sharing_with_organization` | FREE | aws_ram_sharing_with_organization | | `aws_rds_cluster` | LIVE | AWS Aurora Cluster | | `aws_rds_cluster_instance` | LIVE | AWS Aurora Cluster Instance | +| `aws_rds_cluster_parameter_group` | FREE | aws_rds_cluster_parameter_group | | `aws_redshift_cluster` | LIVE | AWS Redshift Cluster | | `aws_redshift_parameter_group` | FREE | AWS Redshift Parameter Group | | `aws_redshift_resource_policy` | FREE | aws_redshift_resource_policy | @@ -511,6 +528,9 @@ Status meaning: | `aws_s3_object` | FREE | AWS S3 Object | | `aws_s3control_access_point_policy` | FREE | aws_s3control_access_point_policy | | `aws_s3control_bucket_policy` | FREE | aws_s3control_bucket_policy | +| `aws_s3tables_namespace` | FREE | aws_s3tables_namespace | +| `aws_s3tables_table_bucket` | LIVE | AWS S3 Table Bucket | +| `aws_s3tables_table_policy` | FREE | aws_s3tables_table_policy | | `aws_sagemaker_endpoint` | STATIC | AWS SageMaker Endpoint | | `aws_sagemaker_notebook_instance` | LIVE | AWS SageMaker Notebook Instance | | `aws_scheduler_schedule` | FREE | aws_scheduler_schedule | @@ -546,6 +566,7 @@ Status meaning: | `aws_ses_domain_mail_from` | FREE | aws_ses_domain_mail_from | | `aws_ses_email_identity` | FREE | aws_ses_email_identity | | `aws_ses_event_destination` | FREE | aws_ses_event_destination | +| `aws_ses_identity_notification_topic` | FREE | aws_ses_identity_notification_topic | | `aws_ses_identity_policy` | FREE | aws_ses_identity_policy | | `aws_ses_receipt_filter` | FREE | aws_ses_receipt_filter | | `aws_ses_receipt_rule` | FREE | aws_ses_receipt_rule | @@ -596,7 +617,6 @@ Status meaning: | `aws_transfer_tag` | FREE | aws_transfer_tag | | `aws_transfer_user` | FREE | aws_transfer_user | | `aws_transfer_workflow` | FREE | aws_transfer_workflow | -| `aws_transit_gateway` | LIVE | AWS Transit Gateway | | `aws_volume_attachment` | FREE | aws_volume_attachment | | `aws_vpc` | FREE | AWS Vpc | | `aws_vpc_dhcp_options` | FREE | aws_vpc_dhcp_options | @@ -605,6 +625,7 @@ Status meaning: | `aws_vpc_endpoint_connection_accepter` | FREE | aws_vpc_endpoint_connection_accepter | | `aws_vpc_endpoint_connection_notification` | FREE | aws_vpc_endpoint_connection_notification | | `aws_vpc_endpoint_policy` | FREE | aws_vpc_endpoint_policy | +| `aws_vpc_endpoint_private_dns` | FREE | aws_vpc_endpoint_private_dns | | `aws_vpc_endpoint_route_table_association` | FREE | aws_vpc_endpoint_route_table_association | | `aws_vpc_endpoint_security_group_association` | FREE | aws_vpc_endpoint_security_group_association | | `aws_vpc_endpoint_service` | FREE | aws_vpc_endpoint_service | @@ -640,7 +661,7 @@ Status meaning: | `aws_workspaces_workspace` | LIVE | AWS WorkSpaces Desktop | | `aws_xray_group` | LIVE | AWS X-Ray Group | -**AWS totals:** 90 LIVE · 20 STATIC · 515 FREE +**AWS totals:** 95 LIVE · 20 STATIC · 531 FREE ## AZURE (409 resources) @@ -1373,4 +1394,4 @@ Status meaning: --- -**Grand total: 1340 resources.** 188 LIVE · 85 STATIC · 1067 FREE. +**Grand total: 1361 resources.** 193 LIVE · 85 STATIC · 1083 FREE. diff --git a/resources/aws/aws_ami_copy.toml b/resources/aws/aws_ami_copy.toml new file mode 100644 index 00000000..971fc733 --- /dev/null +++ b/resources/aws/aws_ami_copy.toml @@ -0,0 +1,28 @@ +kind = "aws_ami_copy" +display_name = "AWS AMI Copy" +provider = "aws" + +# An AMI itself is free. The copy creates EBS snapshots in the +# destination region, and those bill per GB-month at the standard +# snapshot rate ($0.05/GB-month in us-east-1). + +[mappings.snapshot_storage] +service = "AmazonEC2" +product_family = "Storage Snapshot" +attribute_filters = [ + { key = "usagetype", const = "EBS:SnapshotUsage" }, +] + +[[dimensions]] +id = "snapshot_storage" +label = "Copied snapshot storage" +unit = "GB-month" +when = 'sum_field(ebs_block_device, "volume_size") > 0' +quantity = 'sum_field(ebs_block_device, "volume_size")' +rate = 'price("snapshot_storage")' + +[fixture] +attributes = { ebs_block_device = [{ volume_size = 8 }] } +expected_monthly_cost = 0.4 +tolerance = 0.05 +last_verified = "2026-09-29" diff --git a/resources/aws/aws_cloudfront_function.toml b/resources/aws/aws_cloudfront_function.toml new file mode 100644 index 00000000..606fe82e --- /dev/null +++ b/resources/aws/aws_cloudfront_function.toml @@ -0,0 +1,30 @@ +kind = "aws_cloudfront_function" +display_name = "AWS CloudFront Function" +provider = "aws" + +# CloudFront Functions bill per execution, at one global rate (the SKU +# carries location "Any", so the mapping pins region = "global"). +# $0.10 per 1,000,000 executions after the first 2,000,000 free. +# The free tier is a $0 price dimension on the same SKU; the price +# picker skips zeros and returns the paid rate. + +[mappings.executions] +service = "AmazonCloudFront" +product_family = "Request" +region = "global" +attribute_filters = [ + { key = "usagetype", const = "Executions-CloudFrontFunctions" }, +] + +[[dimensions]] +id = "executions" +label = "Function executions" +unit = "executions" +quantity = "default(monthly_invocations, 0)" +rate = 'price("executions")' + +[fixture] +attributes = { monthly_invocations = 10_000_000 } +expected_monthly_cost = 1 +tolerance = 0.05 +last_verified = "2026-09-29" diff --git a/resources/aws/aws_transit_gateway.toml b/resources/aws/aws_ec2_transit_gateway.toml similarity index 94% rename from resources/aws/aws_transit_gateway.toml rename to resources/aws/aws_ec2_transit_gateway.toml index 304d3ab3..b60bd332 100644 --- a/resources/aws/aws_transit_gateway.toml +++ b/resources/aws/aws_ec2_transit_gateway.toml @@ -1,4 +1,4 @@ -kind = "aws_transit_gateway" +kind = "aws_ec2_transit_gateway" display_name = "AWS Transit Gateway" provider = "aws" diff --git a/resources/aws/aws_ec2_transit_gateway_peering_attachment.toml b/resources/aws/aws_ec2_transit_gateway_peering_attachment.toml new file mode 100644 index 00000000..21ef79a4 --- /dev/null +++ b/resources/aws/aws_ec2_transit_gateway_peering_attachment.toml @@ -0,0 +1,30 @@ +kind = "aws_ec2_transit_gateway_peering_attachment" +display_name = "AWS Transit Gateway Peering Attachment" +provider = "aws" + +# Every Transit Gateway attachment type (VPC, VPN, Connect, DirectConnect, +# Peering) shares usagetype TransitGateway-Hours at $0.05/hour under +# service AmazonVPC. Data processed bills on the parent +# aws_ec2_transit_gateway resource. +# The accepter side of a cross-account peering is free: one attachment, +# one charge. + +[mappings.attachment_hours] +service = "AmazonVPC" +product_family = "" +attribute_filters = [ + { key = "usagetype", const = "USE1-TransitGateway-Hours" }, +] + +[[dimensions]] +id = "attachment_hours" +label = "TGW peering attachment" +unit = "hours" +quantity = "monthly_hours()" +rate = 'price("attachment_hours")' + +[fixture] +attributes = {} +expected_monthly_cost = 36.5 +tolerance = 0.05 +last_verified = "2026-09-29" diff --git a/resources/aws/aws_keyspaces_table.toml b/resources/aws/aws_keyspaces_table.toml new file mode 100644 index 00000000..86be605d --- /dev/null +++ b/resources/aws/aws_keyspaces_table.toml @@ -0,0 +1,103 @@ +kind = "aws_keyspaces_table" +display_name = "AWS Keyspaces Table" +provider = "aws" + +# Keyspaces (Cassandra) bills under offer code AmazonMCS, with the same +# shape as DynamoDB: on-demand request units or provisioned capacity +# units, plus storage and optional PITR backup storage. +# Probed us-east-1 2026-09-29: 9 SKUs, group MCS-ReadUnits/MCS-WriteUnits. + +[mappings.read_request_units] +service = "AmazonMCS" +product_family = "PayPerRequest Throughput" +attribute_filters = [ + { key = "group", const = "MCS-ReadUnits" }, +] + +[mappings.write_request_units] +service = "AmazonMCS" +product_family = "PayPerRequest Throughput" +attribute_filters = [ + { key = "group", const = "MCS-WriteUnits" }, +] + +[mappings.provisioned_read] +service = "AmazonMCS" +product_family = "Provisioned IOPS" +attribute_filters = [ + { key = "group", const = "MCS-ReadUnits" }, +] + +[mappings.provisioned_write] +service = "AmazonMCS" +product_family = "Provisioned IOPS" +attribute_filters = [ + { key = "group", const = "MCS-WriteUnits" }, +] + +[mappings.storage] +service = "AmazonMCS" +product_family = "Database Storage" +attribute_filters = [ + { key = "usagetype", const = "TimedStorage-ByteHrs" }, +] + +[mappings.pitr] +service = "AmazonMCS" +product_family = "Database Storage" +attribute_filters = [ + { key = "usagetype", const = "USE1-TimedPITRStorage-ByteHrs" }, +] + +[[dimensions]] +id = "read_request_units" +label = "Read request units" +unit = "request units" +when = 'default(capacity_specification_throughput_mode, "PAY_PER_REQUEST") == "PAY_PER_REQUEST"' +quantity = "default(monthly_read_request_units, 0)" +rate = 'price("read_request_units")' + +[[dimensions]] +id = "write_request_units" +label = "Write request units" +unit = "request units" +when = 'default(capacity_specification_throughput_mode, "PAY_PER_REQUEST") == "PAY_PER_REQUEST"' +quantity = "default(monthly_write_request_units, 0)" +rate = 'price("write_request_units")' + +[[dimensions]] +id = "read_capacity" +label = "Provisioned read capacity" +unit = "RCU-hours" +when = 'default(capacity_specification_throughput_mode, "PAY_PER_REQUEST") == "PROVISIONED"' +quantity = "default(capacity_specification_read_capacity_units, 1) * monthly_hours()" +rate = 'price("provisioned_read")' + +[[dimensions]] +id = "write_capacity" +label = "Provisioned write capacity" +unit = "WCU-hours" +when = 'default(capacity_specification_throughput_mode, "PAY_PER_REQUEST") == "PROVISIONED"' +quantity = "default(capacity_specification_write_capacity_units, 1) * monthly_hours()" +rate = 'price("provisioned_write")' + +[[dimensions]] +id = "storage" +label = "Data storage" +unit = "GB-month" +quantity = "default(storage_gb, 0)" +rate = 'price("storage")' + +[[dimensions]] +id = "pitr_backup" +label = "Point-in-time recovery storage" +unit = "GB-month" +when = 'default(point_in_time_recovery_status, "DISABLED") == "ENABLED" && default(storage_gb, 0) > 0' +quantity = "default(storage_gb, 0)" +rate = 'price("pitr")' + +[fixture] +attributes = { capacity_specification_throughput_mode = "PROVISIONED", capacity_specification_read_capacity_units = 10, capacity_specification_write_capacity_units = 10, storage_gb = 100 } +expected_monthly_cost = 30.694 +tolerance = 0.05 +last_verified = "2026-09-29" diff --git a/resources/aws/aws_s3tables_table_bucket.toml b/resources/aws/aws_s3tables_table_bucket.toml new file mode 100644 index 00000000..c92b4f4c --- /dev/null +++ b/resources/aws/aws_s3tables_table_bucket.toml @@ -0,0 +1,86 @@ +kind = "aws_s3tables_table_bucket" +display_name = "AWS S3 Table Bucket" +provider = "aws" + +# S3 Tables bills under offer code AmazonS3 with a Tables- usagetype +# family and an empty productFamily (probed us-east-1 2026-09-29). +# Storage, requests, and the automatic maintenance charges (object +# monitoring and compaction) all bill on the table bucket. +# Rates are the first storage tier; the price picker takes the highest +# non-zero match, which is the first (most expensive) tier. + +[mappings.storage] +service = "AmazonS3" +product_family = "" +attribute_filters = [ + { key = "usagetype", const = "Tables-TimedStorage-ByteHrs" }, +] + +[mappings.tier_1_requests] +service = "AmazonS3" +product_family = "" +attribute_filters = [ + { key = "group", const = "S3-API-Tables-Tier1" }, +] + +[mappings.tier_2_requests] +service = "AmazonS3" +product_family = "" +attribute_filters = [ + { key = "group", const = "S3-API-Tables-Tier2" }, +] + +[mappings.monitored_objects] +service = "AmazonS3" +product_family = "" +attribute_filters = [ + { key = "usagetype", const = "Tables-MonitoredObjects" }, +] + +[mappings.compaction] +service = "AmazonS3" +product_family = "" +attribute_filters = [ + { key = "usagetype", const = "Tables-ProcessedBytes" }, +] + +[[dimensions]] +id = "storage" +label = "Table storage" +unit = "GB-month" +quantity = "default(storage_gb, 0)" +rate = 'price("storage")' + +[[dimensions]] +id = "tier_1_requests" +label = "PUT, COPY, POST, LIST requests" +unit = "requests" +quantity = "default(monthly_tier_1_requests, 0)" +rate = 'price("tier_1_requests")' + +[[dimensions]] +id = "tier_2_requests" +label = "GET and all other requests" +unit = "requests" +quantity = "default(monthly_tier_2_requests, 0)" +rate = 'price("tier_2_requests")' + +[[dimensions]] +id = "monitored_objects" +label = "Object monitoring" +unit = "objects" +quantity = "default(monthly_monitored_objects, 0)" +rate = 'price("monitored_objects")' + +[[dimensions]] +id = "compaction" +label = "Compaction data processed" +unit = "GB" +quantity = "default(monthly_compacted_gb, 0)" +rate = 'price("compaction")' + +[fixture] +attributes = { storage_gb = 100, monthly_tier_1_requests = 100_000, monthly_tier_2_requests = 1_000_000, monthly_monitored_objects = 100_000, monthly_compacted_gb = 100 } +expected_monthly_cost = 6.55 +tolerance = 0.05 +last_verified = "2026-09-29" diff --git a/resources/aws/free.toml b/resources/aws/free.toml index c67c090f..8c51dd85 100644 --- a/resources/aws/free.toml +++ b/resources/aws/free.toml @@ -471,3 +471,21 @@ provider = "aws" "aws_dx_private_virtual_interface" = "Direct Connect wiring - ports/transfer bill on the connection" "aws_dx_public_virtual_interface" = "Direct Connect wiring - ports/transfer bill on the connection" "aws_dx_transit_virtual_interface" = "Direct Connect wiring - ports/transfer bill on the connection" + +# --- round 3 additions --- +"aws_keyspaces_keyspace" = "Keyspaces container - throughput and storage bill on the table" +"aws_s3tables_namespace" = "S3 Tables container - storage and requests bill on the table bucket" +"aws_s3tables_table_policy" = "resource policy document - no charge" +"aws_rds_cluster_parameter_group" = "RDS configuration - compute and storage bill on the cluster" +"aws_db_event_subscription" = "RDS event routing - notifications bill on the SNS topic" +"aws_ses_identity_notification_topic" = "SES configuration - emails bill per message" +"aws_cloudformation_stack_set" = "CloudFormation is free - the provisioned resources bill themselves" +"aws_vpc_endpoint_private_dns" = "endpoint setting - hours and data bill on the VPC endpoint" +"aws_ecr_repository_creation_template" = "ECR wiring - storage bills on the repository" +"aws_ec2_transit_gateway_vpc_attachment_accepter" = "accepter side of an existing attachment - hours bill once, on the attachment" +"aws_ec2_transit_gateway_peering_attachment_accepter" = "accepter side of an existing attachment - hours bill once, on the attachment" +"aws_globalaccelerator_listener" = "Global Accelerator wiring - fixed fee and data transfer bill on the accelerator" +"aws_globalaccelerator_endpoint_group" = "Global Accelerator wiring - fixed fee and data transfer bill on the accelerator" +"aws_cloudwatch_event_bus" = "custom bus is free - events bill per published event" +"aws_lambda_invocation" = "provisioning-time invocation - runtime bills on the function" +"aws_bcmdataexports_export" = "Data Exports has no charge - the delivered files bill as S3 storage"