From 35d6533e0e64ace0094d1e21a83765591fe34944 Mon Sep 17 00:00:00 2001 From: HarshCasper Date: Wed, 25 Feb 2026 15:06:03 +0530 Subject: [PATCH 1/3] add auto-generated CloudFormation Feature Coverage table --- scripts/create_cloudformation_coverage.py | 283 ++ .../CloudFormationCoverage.tsx | 308 +++ .../docs/aws/services/cloudformation.mdx | 261 +- src/data/cloudformation/coverage.json | 2464 +++++++++++++++++ 4 files changed, 3057 insertions(+), 259 deletions(-) create mode 100644 scripts/create_cloudformation_coverage.py create mode 100644 src/components/cloudformation-coverage/CloudFormationCoverage.tsx create mode 100644 src/data/cloudformation/coverage.json diff --git a/scripts/create_cloudformation_coverage.py b/scripts/create_cloudformation_coverage.py new file mode 100644 index 00000000..d3a50a96 --- /dev/null +++ b/scripts/create_cloudformation_coverage.py @@ -0,0 +1,283 @@ +from __future__ import annotations + +import argparse +import json +import os +import re +import sys +from datetime import datetime, timezone +from pathlib import Path +from typing import Any +from urllib.error import HTTPError, URLError +from urllib.request import Request, urlopen + +NOTION_API_BASE = "https://api.notion.com/v1" +NOTION_VERSION = "2022-06-28" +DEFAULT_DATABASE_ID = "9b3ebbcc1f6749fb908eb2e3582386b0" +DEFAULT_OUTPUT_PATH = Path("src/data/cloudformation/coverage.json") + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Generate CloudFormation resource coverage data from Notion." + ) + parser.add_argument( + "--database-id", + default=DEFAULT_DATABASE_ID, + help="Notion database ID to query.", + ) + parser.add_argument( + "--output", + type=Path, + default=DEFAULT_OUTPUT_PATH, + help="Output JSON file path.", + ) + parser.add_argument( + "--notion-secret", + default=os.getenv("NOTION_SECRET"), + help="Notion API secret. Defaults to NOTION_SECRET environment variable.", + ) + return parser.parse_args() + + +def normalize_key(value: str) -> str: + return re.sub(r"[^a-z0-9]", "", value.lower()) + + +def resolve_property_name(properties: dict[str, Any], candidates: list[str]) -> str | None: + normalized_map = {normalize_key(key): key for key in properties.keys()} + for candidate in candidates: + if key := normalized_map.get(normalize_key(candidate)): + return key + return None + + +def extract_plain_text(items: list[dict[str, Any]]) -> str: + return "".join(item.get("plain_text", "") for item in items).strip() + + +def extract_property_value(prop: dict[str, Any] | None) -> Any: + if not prop: + return "" + + prop_type = prop.get("type") + if prop_type == "title": + return extract_plain_text(prop.get("title", [])) + if prop_type == "rich_text": + return extract_plain_text(prop.get("rich_text", [])) + if prop_type == "select": + select_value = prop.get("select") + return (select_value or {}).get("name", "") + if prop_type == "multi_select": + return ", ".join(item.get("name", "") for item in prop.get("multi_select", [])) + if prop_type == "status": + status_value = prop.get("status") + return (status_value or {}).get("name", "") + if prop_type == "checkbox": + return bool(prop.get("checkbox", False)) + if prop_type == "number": + return prop.get("number") + if prop_type == "url": + return prop.get("url", "") + if prop_type == "email": + return prop.get("email", "") + if prop_type == "phone_number": + return prop.get("phone_number", "") + if prop_type == "formula": + formula = prop.get("formula", {}) + formula_type = formula.get("type") + if formula_type == "string": + return formula.get("string", "") or "" + if formula_type == "boolean": + return bool(formula.get("boolean", False)) + if formula_type == "number": + return formula.get("number") + if formula_type == "date": + date_value = formula.get("date") or {} + return date_value.get("start", "") + return "" + return "" + + +def to_bool(value: Any) -> bool: + if isinstance(value, bool): + return value + if value is None: + return False + if isinstance(value, (int, float)): + return bool(value) + + normalized = str(value).strip().lower() + return normalized in {"true", "1", "yes", "y", "supported", "enabled"} + + +def normalize_tier(value: Any, is_open_source: Any) -> str: + if isinstance(value, str) and value.strip(): + normalized = value.strip().lower() + if normalized in {"community", "oss", "open source", "opensource"}: + return "Community" + if normalized in {"pro", "enterprise"}: + return "Pro" + return value.strip() + + if to_bool(is_open_source): + return "Community" + return "Pro" + + +def derive_service(service_value: Any, resource_type: str) -> str: + if isinstance(service_value, str) and service_value.strip(): + return service_value.strip() + + match = re.match(r"^[A-Za-z0-9]+::([^:]+)::", resource_type) + if match: + return match.group(1) + return "" + + +def notion_post(path: str, secret: str, payload: dict[str, Any]) -> dict[str, Any]: + request = Request( + url=f"{NOTION_API_BASE}{path}", + data=json.dumps(payload).encode("utf-8"), + headers={ + "Authorization": f"Bearer {secret}", + "Notion-Version": NOTION_VERSION, + "Content-Type": "application/json", + }, + method="POST", + ) + try: + with urlopen(request) as response: + return json.loads(response.read().decode("utf-8")) + except HTTPError as err: + body = err.read().decode("utf-8", errors="ignore") + raise RuntimeError(f"Notion API error ({err.code}): {body}") from err + except URLError as err: + raise RuntimeError(f"Notion request failed: {err.reason}") from err + + +def collect_pages(database_id: str, notion_secret: str) -> list[dict[str, Any]]: + pages: list[dict[str, Any]] = [] + cursor: str | None = None + + while True: + payload: dict[str, Any] = {"page_size": 100} + if cursor: + payload["start_cursor"] = cursor + + response = notion_post(f"/databases/{database_id}/query", notion_secret, payload) + pages.extend(response.get("results", [])) + + if not response.get("has_more"): + break + cursor = response.get("next_cursor") + if not cursor: + break + + return pages + + +def transform_pages(pages: list[dict[str, Any]]) -> list[dict[str, Any]]: + rows: list[dict[str, Any]] = [] + + for page in pages: + properties = page.get("properties", {}) + + resource_type_key = resolve_property_name( + properties, ["Resource Type", "Resource", "Type"] + ) + identifier_path_key = resolve_property_name( + properties, + [ + "Primary Identifier Path(s)", + "Primary Identifier Paths", + "Primary Identifier Path", + ], + ) + service_key = resolve_property_name(properties, ["Service"]) + supports_update_key = resolve_property_name( + properties, + [ + "Supports Update", + "Should support Update", + "Update Supported", + "Update", + ], + ) + tier_key = resolve_property_name( + properties, + ["Community or Pro", "Tier", "Edition", "Image", "Provider version"], + ) + is_open_source_key = resolve_property_name( + properties, ["Is open source", "Open Source", "Is OSS"] + ) + + resource_type = str( + extract_property_value(properties.get(resource_type_key)) if resource_type_key else "" + ).strip() + if not resource_type: + continue + + primary_identifier_paths = str( + extract_property_value(properties.get(identifier_path_key)) + if identifier_path_key + else "" + ).strip() + service = derive_service( + extract_property_value(properties.get(service_key)) if service_key else "", + resource_type, + ) + supports_update = to_bool( + extract_property_value(properties.get(supports_update_key)) + if supports_update_key + else False + ) + tier = normalize_tier( + extract_property_value(properties.get(tier_key)) if tier_key else "", + extract_property_value(properties.get(is_open_source_key)) + if is_open_source_key + else False, + ) + + rows.append( + { + "resource_type": resource_type, + "primary_identifier_paths": primary_identifier_paths, + "service": service, + "create": True, + "delete": True, + "update": supports_update, + "tier": tier, + } + ) + + rows.sort(key=lambda item: (item["tier"], item["service"], item["resource_type"])) + return rows + + +def write_output(output_path: Path, database_id: str, resources: list[dict[str, Any]]) -> None: + output_path.parent.mkdir(parents=True, exist_ok=True) + payload = { + "generated_at": datetime.now(timezone.utc).isoformat(), + "database_id": database_id, + "total_resources": len(resources), + "resources": resources, + } + output_path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8") + + +def main() -> None: + args = parse_args() + + if not args.notion_secret: + print("Please provide a Notion token via --notion-secret or NOTION_SECRET.") + sys.exit(1) + + pages = collect_pages(database_id=args.database_id, notion_secret=args.notion_secret) + resources = transform_pages(pages) + write_output(args.output, args.database_id, resources) + print(f"Wrote {len(resources)} resources to {args.output}") + + +if __name__ == "__main__": + main() diff --git a/src/components/cloudformation-coverage/CloudFormationCoverage.tsx b/src/components/cloudformation-coverage/CloudFormationCoverage.tsx new file mode 100644 index 00000000..a28bb62f --- /dev/null +++ b/src/components/cloudformation-coverage/CloudFormationCoverage.tsx @@ -0,0 +1,308 @@ +import React from 'react'; +import data from '@/data/cloudformation/coverage.json'; +import { + useReactTable, + getCoreRowModel, + getSortedRowModel, + getFilteredRowModel, + getPaginationRowModel, + flexRender, +} from '@tanstack/react-table'; +import type { + ColumnDef, + SortingState, + ColumnFiltersState, +} from '@tanstack/react-table'; + +type CloudFormationResource = { + resource_type: string; + primary_identifier_paths: string; + service: string; + create: boolean; + delete: boolean; + update: boolean; + tier: string; +}; + +type CloudFormationCoverageData = { + generated_at: string; + database_id: string; + total_resources: number; + resources: CloudFormationResource[]; +}; + +const coverageData = data as CloudFormationCoverageData; + +const getColumnWidth = (columnId: string): string => { + switch (columnId) { + case 'resource_type': + return '21%'; + case 'primary_identifier_paths': + return '29%'; + case 'service': + return '12%'; + case 'create': + case 'delete': + case 'update': + return '8%'; + case 'tier': + return '14%'; + default: + return '8%'; + } +}; + +const columns: ColumnDef[] = [ + { + accessorKey: 'resource_type', + header: () => 'Resource Type', + cell: ({ row }) => row.original.resource_type, + enableColumnFilter: true, + filterFn: (row, _, filterValue) => + row.original.resource_type + .toLowerCase() + .includes((filterValue ?? '').toLowerCase()), + }, + { + accessorKey: 'primary_identifier_paths', + header: () => 'Primary Identifier Path(s)', + cell: ({ row }) => row.original.primary_identifier_paths || '-', + }, + { + accessorKey: 'service', + header: () => 'Service', + cell: ({ row }) => row.original.service || '-', + }, + { + accessorKey: 'create', + header: () => 'Create', + cell: ({ row }) => (row.original.create ? '✅' : '-'), + enableSorting: true, + sortingFn: (rowA, rowB) => + Number(rowB.original.create) - Number(rowA.original.create), + }, + { + accessorKey: 'delete', + header: () => 'Delete', + cell: ({ row }) => (row.original.delete ? '✅' : '-'), + enableSorting: true, + sortingFn: (rowA, rowB) => + Number(rowB.original.delete) - Number(rowA.original.delete), + }, + { + accessorKey: 'update', + header: () => 'Update', + cell: ({ row }) => (row.original.update ? '✅' : '-'), + enableSorting: true, + sortingFn: (rowA, rowB) => + Number(rowB.original.update) - Number(rowA.original.update), + }, + { + accessorKey: 'tier', + header: () => 'Community / Pro', + cell: ({ row }) => row.original.tier, + enableSorting: true, + }, +]; + +export default function CloudFormationCoverage() { + const [sorting, setSorting] = React.useState([ + { id: 'tier', desc: false }, + { id: 'service', desc: false }, + { id: 'resource_type', desc: false }, + ]); + const [columnFilters, setColumnFilters] = React.useState([]); + + const table = useReactTable({ + data: coverageData.resources, + columns, + state: { sorting, columnFilters }, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getPaginationRowModel: getPaginationRowModel(), + debugTable: false, + initialState: { pagination: { pageSize: 20 } }, + }); + + return ( +
+
+ + table.getColumn('resource_type')?.setFilterValue(e.target.value) + } + className="border rounded px-3 py-2 w-full max-w-sm" + style={{ + color: '#707385', + fontFamily: 'AeonikFono', + fontSize: '14px', + fontWeight: '500', + lineHeight: '24px', + letterSpacing: '-0.2px', + }} + /> +
+ +
+ + + {table.getAllLeafColumns().map((column) => ( + + ))} + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + const canSort = header.column.getCanSort(); + return ( + + ); + })} + + ))} + + + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + ))} + + ))} + +
+ {flexRender( + header.column.columnDef.header, + header.getContext() + )} + {canSort && ( + + {header.column.getIsSorted() === 'asc' + ? ' ▲' + : header.column.getIsSorted() === 'desc' + ? ' ▼' + : ''} + + )} +
+ {flexRender(cell.column.columnDef.cell, cell.getContext())} +
+
+ +
+ + + Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()} + + +
+
+ ); +} diff --git a/src/content/docs/aws/services/cloudformation.mdx b/src/content/docs/aws/services/cloudformation.mdx index 41929d76..70fe0d2f 100644 --- a/src/content/docs/aws/services/cloudformation.mdx +++ b/src/content/docs/aws/services/cloudformation.mdx @@ -6,6 +6,7 @@ tags: ["Free"] --- import FeatureCoverage from "../../../../components/feature-coverage/FeatureCoverage"; +import CloudFormationCoverage from "../../../../components/cloudformation-coverage/CloudFormationCoverage"; import { Tabs, TabItem } from '@astrojs/starlight/components'; @@ -208,265 +209,7 @@ Please exercise caution when using parameters with `NoEcho`. When utilizing the Community image, any resources within the stack that are not supported will be disregarded and won't be deployed. ::: -#### Community image - -| Resource | Create | Delete | Update | -|---------------------------------------------|-------:|-------:|-------:| -| AWS::Amplify::Branch | ✅ | ✅ | - | -| AWS::ApiGateway::Account | ✅ | ✅ | - | -| AWS::ApiGateway::ApiKey | ✅ | ✅ | - | -| AWS::ApiGateway::BasePathMapping | ✅ | ✅ | - | -| AWS::ApiGateway::Deployment | ✅ | ✅ | - | -| AWS::ApiGateway::DomainName | ✅ | ✅ | - | -| AWS::ApiGateway::GatewayResponse | ✅ | ✅ | - | -| AWS::ApiGateway::Method | ✅ | ✅ | ✅ | -| AWS::ApiGateway::Model | ✅ | ✅ | - | -| AWS::ApiGateway::RequestValidator | ✅ | ✅ | - | -| AWS::ApiGateway::Resource | ✅ | ✅ | - | -| AWS::ApiGateway::RestApi | ✅ | ✅ | - | -| AWS::ApiGateway::Stage | ✅ | ✅ | - | -| AWS::ApiGateway::UsagePlan | ✅ | ✅ | ✅ | -| AWS::ApiGateway::UsagePlanKey | ✅ | ✅ | - | -| AWS::AutoScaling::AutoScalingGroup | ✅ | ✅ | - | -| AWS::AutoScaling::LaunchConfiguration | ✅ | ✅ | - | -| AWS::CDK::Metadata | ✅ | ✅ | ✅ | -| AWS::CertificateManager::Certificate | ✅ | ✅ | - | -| AWS::CloudFormation::Macro | ✅ | ✅ | - | -| AWS::CloudFormation::Stack | ✅ | ✅ | - | -| AWS::CloudFormation::WaitCondition | ✅ | ✅ | - | -| AWS::CloudFormation::WaitConditionHandle | ✅ | ✅ | - | -| AWS::CloudWatch::Alarm | ✅ | ✅ | - | -| AWS::CloudWatch::CompositeAlarm | ✅ | ✅ | - | -| AWS::DynamoDB::GlobalTable | ✅ | ✅ | - | -| AWS::DynamoDB::Table | ✅ | ✅ | - | -| AWS::EC2::DHCPOptions | ✅ | ✅ | - | -| AWS::EC2::Instance | ✅ | ✅ | ✅ | -| AWS::EC2::InternetGateway | ✅ | ✅ | - | -| AWS::EC2::KeyPair | ✅ | ✅ | - | -| AWS::EC2::NatGateway | ✅ | ✅ | - | -| AWS::EC2::NetworkAcl | ✅ | ✅ | - | -| AWS::EC2::Route | ✅ | ✅ | - | -| AWS::EC2::RouteTable | ✅ | ✅ | - | -| AWS::EC2::SecurityGroup | ✅ | ✅ | - | -| AWS::EC2::Subnet | ✅ | ✅ | - | -| AWS::EC2::SubnetRouteTableAssociation | ✅ | ✅ | - | -| AWS::EC2::TransitGateway | ✅ | ✅ | - | -| AWS::EC2::TransitGatewayAttachment | ✅ | ✅ | - | -| AWS::EC2::VPC | ✅ | ✅ | - | -| AWS::EC2::VPCGatewayAttachment | ✅ | ✅ | - | -| AWS::ECR::Repository | ✅ | ✅ | - | -| AWS::Elasticsearch::Domain | ✅ | ✅ | - | -| AWS::Events::ApiDestination | ✅ | ✅ | - | -| AWS::Events::Connection | ✅ | ✅ | - | -| AWS::Events::EventBus | ✅ | ✅ | - | -| AWS::Events::EventBusPolicy | ✅ | ✅ | - | -| AWS::Events::Rule | ✅ | ✅ | - | -| AWS::IAM::AccessKey | ✅ | ✅ | ✅ | -| AWS::IAM::Group | ✅ | ✅ | - | -| AWS::IAM::InstanceProfile | ✅ | ✅ | - | -| AWS::IAM::ManagedPolicy | ✅ | ✅ | - | -| AWS::IAM::Policy | ✅ | ✅ | ✅ | -| AWS::IAM::Role | ✅ | ✅ | ✅ | -| AWS::IAM::ServiceLinkedRole | ✅ | ✅ | - | -| AWS::IAM::User | ✅ | ✅ | - | -| AWS::KMS::Alias | ✅ | ✅ | - | -| AWS::KMS::Key | ✅ | ✅ | - | -| AWS::Kinesis::Stream | ✅ | ✅ | - | -| AWS::Kinesis::StreamConsumer | ✅ | ✅ | - | -| AWS::KinesisFirehose::DeliveryStream | ✅ | ✅ | - | -| AWS::Lambda::Alias | ✅ | ✅ | - | -| AWS::Lambda::CodeSigningConfig | ✅ | ✅ | - | -| AWS::Lambda::EventInvokeConfig | ✅ | ✅ | - | -| AWS::Lambda::EventSourceMapping | ✅ | ✅ | - | -| AWS::Lambda::Function | ✅ | ✅ | ✅ | -| AWS::Lambda::LayerVersion | ✅ | ✅ | - | -| AWS::Lambda::LayerVersionPermission | ✅ | ✅ | - | -| AWS::Lambda::Permission | ✅ | ✅ | ✅ | -| AWS::Lambda::Url | ✅ | ✅ | - | -| AWS::Lambda::Version | ✅ | ✅ | - | -| AWS::Logs::LogGroup | ✅ | ✅ | - | -| AWS::Logs::LogStream | ✅ | ✅ | - | -| AWS::Logs::SubscriptionFilter | ✅ | ✅ | - | -| AWS::OpenSearchService::Domain | ✅ | ✅ | - | -| AWS::Redshift::Cluster | ✅ | ✅ | - | -| AWS::ResourceGroups::Group | ✅ | ✅ | - | -| AWS::Route53::HealthCheck | ✅ | ✅ | - | -| AWS::Route53::RecordSet | ✅ | ✅ | - | -| AWS::S3::Bucket | ✅ | ✅ | - | -| AWS::S3::BucketPolicy | ✅ | ✅ | - | -| AWS::SNS::Subscription | ✅ | ✅ | ✅ | -| AWS::SNS::Topic | ✅ | ✅ | ✅ | -| AWS::SNS::TopicPolicy | ✅ | ✅ | - | -| AWS::SQS::Queue | ✅ | ✅ | ✅ | -| AWS::SQS::QueuePolicy | ✅ | ✅ | ✅ | -| AWS::SSM::MaintenanceWindow | ✅ | ✅ | - | -| AWS::SSM::MaintenanceWindowTarget | ✅ | ✅ | - | -| AWS::SSM::MaintenanceWindowTask | ✅ | ✅ | - | -| AWS::SSM::Parameter | ✅ | ✅ | ✅ | -| AWS::SSM::PatchBaseline | ✅ | ✅ | - | -| AWS::Scheduler::Schedule | ✅ | ✅ | - | -| AWS::Scheduler::ScheduleGroup | ✅ | ✅ | - | -| AWS::SecretsManager::ResourcePolicy | ✅ | ✅ | - | -| AWS::SecretsManager::RotationSchedule | ✅ | ✅ | - | -| AWS::SecretsManager::Secret | ✅ | ✅ | - | -| AWS::SecretsManager::SecretTargetAttachment | ✅ | ✅ | - | -| AWS::ServiceDiscovery::HttpNamespace | ✅ | ✅ | - | -| AWS::ServiceDiscovery::PrivateDnsNamespace | ✅ | ✅ | - | -| AWS::ServiceDiscovery::PublicDnsNamespace | ✅ | ✅ | - | -| AWS::ServiceDiscovery::Service | ✅ | ✅ | - | -| AWS::StepFunctions::Activity | ✅ | ✅ | - | -| AWS::StepFunctions::StateMachine | ✅ | ✅ | ✅ | -| AWS::Timestream::Database | ✅ | ✅ | - | -| AWS::Timestream::Table | ✅ | ✅ | - | - -#### Pro image - -| Resource | Create | Delete | Update | -|-------------------------------------------------|-------:|-------:|-------:| -| AWS::Amplify::App | ✅ | ✅ | - | -| AWS::ApiGateway::Authorizer | ✅ | ✅ | - | -| AWS::ApiGateway::VpcLink | ✅ | ✅ | - | -| AWS::ApiGatewayV2::Api | ✅ | ✅ | - | -| AWS::ApiGatewayV2::ApiMapping | ✅ | ✅ | - | -| AWS::ApiGatewayV2::Authorizer | ✅ | ✅ | - | -| AWS::ApiGatewayV2::Deployment | ✅ | ✅ | - | -| AWS::ApiGatewayV2::DomainName | ✅ | ✅ | - | -| AWS::ApiGatewayV2::Integration | ✅ | ✅ | - | -| AWS::ApiGatewayV2::IntegrationResponse | ✅ | ✅ | - | -| AWS::ApiGatewayV2::Route | ✅ | ✅ | - | -| AWS::ApiGatewayV2::RouteResponse | ✅ | ✅ | - | -| AWS::ApiGatewayV2::Stage | ✅ | ✅ | - | -| AWS::ApiGatewayV2::VpcLink | ✅ | ✅ | - | -| AWS::AppConfig::Application | ✅ | ✅ | - | -| AWS::AppConfig::ConfigurationProfile | ✅ | ✅ | - | -| AWS::AppConfig::Deployment | ✅ | ✅ | - | -| AWS::AppConfig::DeploymentStrategy | ✅ | ✅ | - | -| AWS::AppConfig::Environment | ✅ | ✅ | - | -| AWS::AppConfig::HostedConfigurationVersion | ✅ | ✅ | - | -| AWS::AppSync::ApiKey | ✅ | ✅ | - | -| AWS::AppSync::DataSource | ✅ | ✅ | - | -| AWS::AppSync::FunctionConfiguration | ✅ | ✅ | - | -| AWS::AppSync::GraphQLApi | ✅ | ✅ | - | -| AWS::AppSync::GraphQLSchema | ✅ | ✅ | - | -| AWS::AppSync::Resolver | ✅ | ✅ | ✅ | -| AWS::ApplicationAutoScaling::ScalableTarget | ✅ | ✅ | - | -| AWS::ApplicationAutoScaling::ScalingPolicy | ✅ | ✅ | - | -| AWS::Athena::DataCatalog | ✅ | ✅ | - | -| AWS::Athena::NamedQuery | ✅ | ✅ | - | -| AWS::Athena::WorkGroup | ✅ | ✅ | - | -| AWS::Backup::BackupPlan | ✅ | ✅ | - | -| AWS::Batch::ComputeEnvironment | ✅ | ✅ | - | -| AWS::Batch::JobDefinition | ✅ | ✅ | - | -| AWS::Batch::JobQueue | ✅ | ✅ | - | -| AWS::CloudFormation::CustomResource | ✅ | - | - | -| AWS::CloudFront::CachePolicy | ✅ | ✅ | - | -| AWS::CloudFront::CloudFrontOriginAccessIdentity | ✅ | ✅ | - | -| AWS::CloudFront::Distribution | ✅ | ✅ | - | -| AWS::CloudFront::Function | ✅ | ✅ | - | -| AWS::CloudFront::OriginAccessControl | ✅ | ✅ | - | -| AWS::CloudFront::OriginRequestPolicy | ✅ | ✅ | - | -| AWS::Cloudfront::ResponseHeadersPolicy | ✅ | ✅ | - | -| AWS::CloudTrail::Trail | ✅ | ✅ | - | -| AWS::Cognito::IdentityPool | ✅ | ✅ | - | -| AWS::Cognito::IdentityPoolRoleAttachment | ✅ | ✅ | - | -| AWS::Cognito::UserPool | ✅ | ✅ | - | -| AWS::Cognito::UserPoolClient | ✅ | ✅ | - | -| AWS::Cognito::UserPoolDomain | ✅ | ✅ | - | -| AWS::Cognito::UserPoolGroup | ✅ | ✅ | - | -| AWS::Cognito::UserPoolIdentityProvider | ✅ | ✅ | - | -| AWS::Cognito::UserPoolResourceServer | ✅ | ✅ | - | -| AWS::DocDB::DBCluster | ✅ | ✅ | - | -| AWS::DocDB::DBClusterParameterGroup | ✅ | ✅ | - | -| AWS::DocDB::DBInstance | ✅ | ✅ | - | -| AWS::DocDB::DBSubnetGroup | ✅ | ✅ | - | -| AWS::EC2::EIP | ✅ | ✅ | - | -| AWS::EC2::LaunchTemplate | ✅ | ✅ | - | -| AWS::EC2::PrefixList | ✅ | ✅ | - | -| AWS::EC2::SecurityGroupEgress | ✅ | ✅ | - | -| AWS::EC2::SecurityGroupIngress | ✅ | ✅ | - | -| AWS::EC2::SubnetRouteTableAssociation | ✅ | ✅ | - | -| AWS::EC2::VpcEndpoint | ✅ | ✅ | - | -| AWS::EC2::VPCCidrBlock | ✅ | ✅ | - | -| AWS::EC2::VPCEndpoint | ✅ | ✅ | - | -| AWS::EC2::VPCEndpointService | ✅ | ✅ | - | -| AWS::ECS::CapacityProvider | ✅ | ✅ | - | -| AWS::ECS::Cluster | ✅ | ✅ | - | -| AWS::ECS::ClusterCapacityProviderAssociations | ✅ | ✅ | - | -| AWS::ECS::Service | ✅ | ✅ | - | -| AWS::ECS::TaskDefinition | ✅ | ✅ | - | -| AWS::EFS::AccessPoint | ✅ | ✅ | - | -| AWS::EFS::FileSystem | ✅ | ✅ | - | -| AWS::EFS:MountTarget | ✅ | ✅ | - | -| AWS::EKS::Cluster | ✅ | ✅ | - | -| AWS::EKS::FargateProfile | ✅ | ✅ | - | -| AWS::EKS::Nodegroup | ✅ | ✅ | - | -| AWS::ElastiCache::CacheCluster | ✅ | ✅ | - | -| AWS::ElastiCache::ParameterGroup | ✅ | ✅ | - | -| AWS::ElastiCache::ReplicationGroup | ✅ | ✅ | - | -| AWS::ElastiCache::SecurityGroup | ✅ | ✅ | - | -| AWS::ElastiCache::SubnetGroup | ✅ | ✅ | - | -| AWS::ElasticBeanstalk::Application | ✅ | ✅ | - | -| AWS::ElasticBeanstalk::ApplicationVersion | ✅ | ✅ | - | -| AWS::ElasticBeanstalk::ConfigurationTemplate | ✅ | ✅ | - | -| AWS::ElasticBeanstalk::Environment | ✅ | ✅ | - | -| AWS::ElasticLoadBalancingV2::Listener | ✅ | ✅ | - | -| AWS::ElasticLoadBalancingV2::ListenerRule | ✅ | ✅ | - | -| AWS::ElasticLoadBalancingV2::LoadBalancer | ✅ | ✅ | - | -| AWS::ElasticLoadBalancingV2::TargetGroup | ✅ | ✅ | - | -| AWS::Glue::Classifier | ✅ | ✅ | - | -| AWS::Glue::Crawler | ✅ | ✅ | - | -| AWS::Glue::Connection | ✅ | ✅ | - | -| AWS::Glue::Database | ✅ | ✅ | - | -| AWS::Glue::Job | ✅ | ✅ | - | -| AWS::Glue::Registry | ✅ | ✅ | - | -| AWS::Glue::SchemaVersion | ✅ | ✅ | - | -| AWS::Glue::SchemaVersionMetadata | ✅ | ✅ | - | -| AWS::Glue::Table | ✅ | ✅ | - | -| AWS::Glue::Trigger | ✅ | ✅ | - | -| AWS::Glue::Workflow | ✅ | ✅ | - | -| AWS::IoT::Certificate | ✅ | ✅ | - | -| AWS::IoT::Policy | ✅ | ✅ | - | -| AWS::IoT::RoleAlias | ✅ | ✅ | - | -| AWS::IoT::Thing | ✅ | ✅ | - | -| AWS::IoT::TopicRule | ✅ | ✅ | - | -| AWS::IoTAnalytics::Channel | ✅ | ✅ | - | -| AWS::IoTAnalytics::Dataset | ✅ | ✅ | - | -| AWS::IoTAnalytics::Datastore | ✅ | ✅ | - | -| AWS::IoTAnalytics::Pipeline | ✅ | ✅ | - | -| AWS::MSK::Cluster | ✅ | ✅ | - | -| AWS::Neptune::DBCluster | ✅ | ✅ | - | -| AWS::Neptune::DBClusterParameterGroup | ✅ | ✅ | - | -| AWS::Neptune::DBInstance | ✅ | ✅ | - | -| AWS::Neptune::DBParameterGroup | ✅ | ✅ | - | -| AWS::Neptune::DBSubnetGroup | ✅ | ✅ | - | -| AWS::Pipes::Pipe | ✅ | ✅ | - | -| AWS::RDS::DBCluster | ✅ | ✅ | - | -| AWS::RDS::DBClusterParameterGroup | ✅ | ✅ | - | -| AWS::RDS::DBInstance | ✅ | ✅ | - | -| AWS::RDS::DBParameterGroup | ✅ | ✅ | - | -| AWS::RDS::DBProxy | ✅ | ✅ | - | -| AWS::RDS::DBProxyTargetGroup | ✅ | ✅ | - | -| AWS::RDS::DBSubnetGroup | ✅ | ✅ | - | -| AWS::RDS::GlobalCluster | ✅ | ✅ | - | -| AWS::Redshift::ClusterParameterGroup | ✅ | ✅ | - | -| AWS::Redshift::ClusterSecurityGroup | ✅ | ✅ | - | -| AWS::Redshift::ClusterSubnetGroup | ✅ | ✅ | - | -| AWS::Route53::HostedZone | ✅ | ✅ | - | -| AWS::SageMaker::Endpoint | ✅ | ✅ | - | -| AWS::SageMaker::EndpointConfig | ✅ | ✅ | - | -| AWS::SageMaker::Model | ✅ | ✅ | - | -| AWS::SES::ReceiptRule | ✅ | ✅ | - | -| AWS::SES::ReceiptRuleSet | ✅ | ✅ | - | -| AWS::SES::Template | ✅ | ✅ | ✅ | -| AWS::SecretsManager::SecretTargetAttachment | ✅ | ✅ | - | -| AWS::VerifiedPermissions::IdentitySource | ✅ | ✅ | - | -| AWS::VerifiedPermissions::Policy | ✅ | ✅ | - | -| AWS::VerifiedPermissions::PolicyStore | ✅ | ✅ | - | -| AWS::VerifiedPermissions::PolicyTemplate | ✅ | ✅ | - | -| AWS::WAFv2::IPSet | ✅ | ✅ | - | -| AWS::WAFv2::LoggingConfiguration | ✅ | ✅ | - | -| AWS::WAFv2::WebACL | ✅ | ✅ | - | -| AWS::WAFv2::WebACLAssociation | ✅ | ✅ | - | + ## API Coverage diff --git a/src/data/cloudformation/coverage.json b/src/data/cloudformation/coverage.json new file mode 100644 index 00000000..14cfcc76 --- /dev/null +++ b/src/data/cloudformation/coverage.json @@ -0,0 +1,2464 @@ +{ + "generated_at": "2026-02-25T07:56:02.886893+00:00", + "database_id": "9b3ebbcc1f6749fb908eb2e3582386b0", + "total_resources": 273, + "resources": [ + { + "resource_type": "AWS::Amplify::Branch", + "primary_identifier_paths": "/properties/Arn", + "service": "Amplify", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::Account", + "primary_identifier_paths": "/properties/Id", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::ApiKey", + "primary_identifier_paths": "/properties/APIKeyId", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::BasePathMapping", + "primary_identifier_paths": "/properties/BasePath\n/properties/DomainName", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::Deployment", + "primary_identifier_paths": "/properties/DeploymentId\n/properties/RestApiId", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::DomainName", + "primary_identifier_paths": "/properties/DomainName", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::GatewayResponse", + "primary_identifier_paths": "/properties/Id", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::Method", + "primary_identifier_paths": "/properties/HttpMethod\n/properties/ResourceId\n/properties/RestApiId", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::Model", + "primary_identifier_paths": "/properties/Name\n/properties/RestApiId", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::RequestValidator", + "primary_identifier_paths": "/properties/RequestValidatorId\n/properties/RestApiId", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::Resource", + "primary_identifier_paths": "/properties/ResourceId\n/properties/RestApiId", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::RestApi", + "primary_identifier_paths": "/properties/RestApiId", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::Stage", + "primary_identifier_paths": "/properties/RestApiId\n/properties/StageName", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::UsagePlan", + "primary_identifier_paths": "/properties/Id", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ApiGateway::UsagePlanKey", + "primary_identifier_paths": "/properties/Id", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::AutoScaling::AutoScalingGroup", + "primary_identifier_paths": "/properties/Id", + "service": "AutoScaling", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::AutoScaling::LaunchConfiguration", + "primary_identifier_paths": "/properties/LaunchConfigurationName", + "service": "AutoScaling", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::CDK::Metadata", + "primary_identifier_paths": "", + "service": "CDK", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::CertificateManager::Certificate", + "primary_identifier_paths": "/properties/Id", + "service": "CertificateManager", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::CloudFormation::Macro", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFormation", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::CloudFormation::Stack", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFormation", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::CloudFormation::WaitCondition", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFormation", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::CloudFormation::WaitConditionHandle", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFormation", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::CloudWatch::Alarm", + "primary_identifier_paths": "/properties/Id", + "service": "CloudWatch", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::CloudWatch::CompositeAlarm", + "primary_identifier_paths": "/properties/AlarmName", + "service": "CloudWatch", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::DynamoDB::GlobalTable", + "primary_identifier_paths": "/properties/TableName", + "service": "DynamoDB", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::DynamoDB::Table", + "primary_identifier_paths": "/properties/TableName", + "service": "DynamoDB", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::DHCPOptions", + "primary_identifier_paths": "/properties/DhcpOptionsId", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::Instance", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::InternetGateway", + "primary_identifier_paths": "/properties/InternetGatewayId", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::KeyPair", + "primary_identifier_paths": "/properties/KeyName", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::NatGateway", + "primary_identifier_paths": "/properties/NatGatewayId", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::NetworkAcl", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::PrefixList", + "primary_identifier_paths": "/properties/PrefixListId", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::Route", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::RouteTable", + "primary_identifier_paths": "/properties/RouteTableId", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::SecurityGroup", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::Subnet", + "primary_identifier_paths": "/properties/SubnetId", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::SubnetRouteTableAssociation", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::TransitGateway", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::TransitGatewayAttachment", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::VPC", + "primary_identifier_paths": "/properties/VpcId", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::VPCEndpoint", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::EC2::VPCGatewayAttachment", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ECR::Repository", + "primary_identifier_paths": "/properties/RepositoryName", + "service": "ECR", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Elasticsearch::Domain", + "primary_identifier_paths": "/properties/Id", + "service": "Elasticsearch", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::Events::ApiDestination", + "primary_identifier_paths": "/properties/Name", + "service": "Events", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Events::Connection", + "primary_identifier_paths": "/properties/Name", + "service": "Events", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Events::EventBus", + "primary_identifier_paths": "/properties/Id", + "service": "Events", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Events::EventBusPolicy", + "primary_identifier_paths": "/properties/Id", + "service": "Events", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Events::Rule", + "primary_identifier_paths": "/properties/Id", + "service": "Events", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::IAM::AccessKey", + "primary_identifier_paths": "/properties/Id", + "service": "IAM", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::IAM::Group", + "primary_identifier_paths": "/properties/Id", + "service": "IAM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::IAM::InstanceProfile", + "primary_identifier_paths": "/properties/InstanceProfileName", + "service": "IAM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::IAM::ManagedPolicy", + "primary_identifier_paths": "/properties/Id", + "service": "IAM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::IAM::Policy", + "primary_identifier_paths": "/properties/Id", + "service": "IAM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::IAM::Role", + "primary_identifier_paths": "/properties/RoleName", + "service": "IAM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::IAM::ServerCertificate", + "primary_identifier_paths": "/properties/ServerCertificateName", + "service": "IAM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::IAM::ServiceLinkedRole", + "primary_identifier_paths": "/properties/Id", + "service": "IAM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::IAM::User", + "primary_identifier_paths": "/properties/Id", + "service": "IAM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::KMS::Alias", + "primary_identifier_paths": "/properties/AliasName", + "service": "KMS", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::KMS::Key", + "primary_identifier_paths": "/properties/KeyId", + "service": "KMS", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Kinesis::Stream", + "primary_identifier_paths": "/properties/Name", + "service": "Kinesis", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Kinesis::StreamConsumer", + "primary_identifier_paths": "/properties/Id", + "service": "Kinesis", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::KinesisFirehose::DeliveryStream", + "primary_identifier_paths": "/properties/DeliveryStreamName", + "service": "KinesisFirehose", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::Alias", + "primary_identifier_paths": "/properties/Id", + "service": "Lambda", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::CodeSigningConfig", + "primary_identifier_paths": "/properties/CodeSigningConfigArn", + "service": "Lambda", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::EventInvokeConfig", + "primary_identifier_paths": "/properties/Id", + "service": "Lambda", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::EventSourceMapping", + "primary_identifier_paths": "/properties/Id", + "service": "Lambda", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::Function", + "primary_identifier_paths": "/properties/FunctionName", + "service": "Lambda", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::LayerVersion", + "primary_identifier_paths": "/properties/Id", + "service": "Lambda", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::LayerVersionPermission", + "primary_identifier_paths": "/properties/Id", + "service": "Lambda", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::Permission", + "primary_identifier_paths": "/properties/Id", + "service": "Lambda", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::Url", + "primary_identifier_paths": "/properties/FunctionArn", + "service": "Lambda", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::Lambda::Version", + "primary_identifier_paths": "/properties/Id", + "service": "Lambda", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::Logs::LogGroup", + "primary_identifier_paths": "/properties/LogGroupName", + "service": "Logs", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Logs::LogStream", + "primary_identifier_paths": "/properties/Id", + "service": "Logs", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Logs::SubscriptionFilter", + "primary_identifier_paths": "/properties/FilterName\n/properties/LogGroupName", + "service": "Logs", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::OpenSearchService::Domain", + "primary_identifier_paths": "/properties/DomainName", + "service": "OpenSearchService", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::Redshift::Cluster", + "primary_identifier_paths": "/properties/ClusterIdentifier", + "service": "Redshift", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::ResourceGroups::Group", + "primary_identifier_paths": "/properties/Name", + "service": "ResourceGroups", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Route53::HealthCheck", + "primary_identifier_paths": "/properties/HealthCheckId", + "service": "Route53", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Route53::RecordSet", + "primary_identifier_paths": "/properties/Id", + "service": "Route53", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::S3::Bucket", + "primary_identifier_paths": "/properties/BucketName", + "service": "S3", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::S3::BucketPolicy", + "primary_identifier_paths": "/properties/Id", + "service": "S3", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SES::EmailIdentity", + "primary_identifier_paths": "/properties/EmailIdentity", + "service": "SES", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SNS::Subscription", + "primary_identifier_paths": "/properties/Id", + "service": "SNS", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SNS::Topic", + "primary_identifier_paths": "/properties/TopicArn", + "service": "SNS", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SNS::TopicPolicy", + "primary_identifier_paths": "/properties/Id", + "service": "SNS", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SQS::Queue", + "primary_identifier_paths": "/properties/QueueUrl", + "service": "SQS", + "create": true, + "delete": true, + "update": true, + "tier": "Community" + }, + { + "resource_type": "AWS::SQS::QueueInlinePolicy", + "primary_identifier_paths": "", + "service": "SQS", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SQS::QueuePolicy", + "primary_identifier_paths": "/properties/Id", + "service": "SQS", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SSM::MaintenanceWindow", + "primary_identifier_paths": "/properties/Id", + "service": "SSM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SSM::MaintenanceWindowTarget", + "primary_identifier_paths": "/properties/Id", + "service": "SSM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SSM::MaintenanceWindowTask", + "primary_identifier_paths": "/properties/Id", + "service": "SSM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SSM::Parameter", + "primary_identifier_paths": "/properties/Id", + "service": "SSM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SSM::PatchBaseline", + "primary_identifier_paths": "/properties/Id", + "service": "SSM", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Scheduler::Schedule", + "primary_identifier_paths": "/properties/Name", + "service": "Scheduler", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Scheduler::ScheduleGroup", + "primary_identifier_paths": "/properties/Name", + "service": "Scheduler", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SecretsManager::ResourcePolicy", + "primary_identifier_paths": "/properties/Id", + "service": "SecretsManager", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SecretsManager::RotationSchedule", + "primary_identifier_paths": "/properties/Id", + "service": "SecretsManager", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SecretsManager::Secret", + "primary_identifier_paths": "/properties/Id", + "service": "SecretsManager", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::SecretsManager::SecretTargetAttachment", + "primary_identifier_paths": "/properties/Id", + "service": "SecretsManager", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ServiceDiscovery::HttpNamespace", + "primary_identifier_paths": "/properties/Id", + "service": "ServiceDiscovery", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ServiceDiscovery::PrivateDnsNamespace", + "primary_identifier_paths": "/properties/Id", + "service": "ServiceDiscovery", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ServiceDiscovery::PublicDnsNamespace", + "primary_identifier_paths": "/properties/Id", + "service": "ServiceDiscovery", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ServiceDiscovery::Service", + "primary_identifier_paths": "/properties/Id", + "service": "ServiceDiscovery", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::StepFunctions::Activity", + "primary_identifier_paths": "/properties/Arn", + "service": "StepFunctions", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::StepFunctions::StateMachine", + "primary_identifier_paths": "/properties/Arn", + "service": "StepFunctions", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Timestream::Database", + "primary_identifier_paths": "/properties/DatabaseName", + "service": "Timestream", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::Timestream::Table", + "primary_identifier_paths": "/properties/DatabaseName\n/properties/TableName", + "service": "Timestream", + "create": true, + "delete": true, + "update": false, + "tier": "Community" + }, + { + "resource_type": "AWS::ACMPCA::Certificate", + "primary_identifier_paths": "/properties/Arn\n/properties/CertificateAuthorityArn", + "service": "ACMPCA", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ACMPCA::CertificateAuthority", + "primary_identifier_paths": "/properties/Arn", + "service": "ACMPCA", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ACMPCA::CertificateAuthorityActivation", + "primary_identifier_paths": "/properties/CertificateAuthorityArn", + "service": "ACMPCA", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ACMPCA::Permission", + "primary_identifier_paths": "/properties/CertificateAuthorityArn\n/properties/Principal", + "service": "ACMPCA", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Amplify::App", + "primary_identifier_paths": "/properties/Arn", + "service": "Amplify", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGateway::Authorizer", + "primary_identifier_paths": "/properties/AuthorizerId\n/properties/RestApiId", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGateway::VpcLink", + "primary_identifier_paths": "/properties/VpcLinkId", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::Api", + "primary_identifier_paths": "/properties/ApiId", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::ApiMapping", + "primary_identifier_paths": "/properties/Id", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::Authorizer", + "primary_identifier_paths": "/properties/ApiId\n/properties/AuthorizerId", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::Deployment", + "primary_identifier_paths": "/properties/ApiId\n/properties/DeploymentId", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::DomainName", + "primary_identifier_paths": "/properties/Id", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::Integration", + "primary_identifier_paths": "/properties/Id", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::IntegrationResponse", + "primary_identifier_paths": "/properties/ApiId\n/properties/IntegrationId\n/properties/IntegrationResponseId", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::Route", + "primary_identifier_paths": "/properties/ApiId\n/properties/RouteId", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::RouteResponse", + "primary_identifier_paths": "/properties/Id", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::Stage", + "primary_identifier_paths": "/properties/Id", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApiGatewayV2::VpcLink", + "primary_identifier_paths": "/properties/VpcLinkId", + "service": "ApiGatewayV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppConfig::Application", + "primary_identifier_paths": "/properties/Id", + "service": "AppConfig", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppConfig::ConfigurationProfile", + "primary_identifier_paths": "/properties/Id", + "service": "AppConfig", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppConfig::Deployment", + "primary_identifier_paths": "/properties/Id", + "service": "AppConfig", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppConfig::DeploymentStrategy", + "primary_identifier_paths": "/properties/Id", + "service": "AppConfig", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppConfig::Environment", + "primary_identifier_paths": "/properties/Id", + "service": "AppConfig", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppConfig::HostedConfigurationVersion", + "primary_identifier_paths": "/properties/Id", + "service": "AppConfig", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppSync::ApiKey", + "primary_identifier_paths": "/properties/ApiKeyId", + "service": "AppSync", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppSync::DataSource", + "primary_identifier_paths": "/properties/Id", + "service": "AppSync", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppSync::FunctionConfiguration", + "primary_identifier_paths": "/properties/Id", + "service": "AppSync", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppSync::GraphQLApi", + "primary_identifier_paths": "/properties/Id", + "service": "AppSync", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppSync::GraphQLSchema", + "primary_identifier_paths": "/properties/Id", + "service": "AppSync", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::AppSync::Resolver", + "primary_identifier_paths": "/properties/Id", + "service": "AppSync", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApplicationAutoScaling::ScalableTarget", + "primary_identifier_paths": "/properties/Id", + "service": "ApplicationAutoScaling", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ApplicationAutoScaling::ScalingPolicy", + "primary_identifier_paths": "/properties/Id", + "service": "ApplicationAutoScaling", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Athena::DataCatalog", + "primary_identifier_paths": "/properties/Name", + "service": "Athena", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Athena::NamedQuery", + "primary_identifier_paths": "/properties/NamedQueryId", + "service": "Athena", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Athena::WorkGroup", + "primary_identifier_paths": "/properties/Name", + "service": "Athena", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Backup::BackupPlan", + "primary_identifier_paths": "/properties/BackupPlanId", + "service": "Backup", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Batch::ComputeEnvironment", + "primary_identifier_paths": "/properties/ComputeEnvironmentArn", + "service": "Batch", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Batch::JobDefinition", + "primary_identifier_paths": "/properties/Id", + "service": "Batch", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Batch::JobQueue", + "primary_identifier_paths": "/properties/JobQueueArn", + "service": "Batch", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CloudFormation::CustomResource", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFormation", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CloudFront::CachePolicy", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFront", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFront", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CloudFront::Distribution", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFront", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CloudFront::Function", + "primary_identifier_paths": "/properties/FunctionARN", + "service": "CloudFront", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CloudFront::OriginAccessControl", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFront", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CloudFront::OriginRequestPolicy", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFront", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CloudFront::ResponseHeadersPolicy", + "primary_identifier_paths": "/properties/Id", + "service": "CloudFront", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CloudTrail::Trail", + "primary_identifier_paths": "/properties/TrailName", + "service": "CloudTrail", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CodeBuild::Project", + "primary_identifier_paths": "/properties/Id", + "service": "CodeBuild", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CodeDeploy::Application", + "primary_identifier_paths": "/properties/ApplicationName", + "service": "CodeDeploy", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CodeDeploy::DeploymentConfig", + "primary_identifier_paths": "/properties/DeploymentConfigName", + "service": "CodeDeploy", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CodeDeploy::DeploymentGroup", + "primary_identifier_paths": "/properties/Id", + "service": "CodeDeploy", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::CodePipeline::Pipeline", + "primary_identifier_paths": "/properties/Id", + "service": "CodePipeline", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Cognito::IdentityPool", + "primary_identifier_paths": "/properties/Id", + "service": "Cognito", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Cognito::IdentityPoolRoleAttachment", + "primary_identifier_paths": "/properties/Id", + "service": "Cognito", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Cognito::UserPool", + "primary_identifier_paths": "/properties/Id", + "service": "Cognito", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Cognito::UserPoolClient", + "primary_identifier_paths": "/properties/Id", + "service": "Cognito", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Cognito::UserPoolDomain", + "primary_identifier_paths": "/properties/Id", + "service": "Cognito", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Cognito::UserPoolGroup", + "primary_identifier_paths": "/properties/Id", + "service": "Cognito", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Cognito::UserPoolIdentityProvider", + "primary_identifier_paths": "/properties/Id", + "service": "Cognito", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Cognito::UserPoolResourceServer", + "primary_identifier_paths": "/properties/Id", + "service": "Cognito", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::DMS::Endpoint", + "primary_identifier_paths": "/properties/Id", + "service": "DMS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::DMS::ReplicationConfig", + "primary_identifier_paths": "", + "service": "DMS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::DMS::ReplicationInstance", + "primary_identifier_paths": "/properties/Id", + "service": "DMS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::DMS::ReplicationSubnetGroup", + "primary_identifier_paths": "/properties/Id", + "service": "DMS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::DMS::ReplicationTask", + "primary_identifier_paths": "/properties/Id", + "service": "DMS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::DocDB::DBCluster", + "primary_identifier_paths": "/properties/Id", + "service": "DocDB", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::DocDB::DBClusterParameterGroup", + "primary_identifier_paths": "/properties/Id", + "service": "DocDB", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::DocDB::DBInstance", + "primary_identifier_paths": "/properties/Id", + "service": "DocDB", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::DocDB::DBSubnetGroup", + "primary_identifier_paths": "/properties/Id", + "service": "DocDB", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EC2::EIP", + "primary_identifier_paths": "/properties/AllocationId\n/properties/PublicIp", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EC2::LaunchTemplate", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EC2::SecurityGroupEgress", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EC2::SecurityGroupIngress", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EC2::VPCCidrBlock", + "primary_identifier_paths": "/properties/Id", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EC2::VPCEndpointService", + "primary_identifier_paths": "/properties/ServiceId", + "service": "EC2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ECS::CapacityProvider", + "primary_identifier_paths": "/properties/Name", + "service": "ECS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ECS::Cluster", + "primary_identifier_paths": "/properties/ClusterName", + "service": "ECS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ECS::ClusterCapacityProviderAssociations", + "primary_identifier_paths": "/properties/Cluster", + "service": "ECS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ECS::Service", + "primary_identifier_paths": "/properties/Cluster\n/properties/ServiceArn", + "service": "ECS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ECS::TaskDefinition", + "primary_identifier_paths": "/properties/TaskDefinitionArn", + "service": "ECS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EFS::AccessPoint", + "primary_identifier_paths": "/properties/AccessPointId", + "service": "EFS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EFS::FileSystem", + "primary_identifier_paths": "/properties/FileSystemId", + "service": "EFS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EFS::MountTarget", + "primary_identifier_paths": "/properties/Id", + "service": "EFS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EKS::Cluster", + "primary_identifier_paths": "/properties/Name", + "service": "EKS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EKS::FargateProfile", + "primary_identifier_paths": "/properties/ClusterName\n/properties/FargateProfileName", + "service": "EKS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::EKS::Nodegroup", + "primary_identifier_paths": "/properties/Id", + "service": "EKS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElastiCache::CacheCluster", + "primary_identifier_paths": "/properties/Id", + "service": "ElastiCache", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElastiCache::ParameterGroup", + "primary_identifier_paths": "/properties/Id", + "service": "ElastiCache", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElastiCache::ReplicationGroup", + "primary_identifier_paths": "/properties/ReplicationGroupId", + "service": "ElastiCache", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElastiCache::SecurityGroup", + "primary_identifier_paths": "/properties/Id", + "service": "ElastiCache", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElastiCache::SubnetGroup", + "primary_identifier_paths": "/properties/CacheSubnetGroupName", + "service": "ElastiCache", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElasticBeanstalk::Application", + "primary_identifier_paths": "/properties/ApplicationName", + "service": "ElasticBeanstalk", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElasticBeanstalk::ApplicationVersion", + "primary_identifier_paths": "/properties/ApplicationName\n/properties/Id", + "service": "ElasticBeanstalk", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElasticBeanstalk::ConfigurationTemplate", + "primary_identifier_paths": "/properties/ApplicationName\n/properties/TemplateName", + "service": "ElasticBeanstalk", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElasticBeanstalk::Environment", + "primary_identifier_paths": "/properties/EnvironmentName", + "service": "ElasticBeanstalk", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElasticLoadBalancingV2::Listener", + "primary_identifier_paths": "/properties/ListenerArn", + "service": "ElasticLoadBalancingV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElasticLoadBalancingV2::ListenerRule", + "primary_identifier_paths": "/properties/RuleArn", + "service": "ElasticLoadBalancingV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "primary_identifier_paths": "/properties/Id", + "service": "ElasticLoadBalancingV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "primary_identifier_paths": "/properties/TargetGroupArn", + "service": "ElasticLoadBalancingV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Classifier", + "primary_identifier_paths": "/properties/Id", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Connection", + "primary_identifier_paths": "/properties/Id", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Crawler", + "primary_identifier_paths": "/properties/Id", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Database", + "primary_identifier_paths": "/properties/Id", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Job", + "primary_identifier_paths": "/properties/Id", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Registry", + "primary_identifier_paths": "/properties/Arn", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Schema", + "primary_identifier_paths": "/properties/Arn", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::SchemaVersion", + "primary_identifier_paths": "/properties/VersionId", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::SchemaVersionMetadata", + "primary_identifier_paths": "/properties/Key\n/properties/SchemaVersionId\n/properties/Value", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Table", + "primary_identifier_paths": "/properties/Id", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Trigger", + "primary_identifier_paths": "/properties/Id", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Glue::Workflow", + "primary_identifier_paths": "/properties/Id", + "service": "Glue", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::IoT::Certificate", + "primary_identifier_paths": "/properties/Id", + "service": "IoT", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::IoT::Policy", + "primary_identifier_paths": "/properties/Id", + "service": "IoT", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::IoT::RoleAlias", + "primary_identifier_paths": "/properties/RoleAlias", + "service": "IoT", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::IoT::Thing", + "primary_identifier_paths": "/properties/ThingName", + "service": "IoT", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::IoT::TopicRule", + "primary_identifier_paths": "/properties/RuleName", + "service": "IoT", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::IoTAnalytics::Channel", + "primary_identifier_paths": "/properties/ChannelName", + "service": "IoTAnalytics", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::IoTAnalytics::Dataset", + "primary_identifier_paths": "/properties/DatasetName", + "service": "IoTAnalytics", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::IoTAnalytics::Datastore", + "primary_identifier_paths": "/properties/DatastoreName", + "service": "IoTAnalytics", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::IoTAnalytics::Pipeline", + "primary_identifier_paths": "/properties/PipelineName", + "service": "IoTAnalytics", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::KinesisAnalytics::Application", + "primary_identifier_paths": "/properties/Id", + "service": "KinesisAnalytics", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::KinesisAnalytics::ApplicationOutput", + "primary_identifier_paths": "/properties/Id", + "service": "KinesisAnalytics", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::KinesisAnalyticsV2::Application", + "primary_identifier_paths": "/properties/ApplicationName", + "service": "KinesisAnalyticsV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::KinesisAnalyticsV2::ApplicationCloudWatchLoggingOption", + "primary_identifier_paths": "/properties/Id", + "service": "KinesisAnalyticsV2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Lambda::CapacityProvider", + "primary_identifier_paths": "", + "service": "Lambda", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::MSK::Cluster", + "primary_identifier_paths": "/properties/Arn", + "service": "MSK", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::MWAA::Environment", + "primary_identifier_paths": "/properties/Name", + "service": "MWAA", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Neptune::DBCluster", + "primary_identifier_paths": "/properties/DBClusterIdentifier", + "service": "Neptune", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Neptune::DBClusterParameterGroup", + "primary_identifier_paths": "/properties/Id", + "service": "Neptune", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Neptune::DBInstance", + "primary_identifier_paths": "/properties/Id", + "service": "Neptune", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Neptune::DBParameterGroup", + "primary_identifier_paths": "/properties/Id", + "service": "Neptune", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Neptune::DBSubnetGroup", + "primary_identifier_paths": "/properties/Id", + "service": "Neptune", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Pipes::Pipe", + "primary_identifier_paths": "/properties/Name", + "service": "Pipes", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::QLDB::Ledger", + "primary_identifier_paths": "/properties/Id", + "service": "QLDB", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::RDS::DBCluster", + "primary_identifier_paths": "/properties/DBClusterIdentifier", + "service": "RDS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::RDS::DBClusterParameterGroup", + "primary_identifier_paths": "/properties/DBClusterParameterGroupName", + "service": "RDS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::RDS::DBInstance", + "primary_identifier_paths": "/properties/DBInstanceIdentifier", + "service": "RDS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::RDS::DBParameterGroup", + "primary_identifier_paths": "/properties/DBParameterGroupName", + "service": "RDS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::RDS::DBProxy", + "primary_identifier_paths": "/properties/DBProxyName", + "service": "RDS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::RDS::DBProxyEndpoint", + "primary_identifier_paths": "/properties/DBProxyEndpointName", + "service": "RDS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::RDS::DBProxyTargetGroup", + "primary_identifier_paths": "/properties/TargetGroupArn", + "service": "RDS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::RDS::DBSubnetGroup", + "primary_identifier_paths": "/properties/DBSubnetGroupName", + "service": "RDS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::RDS::GlobalCluster", + "primary_identifier_paths": "/properties/GlobalClusterIdentifier", + "service": "RDS", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Redshift::ClusterParameterGroup", + "primary_identifier_paths": "/properties/ParameterGroupName", + "service": "Redshift", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Redshift::ClusterSecurityGroup", + "primary_identifier_paths": "/properties/Id", + "service": "Redshift", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Redshift::ClusterSubnetGroup", + "primary_identifier_paths": "/properties/ClusterSubnetGroupName", + "service": "Redshift", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::Route53::HostedZone", + "primary_identifier_paths": "/properties/Id", + "service": "Route53", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::SES::ReceiptRule", + "primary_identifier_paths": "/properties/Id", + "service": "SES", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::SES::ReceiptRuleSet", + "primary_identifier_paths": "/properties/Id", + "service": "SES", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::SES::Template", + "primary_identifier_paths": "/properties/Id", + "service": "SES", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::SageMaker::Endpoint", + "primary_identifier_paths": "/properties/Id", + "service": "SageMaker", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::SageMaker::EndpointConfig", + "primary_identifier_paths": "/properties/Id", + "service": "SageMaker", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::SageMaker::Model", + "primary_identifier_paths": "/properties/Id", + "service": "SageMaker", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::VerifiedPermissions::IdentitySource", + "primary_identifier_paths": "", + "service": "VerifiedPermissions", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::VerifiedPermissions::Policy", + "primary_identifier_paths": "", + "service": "VerifiedPermissions", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::VerifiedPermissions::PolicyStore", + "primary_identifier_paths": "", + "service": "VerifiedPermissions", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::VerifiedPermissions::PolicyTemplate", + "primary_identifier_paths": "", + "service": "VerifiedPermissions", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::WAFv2::IPSet", + "primary_identifier_paths": "/properties/Id\n/properties/Name\n/properties/Scope", + "service": "WAFv2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::WAFv2::LoggingConfiguration", + "primary_identifier_paths": "/properties/ResourceArn", + "service": "WAFv2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::WAFv2::WebACL", + "primary_identifier_paths": "/properties/Id\n/properties/Name\n/properties/Scope", + "service": "WAFv2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + }, + { + "resource_type": "AWS::WAFv2::WebACLAssociation", + "primary_identifier_paths": "/properties/ResourceArn\n/properties/WebACLArn", + "service": "WAFv2", + "create": true, + "delete": true, + "update": false, + "tier": "Pro" + } + ] +} From d26dfd975ac7fba5a19a29af3d9752f2953d2440 Mon Sep 17 00:00:00 2001 From: HarshCasper Date: Thu, 26 Feb 2026 23:25:42 +0530 Subject: [PATCH 2/3] update comments --- .../update-cloudformation-coverage.yml | 73 + scripts/create_cloudformation_coverage.py | 94 +- .../CloudFormationCoverage.tsx | 32 +- src/data/cloudformation/coverage.json | 2142 ++++++----------- 4 files changed, 907 insertions(+), 1434 deletions(-) create mode 100644 .github/workflows/update-cloudformation-coverage.yml diff --git a/.github/workflows/update-cloudformation-coverage.yml b/.github/workflows/update-cloudformation-coverage.yml new file mode 100644 index 00000000..bacccfd6 --- /dev/null +++ b/.github/workflows/update-cloudformation-coverage.yml @@ -0,0 +1,73 @@ +name: Update CloudFormation Coverage + +on: + schedule: + - cron: 0 5 * * MON + workflow_dispatch: + inputs: + targetBranch: + required: false + type: string + default: 'main' + +jobs: + update-cloudformation-coverage: + name: Update CloudFormation coverage data + runs-on: ubuntu-latest + steps: + - name: Checkout docs + uses: actions/checkout@v4 + with: + fetch-depth: 0 + path: docs + ref: ${{ github.event.inputs.targetBranch || 'main' }} + + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Skip odd weeks on schedule + id: biweekly-gate + env: + EVENT_NAME: ${{ github.event_name }} + run: | + if [ "$EVENT_NAME" = "schedule" ] && [ $((10#$(date +%V) % 2)) -ne 0 ]; then + echo "skip=true" >> "$GITHUB_OUTPUT" + echo "Skipping this scheduled run to maintain biweekly cadence." + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: Update CloudFormation coverage data + if: steps.biweekly-gate.outputs.skip != 'true' + working-directory: docs + run: | + python3 scripts/create_cloudformation_coverage.py + env: + NOTION_SECRET: ${{ secrets.NOTION_TOKEN }} + + - name: Check for changes + if: steps.biweekly-gate.outputs.skip != 'true' + id: check-for-changes + working-directory: docs + env: + TARGET_BRANCH: ${{ github.event.inputs.targetBranch || 'main' }} + run: | + mkdir -p resources + (git diff --name-only origin/automated-cloudformation-coverage-updates src/data/cloudformation/ 2>/dev/null || git diff --name-only "origin/$TARGET_BRANCH" src/data/cloudformation/ 2>/dev/null) | tee -a resources/diff-check.log + echo "diff-count=$(cat resources/diff-check.log | wc -l)" >> "$GITHUB_OUTPUT" + cat resources/diff-check.log + + - name: Create PR + uses: peter-evans/create-pull-request@v7 + if: ${{ success() && steps.biweekly-gate.outputs.skip != 'true' && steps.check-for-changes.outputs.diff-count != '0' && steps.check-for-changes.outputs.diff-count != '' }} + with: + path: docs + title: "Update CloudFormation coverage data" + body: "Updating CloudFormation feature coverage data from the Notion resource database." + branch: "automated-cloudformation-coverage-updates" + author: "LocalStack Bot " + committer: "LocalStack Bot " + commit-message: "update generated cloudformation coverage data" + token: ${{ secrets.PRO_ACCESS_TOKEN }} diff --git a/scripts/create_cloudformation_coverage.py b/scripts/create_cloudformation_coverage.py index d3a50a96..c82f86db 100644 --- a/scripts/create_cloudformation_coverage.py +++ b/scripts/create_cloudformation_coverage.py @@ -5,6 +5,7 @@ import os import re import sys +import time from datetime import datetime, timezone from pathlib import Path from typing import Any @@ -111,20 +112,6 @@ def to_bool(value: Any) -> bool: return normalized in {"true", "1", "yes", "y", "supported", "enabled"} -def normalize_tier(value: Any, is_open_source: Any) -> str: - if isinstance(value, str) and value.strip(): - normalized = value.strip().lower() - if normalized in {"community", "oss", "open source", "opensource"}: - return "Community" - if normalized in {"pro", "enterprise"}: - return "Pro" - return value.strip() - - if to_bool(is_open_source): - return "Community" - return "Pro" - - def derive_service(service_value: Any, resource_type: str) -> str: if isinstance(service_value, str) and service_value.strip(): return service_value.strip() @@ -136,24 +123,35 @@ def derive_service(service_value: Any, resource_type: str) -> str: def notion_post(path: str, secret: str, payload: dict[str, Any]) -> dict[str, Any]: - request = Request( - url=f"{NOTION_API_BASE}{path}", - data=json.dumps(payload).encode("utf-8"), - headers={ - "Authorization": f"Bearer {secret}", - "Notion-Version": NOTION_VERSION, - "Content-Type": "application/json", - }, - method="POST", - ) - try: - with urlopen(request) as response: - return json.loads(response.read().decode("utf-8")) - except HTTPError as err: - body = err.read().decode("utf-8", errors="ignore") - raise RuntimeError(f"Notion API error ({err.code}): {body}") from err - except URLError as err: - raise RuntimeError(f"Notion request failed: {err.reason}") from err + last_error: Exception | None = None + for attempt in range(4): + request = Request( + url=f"{NOTION_API_BASE}{path}", + data=json.dumps(payload).encode("utf-8"), + headers={ + "Authorization": f"Bearer {secret}", + "Notion-Version": NOTION_VERSION, + "Content-Type": "application/json", + }, + method="POST", + ) + try: + with urlopen(request) as response: + return json.loads(response.read().decode("utf-8")) + except HTTPError as err: + body = err.read().decode("utf-8", errors="ignore") + if err.code in {429, 500, 502, 503, 504} and attempt < 3: + time.sleep(2**attempt) + continue + raise RuntimeError(f"Notion API error ({err.code}): {body}") from err + except URLError as err: + last_error = err + if attempt < 3: + time.sleep(2**attempt) + continue + raise RuntimeError(f"Notion request failed: {err.reason}") from err + + raise RuntimeError(f"Notion request failed after retries: {last_error}") def collect_pages(database_id: str, notion_secret: str) -> list[dict[str, Any]]: @@ -186,14 +184,6 @@ def transform_pages(pages: list[dict[str, Any]]) -> list[dict[str, Any]]: resource_type_key = resolve_property_name( properties, ["Resource Type", "Resource", "Type"] ) - identifier_path_key = resolve_property_name( - properties, - [ - "Primary Identifier Path(s)", - "Primary Identifier Paths", - "Primary Identifier Path", - ], - ) service_key = resolve_property_name(properties, ["Service"]) supports_update_key = resolve_property_name( properties, @@ -204,25 +194,12 @@ def transform_pages(pages: list[dict[str, Any]]) -> list[dict[str, Any]]: "Update", ], ) - tier_key = resolve_property_name( - properties, - ["Community or Pro", "Tier", "Edition", "Image", "Provider version"], - ) - is_open_source_key = resolve_property_name( - properties, ["Is open source", "Open Source", "Is OSS"] - ) - resource_type = str( extract_property_value(properties.get(resource_type_key)) if resource_type_key else "" ).strip() if not resource_type: continue - primary_identifier_paths = str( - extract_property_value(properties.get(identifier_path_key)) - if identifier_path_key - else "" - ).strip() service = derive_service( extract_property_value(properties.get(service_key)) if service_key else "", resource_type, @@ -232,26 +209,17 @@ def transform_pages(pages: list[dict[str, Any]]) -> list[dict[str, Any]]: if supports_update_key else False ) - tier = normalize_tier( - extract_property_value(properties.get(tier_key)) if tier_key else "", - extract_property_value(properties.get(is_open_source_key)) - if is_open_source_key - else False, - ) - rows.append( { "resource_type": resource_type, - "primary_identifier_paths": primary_identifier_paths, "service": service, "create": True, "delete": True, "update": supports_update, - "tier": tier, } ) - rows.sort(key=lambda item: (item["tier"], item["service"], item["resource_type"])) + rows.sort(key=lambda item: (item["service"], item["resource_type"])) return rows diff --git a/src/components/cloudformation-coverage/CloudFormationCoverage.tsx b/src/components/cloudformation-coverage/CloudFormationCoverage.tsx index a28bb62f..e59620c6 100644 --- a/src/components/cloudformation-coverage/CloudFormationCoverage.tsx +++ b/src/components/cloudformation-coverage/CloudFormationCoverage.tsx @@ -16,12 +16,10 @@ import type { type CloudFormationResource = { resource_type: string; - primary_identifier_paths: string; service: string; create: boolean; delete: boolean; update: boolean; - tier: string; }; type CloudFormationCoverageData = { @@ -36,19 +34,15 @@ const coverageData = data as CloudFormationCoverageData; const getColumnWidth = (columnId: string): string => { switch (columnId) { case 'resource_type': - return '21%'; - case 'primary_identifier_paths': - return '29%'; + return '50%'; case 'service': - return '12%'; + return '20%'; case 'create': case 'delete': case 'update': - return '8%'; - case 'tier': - return '14%'; + return '10%'; default: - return '8%'; + return '10%'; } }; @@ -63,11 +57,6 @@ const columns: ColumnDef[] = [ .toLowerCase() .includes((filterValue ?? '').toLowerCase()), }, - { - accessorKey: 'primary_identifier_paths', - header: () => 'Primary Identifier Path(s)', - cell: ({ row }) => row.original.primary_identifier_paths || '-', - }, { accessorKey: 'service', header: () => 'Service', @@ -97,17 +86,10 @@ const columns: ColumnDef[] = [ sortingFn: (rowA, rowB) => Number(rowB.original.update) - Number(rowA.original.update), }, - { - accessorKey: 'tier', - header: () => 'Community / Pro', - cell: ({ row }) => row.original.tier, - enableSorting: true, - }, ]; export default function CloudFormationCoverage() { const [sorting, setSorting] = React.useState([ - { id: 'tier', desc: false }, { id: 'service', desc: false }, { id: 'resource_type', desc: false }, ]); @@ -247,11 +229,7 @@ export default function CloudFormationCoverage() { padding: '12px 8px', overflow: 'hidden', textOverflow: 'ellipsis', - whiteSpace: - cell.column.id === 'resource_type' || - cell.column.id === 'primary_identifier_paths' - ? 'normal' - : 'nowrap', + whiteSpace: cell.column.id === 'resource_type' ? 'normal' : 'nowrap', }} > {flexRender(cell.column.columnDef.cell, cell.getContext())} diff --git a/src/data/cloudformation/coverage.json b/src/data/cloudformation/coverage.json index 14cfcc76..7a737323 100644 --- a/src/data/cloudformation/coverage.json +++ b/src/data/cloudformation/coverage.json @@ -1,2464 +1,1918 @@ { - "generated_at": "2026-02-25T07:56:02.886893+00:00", + "generated_at": "2026-02-26T17:51:52.521494+00:00", "database_id": "9b3ebbcc1f6749fb908eb2e3582386b0", "total_resources": 273, "resources": [ + { + "resource_type": "AWS::ACMPCA::Certificate", + "service": "ACMPCA", + "create": true, + "delete": true, + "update": false + }, + { + "resource_type": "AWS::ACMPCA::CertificateAuthority", + "service": "ACMPCA", + "create": true, + "delete": true, + "update": false + }, + { + "resource_type": "AWS::ACMPCA::CertificateAuthorityActivation", + "service": "ACMPCA", + "create": true, + "delete": true, + "update": false + }, + { + "resource_type": "AWS::ACMPCA::Permission", + "service": "ACMPCA", + "create": true, + "delete": true, + "update": false + }, + { + "resource_type": "AWS::Amplify::App", + "service": "Amplify", + "create": true, + "delete": true, + "update": false + }, { "resource_type": "AWS::Amplify::Branch", - "primary_identifier_paths": "/properties/Arn", "service": "Amplify", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::Account", - "primary_identifier_paths": "/properties/Id", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::ApiKey", - "primary_identifier_paths": "/properties/APIKeyId", "service": "ApiGateway", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": true + }, + { + "resource_type": "AWS::ApiGateway::Authorizer", + "service": "ApiGateway", + "create": true, + "delete": true, + "update": false }, { "resource_type": "AWS::ApiGateway::BasePathMapping", - "primary_identifier_paths": "/properties/BasePath\n/properties/DomainName", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::Deployment", - "primary_identifier_paths": "/properties/DeploymentId\n/properties/RestApiId", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::DomainName", - "primary_identifier_paths": "/properties/DomainName", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::GatewayResponse", - "primary_identifier_paths": "/properties/Id", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::Method", - "primary_identifier_paths": "/properties/HttpMethod\n/properties/ResourceId\n/properties/RestApiId", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::Model", - "primary_identifier_paths": "/properties/Name\n/properties/RestApiId", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::RequestValidator", - "primary_identifier_paths": "/properties/RequestValidatorId\n/properties/RestApiId", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::Resource", - "primary_identifier_paths": "/properties/ResourceId\n/properties/RestApiId", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::RestApi", - "primary_identifier_paths": "/properties/RestApiId", "service": "ApiGateway", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": true }, { "resource_type": "AWS::ApiGateway::Stage", - "primary_identifier_paths": "/properties/RestApiId\n/properties/StageName", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::UsagePlan", - "primary_identifier_paths": "/properties/Id", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { "resource_type": "AWS::ApiGateway::UsagePlanKey", - "primary_identifier_paths": "/properties/Id", "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::AutoScaling::AutoScalingGroup", - "primary_identifier_paths": "/properties/Id", - "service": "AutoScaling", + "resource_type": "AWS::ApiGateway::VpcLink", + "service": "ApiGateway", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::AutoScaling::LaunchConfiguration", - "primary_identifier_paths": "/properties/LaunchConfigurationName", - "service": "AutoScaling", + "resource_type": "AWS::ApiGatewayV2::Api", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::CDK::Metadata", - "primary_identifier_paths": "", - "service": "CDK", + "resource_type": "AWS::ApiGatewayV2::ApiMapping", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::CertificateManager::Certificate", - "primary_identifier_paths": "/properties/Id", - "service": "CertificateManager", + "resource_type": "AWS::ApiGatewayV2::Authorizer", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::CloudFormation::Macro", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFormation", + "resource_type": "AWS::ApiGatewayV2::Deployment", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::CloudFormation::Stack", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFormation", + "resource_type": "AWS::ApiGatewayV2::DomainName", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::CloudFormation::WaitCondition", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFormation", + "resource_type": "AWS::ApiGatewayV2::Integration", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::CloudFormation::WaitConditionHandle", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFormation", + "resource_type": "AWS::ApiGatewayV2::IntegrationResponse", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::CloudWatch::Alarm", - "primary_identifier_paths": "/properties/Id", - "service": "CloudWatch", + "resource_type": "AWS::ApiGatewayV2::Route", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::CloudWatch::CompositeAlarm", - "primary_identifier_paths": "/properties/AlarmName", - "service": "CloudWatch", + "resource_type": "AWS::ApiGatewayV2::RouteResponse", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::DynamoDB::GlobalTable", - "primary_identifier_paths": "/properties/TableName", - "service": "DynamoDB", + "resource_type": "AWS::ApiGatewayV2::Stage", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::DynamoDB::Table", - "primary_identifier_paths": "/properties/TableName", - "service": "DynamoDB", + "resource_type": "AWS::ApiGatewayV2::VpcLink", + "service": "ApiGatewayV2", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::DHCPOptions", - "primary_identifier_paths": "/properties/DhcpOptionsId", - "service": "EC2", + "resource_type": "AWS::AppConfig::Application", + "service": "AppConfig", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::Instance", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::AppConfig::ConfigurationProfile", + "service": "AppConfig", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::InternetGateway", - "primary_identifier_paths": "/properties/InternetGatewayId", - "service": "EC2", + "resource_type": "AWS::AppConfig::Deployment", + "service": "AppConfig", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::KeyPair", - "primary_identifier_paths": "/properties/KeyName", - "service": "EC2", + "resource_type": "AWS::AppConfig::DeploymentStrategy", + "service": "AppConfig", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::NatGateway", - "primary_identifier_paths": "/properties/NatGatewayId", - "service": "EC2", + "resource_type": "AWS::AppConfig::Environment", + "service": "AppConfig", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::NetworkAcl", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::AppConfig::HostedConfigurationVersion", + "service": "AppConfig", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::PrefixList", - "primary_identifier_paths": "/properties/PrefixListId", - "service": "EC2", + "resource_type": "AWS::AppSync::ApiKey", + "service": "AppSync", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::Route", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::AppSync::DataSource", + "service": "AppSync", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::RouteTable", - "primary_identifier_paths": "/properties/RouteTableId", - "service": "EC2", + "resource_type": "AWS::AppSync::FunctionConfiguration", + "service": "AppSync", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::SecurityGroup", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::AppSync::GraphQLApi", + "service": "AppSync", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::Subnet", - "primary_identifier_paths": "/properties/SubnetId", - "service": "EC2", + "resource_type": "AWS::AppSync::GraphQLSchema", + "service": "AppSync", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::SubnetRouteTableAssociation", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::AppSync::Resolver", + "service": "AppSync", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::TransitGateway", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::ApplicationAutoScaling::ScalableTarget", + "service": "ApplicationAutoScaling", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::TransitGatewayAttachment", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::ApplicationAutoScaling::ScalingPolicy", + "service": "ApplicationAutoScaling", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::VPC", - "primary_identifier_paths": "/properties/VpcId", - "service": "EC2", + "resource_type": "AWS::Athena::DataCatalog", + "service": "Athena", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::VPCEndpoint", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::Athena::NamedQuery", + "service": "Athena", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::EC2::VPCGatewayAttachment", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::Athena::WorkGroup", + "service": "Athena", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::ECR::Repository", - "primary_identifier_paths": "/properties/RepositoryName", - "service": "ECR", + "resource_type": "AWS::AutoScaling::AutoScalingGroup", + "service": "AutoScaling", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Elasticsearch::Domain", - "primary_identifier_paths": "/properties/Id", - "service": "Elasticsearch", + "resource_type": "AWS::AutoScaling::LaunchConfiguration", + "service": "AutoScaling", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Events::ApiDestination", - "primary_identifier_paths": "/properties/Name", - "service": "Events", + "resource_type": "AWS::Backup::BackupPlan", + "service": "Backup", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Events::Connection", - "primary_identifier_paths": "/properties/Name", - "service": "Events", + "resource_type": "AWS::Batch::ComputeEnvironment", + "service": "Batch", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Events::EventBus", - "primary_identifier_paths": "/properties/Id", - "service": "Events", + "resource_type": "AWS::Batch::JobDefinition", + "service": "Batch", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Events::EventBusPolicy", - "primary_identifier_paths": "/properties/Id", - "service": "Events", + "resource_type": "AWS::Batch::JobQueue", + "service": "Batch", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Events::Rule", - "primary_identifier_paths": "/properties/Id", - "service": "Events", + "resource_type": "AWS::CDK::Metadata", + "service": "CDK", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::IAM::AccessKey", - "primary_identifier_paths": "/properties/Id", - "service": "IAM", + "resource_type": "AWS::CertificateManager::Certificate", + "service": "CertificateManager", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::IAM::Group", - "primary_identifier_paths": "/properties/Id", - "service": "IAM", + "resource_type": "AWS::CloudFormation::CustomResource", + "service": "CloudFormation", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::IAM::InstanceProfile", - "primary_identifier_paths": "/properties/InstanceProfileName", - "service": "IAM", + "resource_type": "AWS::CloudFormation::Macro", + "service": "CloudFormation", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::IAM::ManagedPolicy", - "primary_identifier_paths": "/properties/Id", - "service": "IAM", + "resource_type": "AWS::CloudFormation::Stack", + "service": "CloudFormation", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::IAM::Policy", - "primary_identifier_paths": "/properties/Id", - "service": "IAM", + "resource_type": "AWS::CloudFormation::WaitCondition", + "service": "CloudFormation", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::IAM::Role", - "primary_identifier_paths": "/properties/RoleName", - "service": "IAM", + "resource_type": "AWS::CloudFormation::WaitConditionHandle", + "service": "CloudFormation", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::IAM::ServerCertificate", - "primary_identifier_paths": "/properties/ServerCertificateName", - "service": "IAM", + "resource_type": "AWS::CloudFront::CachePolicy", + "service": "CloudFront", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::IAM::ServiceLinkedRole", - "primary_identifier_paths": "/properties/Id", - "service": "IAM", + "resource_type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", + "service": "CloudFront", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::IAM::User", - "primary_identifier_paths": "/properties/Id", - "service": "IAM", + "resource_type": "AWS::CloudFront::Distribution", + "service": "CloudFront", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::KMS::Alias", - "primary_identifier_paths": "/properties/AliasName", - "service": "KMS", + "resource_type": "AWS::CloudFront::Function", + "service": "CloudFront", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::KMS::Key", - "primary_identifier_paths": "/properties/KeyId", - "service": "KMS", + "resource_type": "AWS::CloudFront::OriginAccessControl", + "service": "CloudFront", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Kinesis::Stream", - "primary_identifier_paths": "/properties/Name", - "service": "Kinesis", + "resource_type": "AWS::CloudFront::OriginRequestPolicy", + "service": "CloudFront", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Kinesis::StreamConsumer", - "primary_identifier_paths": "/properties/Id", - "service": "Kinesis", + "resource_type": "AWS::CloudFront::ResponseHeadersPolicy", + "service": "CloudFront", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::KinesisFirehose::DeliveryStream", - "primary_identifier_paths": "/properties/DeliveryStreamName", - "service": "KinesisFirehose", + "resource_type": "AWS::CloudTrail::Trail", + "service": "CloudTrail", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Lambda::Alias", - "primary_identifier_paths": "/properties/Id", - "service": "Lambda", + "resource_type": "AWS::CloudWatch::Alarm", + "service": "CloudWatch", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Lambda::CodeSigningConfig", - "primary_identifier_paths": "/properties/CodeSigningConfigArn", - "service": "Lambda", + "resource_type": "AWS::CloudWatch::CompositeAlarm", + "service": "CloudWatch", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Lambda::EventInvokeConfig", - "primary_identifier_paths": "/properties/Id", - "service": "Lambda", + "resource_type": "AWS::CodeBuild::Project", + "service": "CodeBuild", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Lambda::EventSourceMapping", - "primary_identifier_paths": "/properties/Id", - "service": "Lambda", + "resource_type": "AWS::CodeDeploy::Application", + "service": "CodeDeploy", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Lambda::Function", - "primary_identifier_paths": "/properties/FunctionName", - "service": "Lambda", + "resource_type": "AWS::CodeDeploy::DeploymentConfig", + "service": "CodeDeploy", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Lambda::LayerVersion", - "primary_identifier_paths": "/properties/Id", - "service": "Lambda", - "create": true, - "delete": true, - "update": false, - "tier": "Community" - }, - { - "resource_type": "AWS::Lambda::LayerVersionPermission", - "primary_identifier_paths": "/properties/Id", - "service": "Lambda", - "create": true, - "delete": true, - "update": false, - "tier": "Community" - }, - { - "resource_type": "AWS::Lambda::Permission", - "primary_identifier_paths": "/properties/Id", - "service": "Lambda", - "create": true, - "delete": true, - "update": false, - "tier": "Community" - }, - { - "resource_type": "AWS::Lambda::Url", - "primary_identifier_paths": "/properties/FunctionArn", - "service": "Lambda", - "create": true, - "delete": true, - "update": true, - "tier": "Community" - }, - { - "resource_type": "AWS::Lambda::Version", - "primary_identifier_paths": "/properties/Id", - "service": "Lambda", - "create": true, - "delete": true, - "update": true, - "tier": "Community" - }, - { - "resource_type": "AWS::Logs::LogGroup", - "primary_identifier_paths": "/properties/LogGroupName", - "service": "Logs", - "create": true, - "delete": true, - "update": false, - "tier": "Community" - }, - { - "resource_type": "AWS::Logs::LogStream", - "primary_identifier_paths": "/properties/Id", - "service": "Logs", + "resource_type": "AWS::CodeDeploy::DeploymentGroup", + "service": "CodeDeploy", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Logs::SubscriptionFilter", - "primary_identifier_paths": "/properties/FilterName\n/properties/LogGroupName", - "service": "Logs", + "resource_type": "AWS::CodePipeline::Pipeline", + "service": "CodePipeline", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::OpenSearchService::Domain", - "primary_identifier_paths": "/properties/DomainName", - "service": "OpenSearchService", + "resource_type": "AWS::Cognito::IdentityPool", + "service": "Cognito", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Redshift::Cluster", - "primary_identifier_paths": "/properties/ClusterIdentifier", - "service": "Redshift", + "resource_type": "AWS::Cognito::IdentityPoolRoleAttachment", + "service": "Cognito", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::ResourceGroups::Group", - "primary_identifier_paths": "/properties/Name", - "service": "ResourceGroups", + "resource_type": "AWS::Cognito::UserPool", + "service": "Cognito", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Route53::HealthCheck", - "primary_identifier_paths": "/properties/HealthCheckId", - "service": "Route53", + "resource_type": "AWS::Cognito::UserPoolClient", + "service": "Cognito", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Route53::RecordSet", - "primary_identifier_paths": "/properties/Id", - "service": "Route53", + "resource_type": "AWS::Cognito::UserPoolDomain", + "service": "Cognito", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::S3::Bucket", - "primary_identifier_paths": "/properties/BucketName", - "service": "S3", + "resource_type": "AWS::Cognito::UserPoolGroup", + "service": "Cognito", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::S3::BucketPolicy", - "primary_identifier_paths": "/properties/Id", - "service": "S3", + "resource_type": "AWS::Cognito::UserPoolIdentityProvider", + "service": "Cognito", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SES::EmailIdentity", - "primary_identifier_paths": "/properties/EmailIdentity", - "service": "SES", + "resource_type": "AWS::Cognito::UserPoolResourceServer", + "service": "Cognito", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SNS::Subscription", - "primary_identifier_paths": "/properties/Id", - "service": "SNS", + "resource_type": "AWS::DMS::Endpoint", + "service": "DMS", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SNS::Topic", - "primary_identifier_paths": "/properties/TopicArn", - "service": "SNS", + "resource_type": "AWS::DMS::ReplicationConfig", + "service": "DMS", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SNS::TopicPolicy", - "primary_identifier_paths": "/properties/Id", - "service": "SNS", + "resource_type": "AWS::DMS::ReplicationInstance", + "service": "DMS", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SQS::Queue", - "primary_identifier_paths": "/properties/QueueUrl", - "service": "SQS", + "resource_type": "AWS::DMS::ReplicationSubnetGroup", + "service": "DMS", "create": true, "delete": true, - "update": true, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SQS::QueueInlinePolicy", - "primary_identifier_paths": "", - "service": "SQS", + "resource_type": "AWS::DMS::ReplicationTask", + "service": "DMS", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SQS::QueuePolicy", - "primary_identifier_paths": "/properties/Id", - "service": "SQS", + "resource_type": "AWS::DocDB::DBCluster", + "service": "DocDB", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SSM::MaintenanceWindow", - "primary_identifier_paths": "/properties/Id", - "service": "SSM", + "resource_type": "AWS::DocDB::DBClusterParameterGroup", + "service": "DocDB", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SSM::MaintenanceWindowTarget", - "primary_identifier_paths": "/properties/Id", - "service": "SSM", + "resource_type": "AWS::DocDB::DBInstance", + "service": "DocDB", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SSM::MaintenanceWindowTask", - "primary_identifier_paths": "/properties/Id", - "service": "SSM", + "resource_type": "AWS::DocDB::DBSubnetGroup", + "service": "DocDB", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SSM::Parameter", - "primary_identifier_paths": "/properties/Id", - "service": "SSM", + "resource_type": "AWS::DynamoDB::GlobalTable", + "service": "DynamoDB", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SSM::PatchBaseline", - "primary_identifier_paths": "/properties/Id", - "service": "SSM", + "resource_type": "AWS::DynamoDB::Table", + "service": "DynamoDB", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": true }, { - "resource_type": "AWS::Scheduler::Schedule", - "primary_identifier_paths": "/properties/Name", - "service": "Scheduler", + "resource_type": "AWS::EC2::DHCPOptions", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Scheduler::ScheduleGroup", - "primary_identifier_paths": "/properties/Name", - "service": "Scheduler", + "resource_type": "AWS::EC2::EIP", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SecretsManager::ResourcePolicy", - "primary_identifier_paths": "/properties/Id", - "service": "SecretsManager", + "resource_type": "AWS::EC2::Instance", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SecretsManager::RotationSchedule", - "primary_identifier_paths": "/properties/Id", - "service": "SecretsManager", + "resource_type": "AWS::EC2::InternetGateway", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SecretsManager::Secret", - "primary_identifier_paths": "/properties/Id", - "service": "SecretsManager", + "resource_type": "AWS::EC2::KeyPair", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::SecretsManager::SecretTargetAttachment", - "primary_identifier_paths": "/properties/Id", - "service": "SecretsManager", + "resource_type": "AWS::EC2::LaunchTemplate", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::ServiceDiscovery::HttpNamespace", - "primary_identifier_paths": "/properties/Id", - "service": "ServiceDiscovery", + "resource_type": "AWS::EC2::NatGateway", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::ServiceDiscovery::PrivateDnsNamespace", - "primary_identifier_paths": "/properties/Id", - "service": "ServiceDiscovery", + "resource_type": "AWS::EC2::NetworkAcl", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::ServiceDiscovery::PublicDnsNamespace", - "primary_identifier_paths": "/properties/Id", - "service": "ServiceDiscovery", + "resource_type": "AWS::EC2::PrefixList", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::ServiceDiscovery::Service", - "primary_identifier_paths": "/properties/Id", - "service": "ServiceDiscovery", + "resource_type": "AWS::EC2::Route", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::StepFunctions::Activity", - "primary_identifier_paths": "/properties/Arn", - "service": "StepFunctions", + "resource_type": "AWS::EC2::RouteTable", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::StepFunctions::StateMachine", - "primary_identifier_paths": "/properties/Arn", - "service": "StepFunctions", + "resource_type": "AWS::EC2::SecurityGroup", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Timestream::Database", - "primary_identifier_paths": "/properties/DatabaseName", - "service": "Timestream", + "resource_type": "AWS::EC2::SecurityGroupEgress", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::Timestream::Table", - "primary_identifier_paths": "/properties/DatabaseName\n/properties/TableName", - "service": "Timestream", + "resource_type": "AWS::EC2::SecurityGroupIngress", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Community" + "update": false }, { - "resource_type": "AWS::ACMPCA::Certificate", - "primary_identifier_paths": "/properties/Arn\n/properties/CertificateAuthorityArn", - "service": "ACMPCA", + "resource_type": "AWS::EC2::Subnet", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ACMPCA::CertificateAuthority", - "primary_identifier_paths": "/properties/Arn", - "service": "ACMPCA", + "resource_type": "AWS::EC2::SubnetRouteTableAssociation", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ACMPCA::CertificateAuthorityActivation", - "primary_identifier_paths": "/properties/CertificateAuthorityArn", - "service": "ACMPCA", + "resource_type": "AWS::EC2::TransitGateway", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ACMPCA::Permission", - "primary_identifier_paths": "/properties/CertificateAuthorityArn\n/properties/Principal", - "service": "ACMPCA", + "resource_type": "AWS::EC2::TransitGatewayAttachment", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Amplify::App", - "primary_identifier_paths": "/properties/Arn", - "service": "Amplify", + "resource_type": "AWS::EC2::VPC", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGateway::Authorizer", - "primary_identifier_paths": "/properties/AuthorizerId\n/properties/RestApiId", - "service": "ApiGateway", + "resource_type": "AWS::EC2::VPCCidrBlock", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGateway::VpcLink", - "primary_identifier_paths": "/properties/VpcLinkId", - "service": "ApiGateway", + "resource_type": "AWS::EC2::VPCEndpoint", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::Api", - "primary_identifier_paths": "/properties/ApiId", - "service": "ApiGatewayV2", + "resource_type": "AWS::EC2::VPCEndpointService", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::ApiMapping", - "primary_identifier_paths": "/properties/Id", - "service": "ApiGatewayV2", + "resource_type": "AWS::EC2::VPCGatewayAttachment", + "service": "EC2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::Authorizer", - "primary_identifier_paths": "/properties/ApiId\n/properties/AuthorizerId", - "service": "ApiGatewayV2", + "resource_type": "AWS::ECR::Repository", + "service": "ECR", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::Deployment", - "primary_identifier_paths": "/properties/ApiId\n/properties/DeploymentId", - "service": "ApiGatewayV2", + "resource_type": "AWS::ECS::CapacityProvider", + "service": "ECS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::DomainName", - "primary_identifier_paths": "/properties/Id", - "service": "ApiGatewayV2", + "resource_type": "AWS::ECS::Cluster", + "service": "ECS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::Integration", - "primary_identifier_paths": "/properties/Id", - "service": "ApiGatewayV2", + "resource_type": "AWS::ECS::ClusterCapacityProviderAssociations", + "service": "ECS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::IntegrationResponse", - "primary_identifier_paths": "/properties/ApiId\n/properties/IntegrationId\n/properties/IntegrationResponseId", - "service": "ApiGatewayV2", + "resource_type": "AWS::ECS::Service", + "service": "ECS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::Route", - "primary_identifier_paths": "/properties/ApiId\n/properties/RouteId", - "service": "ApiGatewayV2", + "resource_type": "AWS::ECS::TaskDefinition", + "service": "ECS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::RouteResponse", - "primary_identifier_paths": "/properties/Id", - "service": "ApiGatewayV2", + "resource_type": "AWS::EFS::AccessPoint", + "service": "EFS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::Stage", - "primary_identifier_paths": "/properties/Id", - "service": "ApiGatewayV2", + "resource_type": "AWS::EFS::FileSystem", + "service": "EFS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApiGatewayV2::VpcLink", - "primary_identifier_paths": "/properties/VpcLinkId", - "service": "ApiGatewayV2", + "resource_type": "AWS::EFS::MountTarget", + "service": "EFS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppConfig::Application", - "primary_identifier_paths": "/properties/Id", - "service": "AppConfig", + "resource_type": "AWS::EKS::Cluster", + "service": "EKS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppConfig::ConfigurationProfile", - "primary_identifier_paths": "/properties/Id", - "service": "AppConfig", + "resource_type": "AWS::EKS::FargateProfile", + "service": "EKS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppConfig::Deployment", - "primary_identifier_paths": "/properties/Id", - "service": "AppConfig", + "resource_type": "AWS::EKS::Nodegroup", + "service": "EKS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppConfig::DeploymentStrategy", - "primary_identifier_paths": "/properties/Id", - "service": "AppConfig", + "resource_type": "AWS::ElastiCache::CacheCluster", + "service": "ElastiCache", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppConfig::Environment", - "primary_identifier_paths": "/properties/Id", - "service": "AppConfig", + "resource_type": "AWS::ElastiCache::ParameterGroup", + "service": "ElastiCache", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppConfig::HostedConfigurationVersion", - "primary_identifier_paths": "/properties/Id", - "service": "AppConfig", + "resource_type": "AWS::ElastiCache::ReplicationGroup", + "service": "ElastiCache", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppSync::ApiKey", - "primary_identifier_paths": "/properties/ApiKeyId", - "service": "AppSync", + "resource_type": "AWS::ElastiCache::SecurityGroup", + "service": "ElastiCache", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppSync::DataSource", - "primary_identifier_paths": "/properties/Id", - "service": "AppSync", + "resource_type": "AWS::ElastiCache::SubnetGroup", + "service": "ElastiCache", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppSync::FunctionConfiguration", - "primary_identifier_paths": "/properties/Id", - "service": "AppSync", + "resource_type": "AWS::ElasticBeanstalk::Application", + "service": "ElasticBeanstalk", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppSync::GraphQLApi", - "primary_identifier_paths": "/properties/Id", - "service": "AppSync", + "resource_type": "AWS::ElasticBeanstalk::ApplicationVersion", + "service": "ElasticBeanstalk", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppSync::GraphQLSchema", - "primary_identifier_paths": "/properties/Id", - "service": "AppSync", + "resource_type": "AWS::ElasticBeanstalk::ConfigurationTemplate", + "service": "ElasticBeanstalk", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::AppSync::Resolver", - "primary_identifier_paths": "/properties/Id", - "service": "AppSync", + "resource_type": "AWS::ElasticBeanstalk::Environment", + "service": "ElasticBeanstalk", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApplicationAutoScaling::ScalableTarget", - "primary_identifier_paths": "/properties/Id", - "service": "ApplicationAutoScaling", + "resource_type": "AWS::ElasticLoadBalancingV2::Listener", + "service": "ElasticLoadBalancingV2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ApplicationAutoScaling::ScalingPolicy", - "primary_identifier_paths": "/properties/Id", - "service": "ApplicationAutoScaling", + "resource_type": "AWS::ElasticLoadBalancingV2::ListenerRule", + "service": "ElasticLoadBalancingV2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Athena::DataCatalog", - "primary_identifier_paths": "/properties/Name", - "service": "Athena", + "resource_type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "service": "ElasticLoadBalancingV2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Athena::NamedQuery", - "primary_identifier_paths": "/properties/NamedQueryId", - "service": "Athena", + "resource_type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "service": "ElasticLoadBalancingV2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Athena::WorkGroup", - "primary_identifier_paths": "/properties/Name", - "service": "Athena", + "resource_type": "AWS::Elasticsearch::Domain", + "service": "Elasticsearch", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": true }, { - "resource_type": "AWS::Backup::BackupPlan", - "primary_identifier_paths": "/properties/BackupPlanId", - "service": "Backup", + "resource_type": "AWS::Events::ApiDestination", + "service": "Events", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Batch::ComputeEnvironment", - "primary_identifier_paths": "/properties/ComputeEnvironmentArn", - "service": "Batch", + "resource_type": "AWS::Events::Connection", + "service": "Events", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Batch::JobDefinition", - "primary_identifier_paths": "/properties/Id", - "service": "Batch", + "resource_type": "AWS::Events::EventBus", + "service": "Events", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Batch::JobQueue", - "primary_identifier_paths": "/properties/JobQueueArn", - "service": "Batch", + "resource_type": "AWS::Events::EventBusPolicy", + "service": "Events", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CloudFormation::CustomResource", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFormation", + "resource_type": "AWS::Events::Rule", + "service": "Events", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CloudFront::CachePolicy", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFront", + "resource_type": "AWS::Glue::Classifier", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFront", + "resource_type": "AWS::Glue::Connection", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CloudFront::Distribution", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFront", + "resource_type": "AWS::Glue::Crawler", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CloudFront::Function", - "primary_identifier_paths": "/properties/FunctionARN", - "service": "CloudFront", + "resource_type": "AWS::Glue::Database", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CloudFront::OriginAccessControl", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFront", + "resource_type": "AWS::Glue::Job", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CloudFront::OriginRequestPolicy", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFront", + "resource_type": "AWS::Glue::Registry", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CloudFront::ResponseHeadersPolicy", - "primary_identifier_paths": "/properties/Id", - "service": "CloudFront", + "resource_type": "AWS::Glue::Schema", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CloudTrail::Trail", - "primary_identifier_paths": "/properties/TrailName", - "service": "CloudTrail", + "resource_type": "AWS::Glue::SchemaVersion", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CodeBuild::Project", - "primary_identifier_paths": "/properties/Id", - "service": "CodeBuild", + "resource_type": "AWS::Glue::SchemaVersionMetadata", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CodeDeploy::Application", - "primary_identifier_paths": "/properties/ApplicationName", - "service": "CodeDeploy", + "resource_type": "AWS::Glue::Table", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CodeDeploy::DeploymentConfig", - "primary_identifier_paths": "/properties/DeploymentConfigName", - "service": "CodeDeploy", + "resource_type": "AWS::Glue::Trigger", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CodeDeploy::DeploymentGroup", - "primary_identifier_paths": "/properties/Id", - "service": "CodeDeploy", + "resource_type": "AWS::Glue::Workflow", + "service": "Glue", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::CodePipeline::Pipeline", - "primary_identifier_paths": "/properties/Id", - "service": "CodePipeline", + "resource_type": "AWS::IAM::AccessKey", + "service": "IAM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": true }, { - "resource_type": "AWS::Cognito::IdentityPool", - "primary_identifier_paths": "/properties/Id", - "service": "Cognito", + "resource_type": "AWS::IAM::Group", + "service": "IAM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Cognito::IdentityPoolRoleAttachment", - "primary_identifier_paths": "/properties/Id", - "service": "Cognito", + "resource_type": "AWS::IAM::InstanceProfile", + "service": "IAM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Cognito::UserPool", - "primary_identifier_paths": "/properties/Id", - "service": "Cognito", + "resource_type": "AWS::IAM::ManagedPolicy", + "service": "IAM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Cognito::UserPoolClient", - "primary_identifier_paths": "/properties/Id", - "service": "Cognito", + "resource_type": "AWS::IAM::Policy", + "service": "IAM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Cognito::UserPoolDomain", - "primary_identifier_paths": "/properties/Id", - "service": "Cognito", + "resource_type": "AWS::IAM::Role", + "service": "IAM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Cognito::UserPoolGroup", - "primary_identifier_paths": "/properties/Id", - "service": "Cognito", + "resource_type": "AWS::IAM::ServerCertificate", + "service": "IAM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Cognito::UserPoolIdentityProvider", - "primary_identifier_paths": "/properties/Id", - "service": "Cognito", + "resource_type": "AWS::IAM::ServiceLinkedRole", + "service": "IAM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Cognito::UserPoolResourceServer", - "primary_identifier_paths": "/properties/Id", - "service": "Cognito", + "resource_type": "AWS::IAM::User", + "service": "IAM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::DMS::Endpoint", - "primary_identifier_paths": "/properties/Id", - "service": "DMS", + "resource_type": "AWS::IoT::Certificate", + "service": "IoT", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::DMS::ReplicationConfig", - "primary_identifier_paths": "", - "service": "DMS", + "resource_type": "AWS::IoT::Policy", + "service": "IoT", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::DMS::ReplicationInstance", - "primary_identifier_paths": "/properties/Id", - "service": "DMS", + "resource_type": "AWS::IoT::RoleAlias", + "service": "IoT", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::DMS::ReplicationSubnetGroup", - "primary_identifier_paths": "/properties/Id", - "service": "DMS", + "resource_type": "AWS::IoT::Thing", + "service": "IoT", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::DMS::ReplicationTask", - "primary_identifier_paths": "/properties/Id", - "service": "DMS", + "resource_type": "AWS::IoT::TopicRule", + "service": "IoT", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::DocDB::DBCluster", - "primary_identifier_paths": "/properties/Id", - "service": "DocDB", + "resource_type": "AWS::IoTAnalytics::Channel", + "service": "IoTAnalytics", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::DocDB::DBClusterParameterGroup", - "primary_identifier_paths": "/properties/Id", - "service": "DocDB", + "resource_type": "AWS::IoTAnalytics::Dataset", + "service": "IoTAnalytics", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::DocDB::DBInstance", - "primary_identifier_paths": "/properties/Id", - "service": "DocDB", + "resource_type": "AWS::IoTAnalytics::Datastore", + "service": "IoTAnalytics", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::DocDB::DBSubnetGroup", - "primary_identifier_paths": "/properties/Id", - "service": "DocDB", + "resource_type": "AWS::IoTAnalytics::Pipeline", + "service": "IoTAnalytics", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EC2::EIP", - "primary_identifier_paths": "/properties/AllocationId\n/properties/PublicIp", - "service": "EC2", + "resource_type": "AWS::KMS::Alias", + "service": "KMS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EC2::LaunchTemplate", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::KMS::Key", + "service": "KMS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EC2::SecurityGroupEgress", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::Kinesis::Stream", + "service": "Kinesis", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EC2::SecurityGroupIngress", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::Kinesis::StreamConsumer", + "service": "Kinesis", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EC2::VPCCidrBlock", - "primary_identifier_paths": "/properties/Id", - "service": "EC2", + "resource_type": "AWS::KinesisAnalytics::Application", + "service": "KinesisAnalytics", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EC2::VPCEndpointService", - "primary_identifier_paths": "/properties/ServiceId", - "service": "EC2", + "resource_type": "AWS::KinesisAnalytics::ApplicationOutput", + "service": "KinesisAnalytics", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ECS::CapacityProvider", - "primary_identifier_paths": "/properties/Name", - "service": "ECS", + "resource_type": "AWS::KinesisAnalyticsV2::Application", + "service": "KinesisAnalyticsV2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ECS::Cluster", - "primary_identifier_paths": "/properties/ClusterName", - "service": "ECS", + "resource_type": "AWS::KinesisAnalyticsV2::ApplicationCloudWatchLoggingOption", + "service": "KinesisAnalyticsV2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ECS::ClusterCapacityProviderAssociations", - "primary_identifier_paths": "/properties/Cluster", - "service": "ECS", + "resource_type": "AWS::KinesisFirehose::DeliveryStream", + "service": "KinesisFirehose", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ECS::Service", - "primary_identifier_paths": "/properties/Cluster\n/properties/ServiceArn", - "service": "ECS", + "resource_type": "AWS::Lambda::Alias", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ECS::TaskDefinition", - "primary_identifier_paths": "/properties/TaskDefinitionArn", - "service": "ECS", + "resource_type": "AWS::Lambda::CapacityProvider", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EFS::AccessPoint", - "primary_identifier_paths": "/properties/AccessPointId", - "service": "EFS", + "resource_type": "AWS::Lambda::CodeSigningConfig", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EFS::FileSystem", - "primary_identifier_paths": "/properties/FileSystemId", - "service": "EFS", + "resource_type": "AWS::Lambda::EventInvokeConfig", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EFS::MountTarget", - "primary_identifier_paths": "/properties/Id", - "service": "EFS", + "resource_type": "AWS::Lambda::EventSourceMapping", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EKS::Cluster", - "primary_identifier_paths": "/properties/Name", - "service": "EKS", + "resource_type": "AWS::Lambda::Function", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": true }, { - "resource_type": "AWS::EKS::FargateProfile", - "primary_identifier_paths": "/properties/ClusterName\n/properties/FargateProfileName", - "service": "EKS", + "resource_type": "AWS::Lambda::LayerVersion", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::EKS::Nodegroup", - "primary_identifier_paths": "/properties/Id", - "service": "EKS", + "resource_type": "AWS::Lambda::LayerVersionPermission", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElastiCache::CacheCluster", - "primary_identifier_paths": "/properties/Id", - "service": "ElastiCache", + "resource_type": "AWS::Lambda::Permission", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElastiCache::ParameterGroup", - "primary_identifier_paths": "/properties/Id", - "service": "ElastiCache", + "resource_type": "AWS::Lambda::Url", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": true }, { - "resource_type": "AWS::ElastiCache::ReplicationGroup", - "primary_identifier_paths": "/properties/ReplicationGroupId", - "service": "ElastiCache", + "resource_type": "AWS::Lambda::Version", + "service": "Lambda", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": true }, { - "resource_type": "AWS::ElastiCache::SecurityGroup", - "primary_identifier_paths": "/properties/Id", - "service": "ElastiCache", + "resource_type": "AWS::Logs::LogGroup", + "service": "Logs", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElastiCache::SubnetGroup", - "primary_identifier_paths": "/properties/CacheSubnetGroupName", - "service": "ElastiCache", + "resource_type": "AWS::Logs::LogStream", + "service": "Logs", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElasticBeanstalk::Application", - "primary_identifier_paths": "/properties/ApplicationName", - "service": "ElasticBeanstalk", + "resource_type": "AWS::Logs::SubscriptionFilter", + "service": "Logs", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElasticBeanstalk::ApplicationVersion", - "primary_identifier_paths": "/properties/ApplicationName\n/properties/Id", - "service": "ElasticBeanstalk", + "resource_type": "AWS::MSK::Cluster", + "service": "MSK", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElasticBeanstalk::ConfigurationTemplate", - "primary_identifier_paths": "/properties/ApplicationName\n/properties/TemplateName", - "service": "ElasticBeanstalk", + "resource_type": "AWS::MWAA::Environment", + "service": "MWAA", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElasticBeanstalk::Environment", - "primary_identifier_paths": "/properties/EnvironmentName", - "service": "ElasticBeanstalk", + "resource_type": "AWS::Neptune::DBCluster", + "service": "Neptune", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElasticLoadBalancingV2::Listener", - "primary_identifier_paths": "/properties/ListenerArn", - "service": "ElasticLoadBalancingV2", + "resource_type": "AWS::Neptune::DBClusterParameterGroup", + "service": "Neptune", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElasticLoadBalancingV2::ListenerRule", - "primary_identifier_paths": "/properties/RuleArn", - "service": "ElasticLoadBalancingV2", + "resource_type": "AWS::Neptune::DBInstance", + "service": "Neptune", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - "primary_identifier_paths": "/properties/Id", - "service": "ElasticLoadBalancingV2", + "resource_type": "AWS::Neptune::DBParameterGroup", + "service": "Neptune", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "primary_identifier_paths": "/properties/TargetGroupArn", - "service": "ElasticLoadBalancingV2", + "resource_type": "AWS::Neptune::DBSubnetGroup", + "service": "Neptune", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::Classifier", - "primary_identifier_paths": "/properties/Id", - "service": "Glue", + "resource_type": "AWS::OpenSearchService::Domain", + "service": "OpenSearchService", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": true }, { - "resource_type": "AWS::Glue::Connection", - "primary_identifier_paths": "/properties/Id", - "service": "Glue", + "resource_type": "AWS::Pipes::Pipe", + "service": "Pipes", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::Crawler", - "primary_identifier_paths": "/properties/Id", - "service": "Glue", + "resource_type": "AWS::QLDB::Ledger", + "service": "QLDB", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::Database", - "primary_identifier_paths": "/properties/Id", - "service": "Glue", + "resource_type": "AWS::RDS::DBCluster", + "service": "RDS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::Job", - "primary_identifier_paths": "/properties/Id", - "service": "Glue", + "resource_type": "AWS::RDS::DBClusterParameterGroup", + "service": "RDS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::Registry", - "primary_identifier_paths": "/properties/Arn", - "service": "Glue", + "resource_type": "AWS::RDS::DBInstance", + "service": "RDS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::Schema", - "primary_identifier_paths": "/properties/Arn", - "service": "Glue", + "resource_type": "AWS::RDS::DBParameterGroup", + "service": "RDS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::SchemaVersion", - "primary_identifier_paths": "/properties/VersionId", - "service": "Glue", + "resource_type": "AWS::RDS::DBProxy", + "service": "RDS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::SchemaVersionMetadata", - "primary_identifier_paths": "/properties/Key\n/properties/SchemaVersionId\n/properties/Value", - "service": "Glue", + "resource_type": "AWS::RDS::DBProxyEndpoint", + "service": "RDS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::Table", - "primary_identifier_paths": "/properties/Id", - "service": "Glue", + "resource_type": "AWS::RDS::DBProxyTargetGroup", + "service": "RDS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::Trigger", - "primary_identifier_paths": "/properties/Id", - "service": "Glue", + "resource_type": "AWS::RDS::DBSubnetGroup", + "service": "RDS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Glue::Workflow", - "primary_identifier_paths": "/properties/Id", - "service": "Glue", + "resource_type": "AWS::RDS::GlobalCluster", + "service": "RDS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::IoT::Certificate", - "primary_identifier_paths": "/properties/Id", - "service": "IoT", + "resource_type": "AWS::Redshift::Cluster", + "service": "Redshift", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": true }, { - "resource_type": "AWS::IoT::Policy", - "primary_identifier_paths": "/properties/Id", - "service": "IoT", + "resource_type": "AWS::Redshift::ClusterParameterGroup", + "service": "Redshift", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::IoT::RoleAlias", - "primary_identifier_paths": "/properties/RoleAlias", - "service": "IoT", + "resource_type": "AWS::Redshift::ClusterSecurityGroup", + "service": "Redshift", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::IoT::Thing", - "primary_identifier_paths": "/properties/ThingName", - "service": "IoT", + "resource_type": "AWS::Redshift::ClusterSubnetGroup", + "service": "Redshift", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::IoT::TopicRule", - "primary_identifier_paths": "/properties/RuleName", - "service": "IoT", + "resource_type": "AWS::ResourceGroups::Group", + "service": "ResourceGroups", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::IoTAnalytics::Channel", - "primary_identifier_paths": "/properties/ChannelName", - "service": "IoTAnalytics", + "resource_type": "AWS::Route53::HealthCheck", + "service": "Route53", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::IoTAnalytics::Dataset", - "primary_identifier_paths": "/properties/DatasetName", - "service": "IoTAnalytics", + "resource_type": "AWS::Route53::HostedZone", + "service": "Route53", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::IoTAnalytics::Datastore", - "primary_identifier_paths": "/properties/DatastoreName", - "service": "IoTAnalytics", + "resource_type": "AWS::Route53::RecordSet", + "service": "Route53", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::IoTAnalytics::Pipeline", - "primary_identifier_paths": "/properties/PipelineName", - "service": "IoTAnalytics", + "resource_type": "AWS::S3::Bucket", + "service": "S3", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": true }, { - "resource_type": "AWS::KinesisAnalytics::Application", - "primary_identifier_paths": "/properties/Id", - "service": "KinesisAnalytics", + "resource_type": "AWS::S3::BucketPolicy", + "service": "S3", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::KinesisAnalytics::ApplicationOutput", - "primary_identifier_paths": "/properties/Id", - "service": "KinesisAnalytics", + "resource_type": "AWS::SES::EmailIdentity", + "service": "SES", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::KinesisAnalyticsV2::Application", - "primary_identifier_paths": "/properties/ApplicationName", - "service": "KinesisAnalyticsV2", + "resource_type": "AWS::SES::ReceiptRule", + "service": "SES", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::KinesisAnalyticsV2::ApplicationCloudWatchLoggingOption", - "primary_identifier_paths": "/properties/Id", - "service": "KinesisAnalyticsV2", + "resource_type": "AWS::SES::ReceiptRuleSet", + "service": "SES", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Lambda::CapacityProvider", - "primary_identifier_paths": "", - "service": "Lambda", + "resource_type": "AWS::SES::Template", + "service": "SES", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::MSK::Cluster", - "primary_identifier_paths": "/properties/Arn", - "service": "MSK", + "resource_type": "AWS::SNS::Subscription", + "service": "SNS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::MWAA::Environment", - "primary_identifier_paths": "/properties/Name", - "service": "MWAA", + "resource_type": "AWS::SNS::Topic", + "service": "SNS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Neptune::DBCluster", - "primary_identifier_paths": "/properties/DBClusterIdentifier", - "service": "Neptune", + "resource_type": "AWS::SNS::TopicPolicy", + "service": "SNS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Neptune::DBClusterParameterGroup", - "primary_identifier_paths": "/properties/Id", - "service": "Neptune", + "resource_type": "AWS::SQS::Queue", + "service": "SQS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": true }, { - "resource_type": "AWS::Neptune::DBInstance", - "primary_identifier_paths": "/properties/Id", - "service": "Neptune", + "resource_type": "AWS::SQS::QueueInlinePolicy", + "service": "SQS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Neptune::DBParameterGroup", - "primary_identifier_paths": "/properties/Id", - "service": "Neptune", + "resource_type": "AWS::SQS::QueuePolicy", + "service": "SQS", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Neptune::DBSubnetGroup", - "primary_identifier_paths": "/properties/Id", - "service": "Neptune", + "resource_type": "AWS::SSM::MaintenanceWindow", + "service": "SSM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Pipes::Pipe", - "primary_identifier_paths": "/properties/Name", - "service": "Pipes", + "resource_type": "AWS::SSM::MaintenanceWindowTarget", + "service": "SSM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::QLDB::Ledger", - "primary_identifier_paths": "/properties/Id", - "service": "QLDB", + "resource_type": "AWS::SSM::MaintenanceWindowTask", + "service": "SSM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::RDS::DBCluster", - "primary_identifier_paths": "/properties/DBClusterIdentifier", - "service": "RDS", + "resource_type": "AWS::SSM::Parameter", + "service": "SSM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::RDS::DBClusterParameterGroup", - "primary_identifier_paths": "/properties/DBClusterParameterGroupName", - "service": "RDS", + "resource_type": "AWS::SSM::PatchBaseline", + "service": "SSM", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::RDS::DBInstance", - "primary_identifier_paths": "/properties/DBInstanceIdentifier", - "service": "RDS", + "resource_type": "AWS::SageMaker::Endpoint", + "service": "SageMaker", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::RDS::DBParameterGroup", - "primary_identifier_paths": "/properties/DBParameterGroupName", - "service": "RDS", + "resource_type": "AWS::SageMaker::EndpointConfig", + "service": "SageMaker", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::RDS::DBProxy", - "primary_identifier_paths": "/properties/DBProxyName", - "service": "RDS", + "resource_type": "AWS::SageMaker::Model", + "service": "SageMaker", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::RDS::DBProxyEndpoint", - "primary_identifier_paths": "/properties/DBProxyEndpointName", - "service": "RDS", + "resource_type": "AWS::Scheduler::Schedule", + "service": "Scheduler", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::RDS::DBProxyTargetGroup", - "primary_identifier_paths": "/properties/TargetGroupArn", - "service": "RDS", + "resource_type": "AWS::Scheduler::ScheduleGroup", + "service": "Scheduler", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::RDS::DBSubnetGroup", - "primary_identifier_paths": "/properties/DBSubnetGroupName", - "service": "RDS", + "resource_type": "AWS::SecretsManager::ResourcePolicy", + "service": "SecretsManager", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::RDS::GlobalCluster", - "primary_identifier_paths": "/properties/GlobalClusterIdentifier", - "service": "RDS", + "resource_type": "AWS::SecretsManager::RotationSchedule", + "service": "SecretsManager", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Redshift::ClusterParameterGroup", - "primary_identifier_paths": "/properties/ParameterGroupName", - "service": "Redshift", + "resource_type": "AWS::SecretsManager::Secret", + "service": "SecretsManager", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Redshift::ClusterSecurityGroup", - "primary_identifier_paths": "/properties/Id", - "service": "Redshift", + "resource_type": "AWS::SecretsManager::SecretTargetAttachment", + "service": "SecretsManager", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Redshift::ClusterSubnetGroup", - "primary_identifier_paths": "/properties/ClusterSubnetGroupName", - "service": "Redshift", + "resource_type": "AWS::ServiceDiscovery::HttpNamespace", + "service": "ServiceDiscovery", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::Route53::HostedZone", - "primary_identifier_paths": "/properties/Id", - "service": "Route53", + "resource_type": "AWS::ServiceDiscovery::PrivateDnsNamespace", + "service": "ServiceDiscovery", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::SES::ReceiptRule", - "primary_identifier_paths": "/properties/Id", - "service": "SES", + "resource_type": "AWS::ServiceDiscovery::PublicDnsNamespace", + "service": "ServiceDiscovery", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::SES::ReceiptRuleSet", - "primary_identifier_paths": "/properties/Id", - "service": "SES", + "resource_type": "AWS::ServiceDiscovery::Service", + "service": "ServiceDiscovery", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::SES::Template", - "primary_identifier_paths": "/properties/Id", - "service": "SES", + "resource_type": "AWS::StepFunctions::Activity", + "service": "StepFunctions", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::SageMaker::Endpoint", - "primary_identifier_paths": "/properties/Id", - "service": "SageMaker", + "resource_type": "AWS::StepFunctions::StateMachine", + "service": "StepFunctions", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::SageMaker::EndpointConfig", - "primary_identifier_paths": "/properties/Id", - "service": "SageMaker", + "resource_type": "AWS::Timestream::Database", + "service": "Timestream", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { - "resource_type": "AWS::SageMaker::Model", - "primary_identifier_paths": "/properties/Id", - "service": "SageMaker", + "resource_type": "AWS::Timestream::Table", + "service": "Timestream", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { "resource_type": "AWS::VerifiedPermissions::IdentitySource", - "primary_identifier_paths": "", "service": "VerifiedPermissions", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { "resource_type": "AWS::VerifiedPermissions::Policy", - "primary_identifier_paths": "", "service": "VerifiedPermissions", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { "resource_type": "AWS::VerifiedPermissions::PolicyStore", - "primary_identifier_paths": "", "service": "VerifiedPermissions", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { "resource_type": "AWS::VerifiedPermissions::PolicyTemplate", - "primary_identifier_paths": "", "service": "VerifiedPermissions", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { "resource_type": "AWS::WAFv2::IPSet", - "primary_identifier_paths": "/properties/Id\n/properties/Name\n/properties/Scope", "service": "WAFv2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { "resource_type": "AWS::WAFv2::LoggingConfiguration", - "primary_identifier_paths": "/properties/ResourceArn", "service": "WAFv2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { "resource_type": "AWS::WAFv2::WebACL", - "primary_identifier_paths": "/properties/Id\n/properties/Name\n/properties/Scope", "service": "WAFv2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false }, { "resource_type": "AWS::WAFv2::WebACLAssociation", - "primary_identifier_paths": "/properties/ResourceArn\n/properties/WebACLArn", "service": "WAFv2", "create": true, "delete": true, - "update": false, - "tier": "Pro" + "update": false } ] } From 38ab6fe583e8db12fb77220791ea5e7eaee505c9 Mon Sep 17 00:00:00 2001 From: HarshCasper Date: Thu, 26 Feb 2026 23:27:05 +0530 Subject: [PATCH 3/3] remove existing workflows --- .github/workflows/docs-parity-updates.yml | 6 - scripts/create_cfn_coverage_table.py | 252 ---------------------- 2 files changed, 258 deletions(-) delete mode 100755 scripts/create_cfn_coverage_table.py diff --git a/.github/workflows/docs-parity-updates.yml b/.github/workflows/docs-parity-updates.yml index 659a87e0..9011ac45 100644 --- a/.github/workflows/docs-parity-updates.yml +++ b/.github/workflows/docs-parity-updates.yml @@ -139,12 +139,6 @@ jobs: python3 -m scripts.create_data_coverage -i target/metrics-implementation-details -r target/metrics-raw -o target/updated_coverage -s src/data/coverage/service_display_name.json mv -f target/updated_coverage/data/*.json src/data/coverage - - name: Generate CloudFormation Coverage Tables - working-directory: docs - continue-on-error: true - run: | - python3 scripts/create_cfn_coverage_table.py --cfn-json target/iac-catalog-assets/cfn_resources.json - - name: Check for changes id: check-for-changes working-directory: docs diff --git a/scripts/create_cfn_coverage_table.py b/scripts/create_cfn_coverage_table.py deleted file mode 100755 index 60f8c66a..00000000 --- a/scripts/create_cfn_coverage_table.py +++ /dev/null @@ -1,252 +0,0 @@ -from __future__ import annotations - -import argparse -import json -import re -from io import StringIO -from pathlib import Path -from typing import IO, Callable - -from dataclasses import dataclass - -COMMUNITY_HEADING_PATTERN = r"####\s*Community image" -PRO_HEADING_PATTERN = r"\n####\s*Pro image" -API_COVERAGE_HEADING_PATTERN = r"^\s*##\s|$\Z" -DEFAULT_PAGE_PATH = "src/content/docs/aws/services/cloudformation.mdx" - - -@dataclass -class ColumnConfig: - header: str - key: str - alignment: str = "left" - formatter: Callable[[any], str] | None = None - - def format_value(self, value: any) -> str: - if self.formatter: - return self.formatter(value) - return str(value) if value is not None else "-" - - -def bool_formatter(value: bool): - return "✅" if value else "-" - - -@dataclass -class TableConfig: - columns: list[ColumnConfig] - sort_by: str | None = None - - def get_headers(self) -> list[str]: - return [col.header for col in self.columns] - - -class MarkdownTableGenerator: - def __init__(self, config: TableConfig): - self.config = config - - def _calculate_column_widths(self, data: list[dict[str, any]]) -> list[int]: - widths = [] - - for col in self.config.columns: - max_width = len(col.header) - - for row in data: - value = row.get(col.key, "") - formatted_value = col.format_value(value) - max_width = max(max_width, len(formatted_value)) - - widths.append(max_width) - - return widths - - def _get_alignment_separator(self, alignment: str, width: int) -> str: - if alignment == "right": - return f"{'-' * (width + 1)}:" - elif alignment == "center": - return f":{'-' * width}:" - else: - return f"{'-' * width}" - - def _format_cell(self, value: str, width: int, alignment: str) -> str: - if alignment == "right": - return value.rjust(width) - elif alignment == "center": - return value.center(width) - else: - return value.ljust(width) - - def _write_header_row(self, writer: IO[str], widths: list[int]) -> None: - headers = self.config.get_headers() - formatted_headers = [] - - for i, header in enumerate(headers): - alignment = self.config.columns[i].alignment - formatted_header = self._format_cell(header, widths[i], alignment) - formatted_headers.append(formatted_header) - - writer.write(f"| {' | '.join(formatted_headers)} |\n") - - def _write_separator_row(self, writer: IO[str], widths: list[int]) -> None: - separators = [] - for i, col in enumerate(self.config.columns): - separator = self._get_alignment_separator(col.alignment, widths[i]) - separators.append(separator) - - writer.write(f"|{'|'.join(separators)}|\n") - - def _write_data_rows( - self, writer: IO[str], data: list[Dict[str, Any]], widths: list[int] - ) -> None: - if self.config.sort_by: - data = sorted(data, key=lambda x: x.get(self.config.sort_by, "")) - - for row in data: - formatted_cells = [] - - for i, col in enumerate(self.config.columns): - value = row.get(col.key, "") - formatted_value = col.format_value(value) - formatted_cell = self._format_cell( - formatted_value, widths[i], col.alignment - ) - formatted_cells.append(formatted_cell) - - writer.write(f"| {' | '.join(formatted_cells)} |\n") - - def generate_table(self, data: list[dict[str, any]] | None) -> str: - if not data: - return "" - - buffer = StringIO() - widths = self._calculate_column_widths(data) - - self._write_header_row(buffer, widths) - self._write_separator_row(buffer, widths) - self._write_data_rows(buffer, data, widths) - - table = buffer.getvalue().rstrip("\n") + "\n" - return table - -class CloudFormationDataTransformer(): - def transform(self, section_data: dict[str, any] | None) -> list[dict[str, any]]: - if not section_data: - return [] - - rows = [] - - for resource_type, metadata in section_data.items(): - methods = set(metadata.get("methods", [])) - - row = { - "resource": resource_type, - "create": "Create" in methods, - "delete": "Delete" in methods, - "update": "Update" in methods, - } - rows.append(row) - return rows - - -def create_argument_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser( - description="Update CloudFormation Resources tables in docs" - ) - parser.add_argument( - "--cfn-json", - required=True, - type=Path, - help="Path to iac-catalog-assets/cfn_resources.json in downloaded artifacts", - ) - parser.add_argument( - "--md-file", - required=False, - type=Path, - default=str(DEFAULT_PAGE_PATH), - help="Markdown file which needs to be updated", - ) - - return parser - - -def _load_cfn_file(cfn_file_path: Path) -> dict[str, any]: - try: - with cfn_file_path.open("r", encoding="utf-8") as f: - return json.load(f) - except json.JSONDecodeError as e: - raise ValueError(f"Invalid JSON in cfn json file: {e}") - - -def replace_content_between( - content: str, - starting_rx: str, - ending_rx: str, - replacement_block: str, -) -> str: - # Build a regex that replaces the content between two headings starting_rx and ending_rx. - # Group1 - start heading - # Group2 - content; lookahead preserves end boundary. - pattern = re.compile( - rf"(^{starting_rx}\s*\n)(.*?)(?={ending_rx})", - re.DOTALL | re.MULTILINE, - ) - - match = pattern.search(content) - if not match: - raise ValueError( - f"Could not find section with heading pattern: {starting_rx!r}" - ) - - heading = match.group(1) - replacement = f"{heading}{replacement_block}" if replacement_block else heading - - return pattern.sub(replacement, content, count=1) - - -def main(): - parser = create_argument_parser() - args = parser.parse_args() - - table_config = TableConfig( - columns=[ - ColumnConfig("Resource", "resource", "left"), - ColumnConfig("Create", "create", "right", bool_formatter), - ColumnConfig("Delete", "delete", "right", bool_formatter), - ColumnConfig("Update", "update", "right", bool_formatter), - ] - ) - - table_generator = MarkdownTableGenerator(table_config) - data_transformer = CloudFormationDataTransformer() - - cfn_catalog = _load_cfn_file(args.cfn_json) - - community_data = data_transformer.transform(cfn_catalog.get("community")) - pro_data = data_transformer.transform(cfn_catalog.get("pro")) - - community_table = table_generator.generate_table(community_data) - pro_table = table_generator.generate_table(pro_data) - - original_doc = args.md_file.read_text(encoding="utf-8") - updated_doc = original_doc - - updated_doc = replace_content_between( - content=original_doc, - starting_rx=COMMUNITY_HEADING_PATTERN, - ending_rx=PRO_HEADING_PATTERN, - replacement_block=community_table, - ) - - updated_doc = replace_content_between( - content=updated_doc, - starting_rx=PRO_HEADING_PATTERN, - ending_rx=API_COVERAGE_HEADING_PATTERN, - replacement_block=pro_table, - ) - - if updated_doc != original_doc: - args.md_file.write_text(updated_doc) - - -if __name__ == "__main__": - main()