diff --git a/config/groups.go b/config/groups.go index 38974fc94c..f839f59aa8 100644 --- a/config/groups.go +++ b/config/groups.go @@ -48,11 +48,9 @@ func ReplaceGroupWords(group string, count int) GroupKindCalculator { // GroupMap contains all overrides we'd like to make to the default group search. // It's written with data from TF Provider AWS repo service grouping in here: // https://github.com/hashicorp/terraform-provider-aws/tree/main/internal/service +// which is itself based on the AWS Go SDK. // -// At the end, all of them are based on grouping of the AWS Go SDK. -// The initial grouping is calculated based on folder grouping of AWS TF Provider -// which is based on Go SDK. Here is the script used to fetch that list: -// https://gist.github.com/muvaf/8d61365ffc1df7757864422ba16d7819 +// The map is generated by using the shell and python scripts in the `scripts` directory. var GroupMap = map[string]GroupKindCalculator{ "aws_alb_listener_certificate": ReplaceGroupWords("elbv2", 0), "aws_alb_listener_rule": ReplaceGroupWords("elbv2", 0), @@ -98,9 +96,11 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_cloudwatch_event_bus_policy": ReplaceGroupWords("cloudwatchevents", 2), "aws_cloudwatch_event_bus": ReplaceGroupWords("cloudwatchevents", 2), "aws_cloudwatch_event_connection": ReplaceGroupWords("cloudwatchevents", 2), + "aws_cloudwatch_event_endpoint": ReplaceGroupWords("cloudwatchevents", 2), "aws_cloudwatch_event_permission": ReplaceGroupWords("cloudwatchevents", 2), "aws_cloudwatch_event_rule": ReplaceGroupWords("cloudwatchevents", 2), "aws_cloudwatch_event_target": ReplaceGroupWords("cloudwatchevents", 2), + "aws_cloudwatch_log_data_protection_policy": ReplaceGroupWords("cloudwatchlogs", 2), "aws_cloudwatch_log_destination_policy": ReplaceGroupWords("cloudwatchlogs", 2), "aws_cloudwatch_log_destination": ReplaceGroupWords("cloudwatchlogs", 2), "aws_cloudwatch_log_group": ReplaceGroupWords("cloudwatchlogs", 2), @@ -108,15 +108,16 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_cloudwatch_log_resource_policy": ReplaceGroupWords("cloudwatchlogs", 2), "aws_cloudwatch_log_stream": ReplaceGroupWords("cloudwatchlogs", 2), "aws_cloudwatch_log_subscription_filter": ReplaceGroupWords("cloudwatchlogs", 2), - "aws_cloudwatch_query_definition": ReplaceGroupWords("cloudwatchlogs", 2), + "aws_cloudwatch_query_definition": ReplaceGroupWords("cloudwatchlogs", 1), "aws_codedeploy_app": ReplaceGroupWords("deploy", 1), "aws_codedeploy_deployment_config": ReplaceGroupWords("deploy", 1), "aws_codedeploy_deployment_group": ReplaceGroupWords("deploy", 1), "aws_codepipeline": ReplaceGroupWords("codepipeline", 0), - "aws_cognito_identity_pool_provider_principal_tag": ReplaceGroupWords("cognitoidentity", 0), + "aws_cognito_identity_pool_provider_principal_tag": ReplaceGroupWords("cognitoidentity", 2), "aws_cognito_identity_pool_roles_attachment": ReplaceGroupWords("cognitoidentity", 2), "aws_cognito_identity_pool": ReplaceGroupWords("cognitoidentity", 2), "aws_cognito_identity_provider": ReplaceGroupWords("cognitoidp", 1), + "aws_cognito_managed_user_pool_client": ReplaceGroupWords("cognitoidp", 1), "aws_cognito_resource_server": ReplaceGroupWords("cognitoidp", 1), "aws_cognito_risk_configuration": ReplaceGroupWords("cognitoidp", 1), "aws_cognito_user_group": ReplaceGroupWords("cognitoidp", 1), @@ -134,13 +135,15 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_config_conformance_pack": ReplaceGroupWords("configservice", 1), "aws_config_delivery_channel": ReplaceGroupWords("configservice", 1), "aws_config_organization_conformance_pack": ReplaceGroupWords("configservice", 1), + "aws_config_organization_custom_policy_rule": ReplaceGroupWords("configservice", 1), "aws_config_organization_custom_rule": ReplaceGroupWords("configservice", 1), "aws_config_organization_managed_rule": ReplaceGroupWords("configservice", 1), "aws_config_remediation_configuration": ReplaceGroupWords("configservice", 1), + "aws_config_retention_configuration": ReplaceGroupWords("configservice", 1), "aws_customer_gateway": ReplaceGroupWords("ec2", 0), "aws_db_cluster_snapshot": ReplaceGroupWords("rds", 1), "aws_db_event_subscription": ReplaceGroupWords("rds", 1), - "aws_db_instance_automated_backups_replication": ReplaceGroupWords("rds", 0), + "aws_db_instance_automated_backups_replication": ReplaceGroupWords("rds", 1), "aws_db_instance_role_association": ReplaceGroupWords("rds", 1), "aws_db_instance": ReplaceGroupWords("rds", 1), "aws_db_option_group": ReplaceGroupWords("rds", 1), @@ -149,7 +152,7 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_db_proxy_endpoint": ReplaceGroupWords("rds", 1), "aws_db_proxy_target": ReplaceGroupWords("rds", 1), "aws_db_proxy": ReplaceGroupWords("rds", 1), - "aws_db_snapshot_copy": ReplaceGroupWords("rds", 0), + "aws_db_snapshot_copy": ReplaceGroupWords("rds", 1), "aws_db_snapshot": ReplaceGroupWords("rds", 1), "aws_db_subnet_group": ReplaceGroupWords("rds", 1), "aws_default_network_acl": ReplaceGroupWords("ec2", 0), @@ -161,8 +164,11 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_directory_service_conditional_forwarder": ReplaceGroupWords("ds", 2), "aws_directory_service_directory": ReplaceGroupWords("ds", 2), "aws_directory_service_log_subscription": ReplaceGroupWords("ds", 2), + "aws_directory_service_radius_settings": ReplaceGroupWords("ds", 2), + "aws_directory_service_region": ReplaceGroupWords("ds", 2), "aws_directory_service_shared_directory_accepter": ReplaceGroupWords("ds", 2), "aws_directory_service_shared_directory": ReplaceGroupWords("ds", 2), + "aws_directory_service_trust": ReplaceGroupWords("ds", 2), "aws_dx_bgp_peer": ReplaceGroupWords("directconnect", 1), "aws_dx_connection_association": ReplaceGroupWords("directconnect", 1), "aws_dx_connection_confirmation": ReplaceGroupWords("directconnect", 1), @@ -178,11 +184,13 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_dx_hosted_transit_virtual_interface_accepter": ReplaceGroupWords("directconnect", 1), "aws_dx_hosted_transit_virtual_interface": ReplaceGroupWords("directconnect", 1), "aws_dx_lag": ReplaceGroupWords("directconnect", 1), + "aws_dx_macsec_key_association": ReplaceGroupWords("directconnect", 0), "aws_dx_private_virtual_interface": ReplaceGroupWords("directconnect", 1), "aws_dx_public_virtual_interface": ReplaceGroupWords("directconnect", 1), "aws_dx_transit_virtual_interface": ReplaceGroupWords("directconnect", 1), "aws_ebs_default_kms_key": ReplaceGroupWords("ec2", 0), "aws_ebs_encryption_by_default": ReplaceGroupWords("ec2", 0), + "aws_ebs_fast_snapshot_restore": ReplaceGroupWords("ec2", 0), "aws_ebs_snapshot_copy": ReplaceGroupWords("ec2", 0), "aws_ebs_snapshot_import": ReplaceGroupWords("ec2", 0), "aws_ebs_snapshot": ReplaceGroupWords("ec2", 0), @@ -212,6 +220,8 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_lb_ssl_negotiation_policy": ReplaceGroupWords("elb", 0), "aws_lb_target_group_attachment": ReplaceGroupWords("elbv2", 0), "aws_lb_target_group": ReplaceGroupWords("elbv2", 0), + "aws_lb_trust_store_revocation": ReplaceGroupWords("elbv2", 0), + "aws_lb_trust_store": ReplaceGroupWords("elbv2", 0), "aws_lb": ReplaceGroupWords("elbv2", 0), "aws_lex_bot_alias": ReplaceGroupWords("lexmodels", 1), "aws_lex_bot": ReplaceGroupWords("lexmodels", 1), @@ -225,10 +235,13 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_media_package_channel": ReplaceGroupWords("mediapackage", 2), "aws_media_store_container_policy": ReplaceGroupWords("mediastore", 2), "aws_media_store_container": ReplaceGroupWords("mediastore", 2), + "aws_msk_cluster_policy": ReplaceGroupWords("kafka", 1), "aws_msk_cluster": ReplaceGroupWords("kafka", 1), "aws_msk_configuration": ReplaceGroupWords("kafka", 1), + "aws_msk_replicator": ReplaceGroupWords("kafka", 1), "aws_msk_scram_secret_association": ReplaceGroupWords("kafka", 1), "aws_msk_serverless_cluster": ReplaceGroupWords("kafka", 1), + "aws_msk_vpc_connection": ReplaceGroupWords("kafka", 1), "aws_mskconnect_connector": ReplaceGroupWords("kafkaconnect", 1), "aws_mskconnect_custom_plugin": ReplaceGroupWords("kafkaconnect", 1), "aws_mskconnect_worker_configuration": ReplaceGroupWords("kafkaconnect", 1), @@ -242,11 +255,9 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_placement_group": ReplaceGroupWords("ec2", 0), "aws_prometheus_alert_manager_definition": ReplaceGroupWords("amp", 1), "aws_prometheus_rule_group_namespace": ReplaceGroupWords("amp", 1), + "aws_prometheus_scraper": ReplaceGroupWords("amp", 1), "aws_prometheus_workspace": ReplaceGroupWords("amp", 1), "aws_proxy_protocol_policy": ReplaceGroupWords("elb", 0), - "aws_route_table_association": ReplaceGroupWords("ec2", 0), - "aws_route_table": ReplaceGroupWords("ec2", 0), - "aws_route": ReplaceGroupWords("ec2", 0), "aws_route53_resolver_dnssec_config": ReplaceGroupWords("route53resolver", 2), "aws_route53_resolver_endpoint": ReplaceGroupWords("route53resolver", 2), "aws_route53_resolver_firewall_config": ReplaceGroupWords("route53resolver", 2), @@ -258,6 +269,9 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_route53_resolver_query_log_config": ReplaceGroupWords("route53resolver", 2), "aws_route53_resolver_rule_association": ReplaceGroupWords("route53resolver", 2), "aws_route53_resolver_rule": ReplaceGroupWords("route53resolver", 2), + "aws_route_table_association": ReplaceGroupWords("ec2", 0), + "aws_route_table": ReplaceGroupWords("ec2", 0), + "aws_route": ReplaceGroupWords("ec2", 0), "aws_s3_access_point": ReplaceGroupWords("s3control", 1), "aws_s3_account_public_access_block": ReplaceGroupWords("s3control", 1), "aws_security_group_rule": ReplaceGroupWords("ec2", 0), @@ -273,6 +287,12 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_spot_fleet_request": ReplaceGroupWords("ec2", 0), "aws_spot_instance_request": ReplaceGroupWords("ec2", 0), "aws_subnet": ReplaceGroupWords("ec2", 0), + "aws_verifiedaccess_endpoint": ReplaceGroupWords("ec2", 0), + "aws_verifiedaccess_group": ReplaceGroupWords("ec2", 0), + "aws_verifiedaccess_instance_logging_configuration": ReplaceGroupWords("ec2", 0), + "aws_verifiedaccess_instance_trust_provider_attachment": ReplaceGroupWords("ec2", 0), + "aws_verifiedaccess_instance": ReplaceGroupWords("ec2", 0), + "aws_verifiedaccess_trust_provider": ReplaceGroupWords("ec2", 0), "aws_volume_attachment": ReplaceGroupWords("ec2", 0), "aws_vpc_dhcp_options_association": ReplaceGroupWords("ec2", 0), "aws_vpc_dhcp_options": ReplaceGroupWords("ec2", 0), @@ -290,15 +310,17 @@ var GroupMap = map[string]GroupKindCalculator{ "aws_vpc_ipam_pool_cidr": ReplaceGroupWords("ec2", 0), "aws_vpc_ipam_pool": ReplaceGroupWords("ec2", 0), "aws_vpc_ipam_preview_next_cidr": ReplaceGroupWords("ec2", 0), + "aws_vpc_ipam_resource_discovery_association": ReplaceGroupWords("ec2", 0), + "aws_vpc_ipam_resource_discovery": ReplaceGroupWords("ec2", 0), "aws_vpc_ipam_scope": ReplaceGroupWords("ec2", 0), "aws_vpc_ipam": ReplaceGroupWords("ec2", 0), - "aws_vpc_security_group_egress_rule": ReplaceGroupWords("ec2", 0), - "aws_vpc_security_group_ingress_rule": ReplaceGroupWords("ec2", 0), "aws_vpc_ipv4_cidr_block_association": ReplaceGroupWords("ec2", 0), "aws_vpc_ipv6_cidr_block_association": ReplaceGroupWords("ec2", 0), "aws_vpc_peering_connection_accepter": ReplaceGroupWords("ec2", 0), "aws_vpc_peering_connection_options": ReplaceGroupWords("ec2", 0), "aws_vpc_peering_connection": ReplaceGroupWords("ec2", 0), + "aws_vpc_security_group_egress_rule": ReplaceGroupWords("ec2", 0), + "aws_vpc_security_group_ingress_rule": ReplaceGroupWords("ec2", 0), "aws_vpc": ReplaceGroupWords("ec2", 0), "aws_vpn_connection_route": ReplaceGroupWords("ec2", 0), "aws_vpn_connection": ReplaceGroupWords("ec2", 0), @@ -313,4 +335,10 @@ var KindMap = map[string]string{ "aws_cloudformation_type": "CloudFormationType", "aws_cloudtrail": "Trail", "aws_config_configuration_recorder_status": "AWSConfigurationRecorderStatus", + // These would be better unmodified, but they were given non-standard names due to a bug in the + // handwritten GroupMap, and renaming them now would be a breaking change. + "aws_cloudwatch_query_definition": "Definition", + "aws_cognito_identity_pool_provider_principal_tag": "CognitoIdentityPoolProviderPrincipalTag", + "aws_db_instance_automated_backups_replication": "DBInstanceAutomatedBackupsReplication", + "aws_db_snapshot_copy": "DBSnapshotCopy", } diff --git a/scripts/gen-api-group-exceptions.py b/scripts/gen-api-group-exceptions.py new file mode 100644 index 0000000000..b69e831052 --- /dev/null +++ b/scripts/gen-api-group-exceptions.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +from functools import cmp_to_key + + +# First run gen-tf-resource-list.sh to generate the list of sdk and framework resources +# from the source code of terraform-provider-aws. Then run this script to generate the +# contents of the GroupMap in config/groups.go. +def find_exceptions(filename: str): + needs_change = [] + with open(filename) as f: + resources = f.readlines() + for r in resources: + line = r.strip().split(" ") + if len(line) != 3: + raise Exception(f"Invalid line: {r}") + [aws_group, tf_filename, tf_resource_name] = line + + # Some customizations for places where terraform-provider-aws is inconsistent, or where this provider + # was inconsistent in the past and we need to keep that inconsistency to avoid a breaking change. + + # This resource is in the route53resolver SDK group, but it's in the route53 crossplane provider api group, + # because of a bug in the previous manually-maintained mapping. + if tf_resource_name == "aws_route53_resolver_config": + continue + + # This resource is in the ec2 SDK group, but it's in the vpc crossplane provider api group (and it's the only + # resource in that group) + if tf_resource_name == "aws_vpc_network_performance_metric_subscription": + continue + + # terraform-provider-aws doesn't use the same group names as the AWS SDKs for cloudwatch logs and events + if aws_group in ["logs", "events"]: + aws_group = "cloudwatch" + aws_group + + # The vpc ipam resources don't include "vpc_" in their filenames, but it is in the terraform resource name + if tf_filename.startswith("ipam_"): + tf_filename = "vpc_" + tf_filename + + # Some of the ec2 resources have filenames like "ec2_.go" and others are just ".go" + if aws_group == "ec2" and tf_filename.startswith("ec2_"): + tf_filename = tf_filename.removeprefix("ec2_") + # terraform-provider-aws uses tag_gen.go as a filename for generated resources that implement tag-like behavior, + # and are named "tag" + if tf_filename == "tag_gen": + tf_filename = "tag" + + name = tf_resource_name.removeprefix("aws_") + if name.endswith(tf_filename): + calculated_group = name.removesuffix(tf_filename).removesuffix("_") + elif aws_group == "ec2" and name.startswith("ec2_"): + # Several ec2 resources have filenames like transitgateway_policy_table.go, and a resource name like + # transit_gateway_policy_table. + calculated_group = "ec2" + else: + # These are mostly the really old resources like "aws_subnet" that predate the concept of api groups + calculated_group = "" + words_to_drop = len([w for w in calculated_group.split("_") if w]) + if aws_group == "elbv2" and tf_resource_name.startswith("aws_lb"): + # The elbv2 resources currently all have a kind that starts with LB, so we need to not drop that word. + words_to_drop = 0 + if aws_group != calculated_group: + needs_change.append([tf_resource_name, aws_group, words_to_drop]) + return needs_change + + +# python and golang differ in their sorting behavior when one string is a prefix of another. Implement the golang order. +# hacked together to only sort lists by their first element, which is a string. +@cmp_to_key +def golang_cmp(a, b): + if a[0] == b[0]: + return 0 + if a[0].startswith(b[0]): + return -1 + if b[0].startswith(a[0]): + return 1 + return 1 if a > b else -1 + + +if __name__ == "__main__": + exceptions = find_exceptions("../hack/sdk-resources.lst") + exceptions.extend(find_exceptions("../hack/framework-resources.lst")) + exceptions.sort(key=golang_cmp) + for l in exceptions: + [tf_resource_name, aws_group, drop] = l + print(f'"{tf_resource_name}": ReplaceGroupWords("{aws_group}", {drop}),') + + + + diff --git a/scripts/gen-tf-resource-lists.sh b/scripts/gen-tf-resource-lists.sh new file mode 100755 index 0000000000..108ef00e41 --- /dev/null +++ b/scripts/gen-tf-resource-lists.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +XP_PROVIDER_PATH=`pwd` + +cd $TF_PROVIDER_PATH/internal/service +git grep -l '@FrameworkResource' | xargs grep '\.TypeName = "aws_' | sed -n 's|\([^/]*\)/\(\w*\)\.go:.*"\(aws_[a-z0-9_]*\)".*|\1 \2 \3|p' > $XP_PROVIDER_PATH/hack/framework-resources.lst +git grep '// @SDKResource("aws' | sed -n 's|\([^/]*\)/\(\w*\)\.go:// @SDKResource(.\([a-z0-9_]*\).*|\1 \2 \3|p' > $XP_PROVIDER_PATH/hack/sdk-resources.lst \ No newline at end of file